aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/i2c/v1.rs131
1 files changed, 73 insertions, 58 deletions
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index be7f91a9a..5c57a9ccc 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -142,7 +142,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
142 return Err(Error::Arbitration); 142 return Err(Error::Arbitration);
143 } 143 }
144 144
145 // Set up current address, we're trying to talk to 145 // Set up current address we're trying to talk to
146 T::regs().dr().write(|reg| reg.set_dr(addr << 1)); 146 T::regs().dr().write(|reg| reg.set_dr(addr << 1));
147 147
148 // Wait until address was sent 148 // Wait until address was sent
@@ -235,7 +235,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
235 return Err(Error::Arbitration); 235 return Err(Error::Arbitration);
236 } 236 }
237 237
238 // Set up current address, we're trying to talk to 238 // Set up current address we're trying to talk to
239 T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)); 239 T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1));
240 240
241 // Wait until address was sent 241 // Wait until address was sent
@@ -331,27 +331,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
331 where 331 where
332 TXDMA: crate::i2c::TxDma<T>, 332 TXDMA: crate::i2c::TxDma<T>,
333 { 333 {
334 let dma_transfer = unsafe { 334 T::regs().cr2().modify(|w| {
335 let regs = T::regs(); 335 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
336 regs.cr2().modify(|w| { 336 // reception.
337 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for reception. 337 w.set_itbufen(false);
338 w.set_itbufen(false); 338 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2
339 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2 register. 339 // register.
340 w.set_dmaen(true); 340 w.set_dmaen(true);
341 // Sending NACK is not necessary (nor possible) for write transfer. 341 // Sending NACK is not necessary (nor possible) for write transfer.
342 w.set_last(false); 342 w.set_last(false);
343 }); 343 });
344 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to this address from the memory after each TxE event.
345 let dst = regs.dr().as_ptr() as *mut u8;
346
347 let ch = &mut self.tx_dma;
348 let request = ch.request();
349 Transfer::new_write(ch, request, write, dst, Default::default())
350 };
351 344
345 // Sentinel to disable transfer when an error occurs or future is canceled.
346 // TODO: Generate STOP condition on cancel?
352 let on_drop = OnDrop::new(|| { 347 let on_drop = OnDrop::new(|| {
353 let regs = T::regs(); 348 T::regs().cr2().modify(|w| {
354 regs.cr2().modify(|w| {
355 w.set_dmaen(false); 349 w.set_dmaen(false);
356 w.set_iterren(false); 350 w.set_iterren(false);
357 w.set_itevten(false); 351 w.set_itevten(false);
@@ -390,7 +384,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
390 return Err(Error::Arbitration); 384 return Err(Error::Arbitration);
391 } 385 }
392 386
393 // Set up current address, we're trying to talk to 387 // Set up current address we're trying to talk to
394 T::regs().dr().write(|reg| reg.set_dr(address << 1)); 388 T::regs().dr().write(|reg| reg.set_dr(address << 1));
395 389
396 // Wait for the address to be acknowledged 390 // Wait for the address to be acknowledged
@@ -416,14 +410,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
416 T::regs().sr2().read(); 410 T::regs().sr2().read();
417 } 411 }
418 412
413 let dma_transfer = unsafe {
414 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to
415 // this address from the memory after each TxE event.
416 let dst = T::regs().dr().as_ptr() as *mut u8;
417
418 let ch = &mut self.tx_dma;
419 let request = ch.request();
420 Transfer::new_write(ch, request, write, dst, Default::default())
421 };
422
419 // Wait for bytes to be sent, or an error to occur. 423 // Wait for bytes to be sent, or an error to occur.
420 let poll_error = poll_fn(|cx| { 424 let poll_error = poll_fn(|cx| {
421 state.waker.register(cx.waker()); 425 state.waker.register(cx.waker());
422 426
423 match Self::check_and_clear_error_flags() { 427 match Self::check_and_clear_error_flags() {
424 // Unclear why the Err turbofish is necessary here? The compiler didn’t require it in the other 428 Err(e) => Poll::Ready(Err::<(), Error>(e)),
425 // identical poll_fn check_and_clear matches.
426 Err(e) => Poll::Ready(Err::<T, Error>(e)),
427 Ok(_) => { 429 Ok(_) => {
428 // When pending, (re-)enable interrupts to wake us up. 430 // When pending, (re-)enable interrupts to wake us up.
429 Self::enable_interrupts(); 431 Self::enable_interrupts();
@@ -502,31 +504,30 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
502 where 504 where
503 RXDMA: crate::i2c::RxDma<T>, 505 RXDMA: crate::i2c::RxDma<T>,
504 { 506 {
505 let buffer_len = buffer.len(); 507 if buffer.is_empty() {
508 return Err(Error::Overrun);
509 }
506 510
507 let dma_transfer = unsafe { 511 // Some branches below depend on whether the buffer contains only a single byte.
508 let regs = T::regs(); 512 let single_byte = buffer.len() == 1;
509 regs.cr2().modify(|w| {
510 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for reception.
511 w.set_itbufen(false);
512 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2 register.
513 w.set_dmaen(true);
514 // If, in the I2C_CR2 register, the LAST bit is set, I2C
515 // automatically sends a NACK after the next byte following EOT_1. The user can
516 // generate a Stop condition in the DMA Transfer Complete interrupt routine if enabled.
517 w.set_last(frame.send_nack() && buffer_len != 1);
518 });
519 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to this address from the memory after each TxE event.
520 let src = regs.dr().as_ptr() as *mut u8;
521 513
522 let ch = &mut self.rx_dma; 514 T::regs().cr2().modify(|w| {
523 let request = ch.request(); 515 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
524 Transfer::new_read(ch, request, src, buffer, Default::default()) 516 // reception.
525 }; 517 w.set_itbufen(false);
518 // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2
519 // register.
520 w.set_dmaen(true);
521 // If, in the I2C_CR2 register, the LAST bit is set, I2C automatically sends a NACK
522 // after the next byte following EOT_1. The user can generate a Stop condition in
523 // the DMA Transfer Complete interrupt routine if enabled.
524 w.set_last(frame.send_nack() && !single_byte);
525 });
526 526
527 // Sentinel to disable transfer when an error occurs or future is canceled.
528 // TODO: Generate STOP condition on cancel?
527 let on_drop = OnDrop::new(|| { 529 let on_drop = OnDrop::new(|| {
528 let regs = T::regs(); 530 T::regs().cr2().modify(|w| {
529 regs.cr2().modify(|w| {
530 w.set_dmaen(false); 531 w.set_dmaen(false);
531 w.set_iterren(false); 532 w.set_iterren(false);
532 w.set_itevten(false); 533 w.set_itevten(false);
@@ -566,7 +567,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
566 return Err(Error::Arbitration); 567 return Err(Error::Arbitration);
567 } 568 }
568 569
569 // Set up current address, we're trying to talk to 570 // Set up current address we're trying to talk to
570 T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1)); 571 T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1));
571 572
572 // Wait for the address to be acknowledged 573 // Wait for the address to be acknowledged
@@ -590,7 +591,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
590 591
591 // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6 592 // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6
592 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. 593 // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag.
593 if frame.send_nack() && buffer_len == 1 { 594 if frame.send_nack() && single_byte {
594 T::regs().cr1().modify(|w| { 595 T::regs().cr1().modify(|w| {
595 w.set_ack(false); 596 w.set_ack(false);
596 }); 597 });
@@ -598,27 +599,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
598 599
599 // Clear condition by reading SR2 600 // Clear condition by reading SR2
600 T::regs().sr2().read(); 601 T::regs().sr2().read();
601 } else if frame.send_nack() && buffer_len == 1 { 602 } else {
602 T::regs().cr1().modify(|w| { 603 // Before starting reception of single byte (but without START condition, i.e. in case
603 w.set_ack(false); 604 // of continued frame), program NACK to emit at end of this byte.
604 }); 605 if frame.send_nack() && single_byte {
606 T::regs().cr1().modify(|w| {
607 w.set_ack(false);
608 });
609 }
605 } 610 }
606 611
607 // 18.3.8: When a single byte must be received: [snip] Then the 612 // 18.3.8: When a single byte must be received: [snip] Then the user can program the STOP
608 // user can program the STOP condition either after clearing ADDR flag, or in the 613 // condition either after clearing ADDR flag, or in the DMA Transfer Complete interrupt
609 // DMA Transfer Complete interrupt routine. 614 // routine.
610 if frame.send_stop() && buffer_len == 1 { 615 if frame.send_stop() && single_byte {
611 T::regs().cr1().modify(|w| { 616 T::regs().cr1().modify(|w| {
612 w.set_stop(true); 617 w.set_stop(true);
613 }); 618 });
614 } 619 }
615 620
621 let dma_transfer = unsafe {
622 // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved
623 // from this address from the memory after each RxE event.
624 let src = T::regs().dr().as_ptr() as *mut u8;
625
626 let ch = &mut self.rx_dma;
627 let request = ch.request();
628 Transfer::new_read(ch, request, src, buffer, Default::default())
629 };
630
616 // Wait for bytes to be received, or an error to occur. 631 // Wait for bytes to be received, or an error to occur.
617 let poll_error = poll_fn(|cx| { 632 let poll_error = poll_fn(|cx| {
618 state.waker.register(cx.waker()); 633 state.waker.register(cx.waker());
619 634
620 match Self::check_and_clear_error_flags() { 635 match Self::check_and_clear_error_flags() {
621 Err(e) => Poll::Ready(Err::<T, Error>(e)), 636 Err(e) => Poll::Ready(Err::<(), Error>(e)),
622 _ => { 637 _ => {
623 // When pending, (re-)enable interrupts to wake us up. 638 // When pending, (re-)enable interrupts to wake us up.
624 Self::enable_interrupts(); 639 Self::enable_interrupts();
@@ -636,7 +651,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
636 w.set_dmaen(false); 651 w.set_dmaen(false);
637 }); 652 });
638 653
639 if frame.send_stop() && buffer_len != 1 { 654 if frame.send_stop() && !single_byte {
640 T::regs().cr1().modify(|w| { 655 T::regs().cr1().modify(|w| {
641 w.set_stop(true); 656 w.set_stop(true);
642 }); 657 });