aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf
diff options
context:
space:
mode:
authorAlex Moon <[email protected]>2024-08-14 17:07:57 -0400
committerAlex Moon <[email protected]>2024-10-23 16:44:07 -0400
commit528a3e43550b5d2ce4a5f44d890feaa3e56c113a (patch)
tree8d1c9b7c14d21178cc0932d1c773efd2c63ca656 /embassy-nrf
parent8803128707b8bd9fc9dcea392a62dfd42aa822d2 (diff)
Add support for transactions to Twim in embassy-nrf
Diffstat (limited to 'embassy-nrf')
-rw-r--r--embassy-nrf/src/twim.rs621
1 files changed, 377 insertions, 244 deletions
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index c64743ecc..d0518807c 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -4,6 +4,7 @@
4 4
5use core::future::{poll_fn, Future}; 5use core::future::{poll_fn, Future};
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::mem::MaybeUninit;
7use core::sync::atomic::compiler_fence; 8use core::sync::atomic::compiler_fence;
8use core::sync::atomic::Ordering::SeqCst; 9use core::sync::atomic::Ordering::SeqCst;
9use core::task::Poll; 10use core::task::Poll;
@@ -13,11 +14,12 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
13use embassy_sync::waitqueue::AtomicWaker; 14use embassy_sync::waitqueue::AtomicWaker;
14#[cfg(feature = "time")] 15#[cfg(feature = "time")]
15use embassy_time::{Duration, Instant}; 16use embassy_time::{Duration, Instant};
17use embedded_hal_1::i2c::Operation;
16 18
17use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 19use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
18use crate::gpio::Pin as GpioPin; 20use crate::gpio::Pin as GpioPin;
19use crate::interrupt::typelevel::Interrupt; 21use crate::interrupt::typelevel::Interrupt;
20use crate::util::{slice_in_ram, slice_in_ram_or}; 22use crate::util::slice_in_ram;
21use crate::{gpio, interrupt, pac, Peripheral}; 23use crate::{gpio, interrupt, pac, Peripheral};
22 24
23/// TWI frequency 25/// TWI frequency
@@ -103,6 +105,18 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
103 let r = T::regs(); 105 let r = T::regs();
104 let s = T::state(); 106 let s = T::state();
105 107
108 // Workaround for lack of LASTRX_SUSPEND short in some nRF chips
109 // Do this first to minimize latency
110 #[cfg(any(feature = "nrf52832", feature = "_nrf5340", feature = "_nrf9120"))]
111 if r.events_lastrx.read().bits() != 0 {
112 r.tasks_suspend.write(|w| unsafe { w.bits(1) });
113 r.events_lastrx.reset();
114 }
115
116 if r.events_suspended.read().bits() != 0 {
117 s.end_waker.wake();
118 r.intenclr.write(|w| w.suspended().clear());
119 }
106 if r.events_stopped.read().bits() != 0 { 120 if r.events_stopped.read().bits() != 0 {
107 s.end_waker.wake(); 121 s.end_waker.wake();
108 r.intenclr.write(|w| w.stopped().clear()); 122 r.intenclr.write(|w| w.stopped().clear());
@@ -182,8 +196,22 @@ impl<'d, T: Instance> Twim<'d, T> {
182 } 196 }
183 197
184 /// Set TX buffer, checking that it is in RAM and has suitable length. 198 /// Set TX buffer, checking that it is in RAM and has suitable length.
185 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { 199 unsafe fn set_tx_buffer(
186 slice_in_ram_or(buffer, Error::BufferNotInRAM)?; 200 &mut self,
201 buffer: &[u8],
202 ram_buffer: Option<&mut [MaybeUninit<u8>; FORCE_COPY_BUFFER_SIZE]>,
203 ) -> Result<(), Error> {
204 let buffer = if slice_in_ram(buffer) {
205 buffer
206 } else {
207 let ram_buffer = ram_buffer.ok_or(Error::BufferNotInRAM)?;
208 trace!("Copying TWIM tx buffer into RAM for DMA");
209 let ram_buffer = &mut ram_buffer[..buffer.len()];
210 // Inline implementation of the nightly API MaybeUninit::copy_from_slice(ram_buffer, buffer)
211 let uninit_src: &[MaybeUninit<u8>] = unsafe { core::mem::transmute(buffer) };
212 ram_buffer.copy_from_slice(uninit_src);
213 unsafe { &*(ram_buffer as *const [MaybeUninit<u8>] as *const [u8]) }
214 };
187 215
188 if buffer.len() > EASY_DMA_SIZE { 216 if buffer.len() > EASY_DMA_SIZE {
189 return Err(Error::TxBufferTooLong); 217 return Err(Error::TxBufferTooLong);
@@ -290,7 +318,7 @@ impl<'d, T: Instance> Twim<'d, T> {
290 fn blocking_wait(&mut self) { 318 fn blocking_wait(&mut self) {
291 let r = T::regs(); 319 let r = T::regs();
292 loop { 320 loop {
293 if r.events_stopped.read().bits() != 0 { 321 if r.events_suspended.read().bits() != 0 || r.events_stopped.read().bits() != 0 {
294 r.events_stopped.reset(); 322 r.events_stopped.reset();
295 break; 323 break;
296 } 324 }
@@ -307,7 +335,7 @@ impl<'d, T: Instance> Twim<'d, T> {
307 let r = T::regs(); 335 let r = T::regs();
308 let deadline = Instant::now() + timeout; 336 let deadline = Instant::now() + timeout;
309 loop { 337 loop {
310 if r.events_stopped.read().bits() != 0 { 338 if r.events_suspended.read().bits() != 0 || r.events_stopped.read().bits() != 0 {
311 r.events_stopped.reset(); 339 r.events_stopped.reset();
312 break; 340 break;
313 } 341 }
@@ -331,7 +359,7 @@ impl<'d, T: Instance> Twim<'d, T> {
331 let s = T::state(); 359 let s = T::state();
332 360
333 s.end_waker.register(cx.waker()); 361 s.end_waker.register(cx.waker());
334 if r.events_stopped.read().bits() != 0 { 362 if r.events_suspended.read().bits() != 0 || r.events_stopped.read().bits() != 0 {
335 r.events_stopped.reset(); 363 r.events_stopped.reset();
336 364
337 return Poll::Ready(()); 365 return Poll::Ready(());
@@ -347,168 +375,357 @@ impl<'d, T: Instance> Twim<'d, T> {
347 }) 375 })
348 } 376 }
349 377
350 fn setup_write_from_ram(&mut self, address: u8, buffer: &[u8], inten: bool) -> Result<(), Error> { 378 fn setup_operations(
379 &mut self,
380 address: u8,
381 operations: &mut [Operation<'_>],
382 tx_ram_buffer: Option<&mut [MaybeUninit<u8>; FORCE_COPY_BUFFER_SIZE]>,
383 inten: bool,
384 stop: bool,
385 ) -> Result<(), Error> {
351 let r = T::regs(); 386 let r = T::regs();
352 387
353 compiler_fence(SeqCst); 388 compiler_fence(SeqCst);
354 389
355 r.address.write(|w| unsafe { w.address().bits(address) }); 390 r.address.write(|w| unsafe { w.address().bits(address) });
356 391
357 // Set up the DMA write. 392 let was_suspended = r.events_suspended.read().bits() != 0;
358 unsafe { self.set_tx_buffer(buffer)? }; 393 r.events_suspended.reset();
359
360 // Clear events
361 r.events_stopped.reset(); 394 r.events_stopped.reset();
362 r.events_error.reset(); 395 r.events_error.reset();
363 r.events_lasttx.reset();
364 self.clear_errorsrc(); 396 self.clear_errorsrc();
365 397
366 if inten { 398 if inten {
367 r.intenset.write(|w| w.stopped().set().error().set()); 399 r.intenset.write(|w| w.suspended().set().stopped().set().error().set());
368 } else { 400 } else {
369 r.intenclr.write(|w| w.stopped().clear().error().clear()); 401 r.intenclr
402 .write(|w| w.suspended().clear().stopped().clear().error().clear());
370 } 403 }
404 #[cfg(any(feature = "nrf52832", feature = "_nrf5340", feature = "_nrf9120"))]
405 r.intenclr.write(|w| w.lastrx().clear());
406
407 match operations {
408 [Operation::Read(rd_buffer), Operation::Write(wr_buffer), rest @ ..]
409 if !rd_buffer.is_empty() && !wr_buffer.is_empty() =>
410 {
411 let stop = stop && rest.is_empty();
412
413 // Set up DMA buffers.
414 unsafe {
415 self.set_tx_buffer(wr_buffer, tx_ram_buffer)?;
416 self.set_rx_buffer(rd_buffer)?;
417 }
371 418
372 // Start write operation. 419 r.shorts.write(|w| {
373 r.shorts.write(|w| w.lasttx_stop().enabled()); 420 w.lastrx_starttx().enabled();
374 r.tasks_starttx.write(|w| unsafe { w.bits(1) }); 421 if stop {
375 if buffer.is_empty() { 422 w.lasttx_stop().enabled();
376 // With a zero-length buffer, LASTTX doesn't fire (because there's no last byte!), so do the STOP ourselves. 423 } else {
377 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 424 w.lasttx_suspend().enabled();
378 } 425 }
379 Ok(()) 426 w
380 } 427 });
428
429 // Start read+write operation.
430 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
431
432 if was_suspended {
433 r.tasks_resume.write(|w| unsafe { w.bits(1) });
434 }
435 }
436 [Operation::Write(wr_buffer), Operation::Read(rd_buffer), rest @ ..]
437 if !wr_buffer.is_empty() && !rd_buffer.is_empty() =>
438 {
439 let stop = stop && rest.is_empty();
440
441 // Set up DMA buffers.
442 unsafe {
443 self.set_tx_buffer(wr_buffer, tx_ram_buffer)?;
444 self.set_rx_buffer(rd_buffer)?;
445 }
381 446
382 fn setup_read(&mut self, address: u8, buffer: &mut [u8], inten: bool) -> Result<(), Error> { 447 // Start write+read operation.
383 let r = T::regs(); 448 r.shorts.write(|w| {
449 w.lasttx_startrx().enabled();
450 if stop {
451 w.lastrx_stop().enabled();
452 } else {
453 #[cfg(not(any(feature = "nrf52832", feature = "_nrf5340", feature = "_nrf9120")))]
454 w.lastrx_suspend().enabled();
455 }
456 w
457 });
458 #[cfg(any(feature = "nrf52832", feature = "_nrf5340", feature = "_nrf9120"))]
459 if !stop {
460 r.intenset.write(|w| w.lastrx().set());
461 }
384 462
385 compiler_fence(SeqCst); 463 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
386 464
387 r.address.write(|w| unsafe { w.address().bits(address) }); 465 if was_suspended {
466 r.tasks_resume.write(|w| unsafe { w.bits(1) });
467 }
468 }
469 [Operation::Read(buffer), rest @ ..] => {
470 let stop = stop && rest.is_empty();
388 471
389 // Set up the DMA read. 472 // Set up DMA buffers.
390 unsafe { self.set_rx_buffer(buffer)? }; 473 unsafe {
474 self.set_rx_buffer(buffer)?;
475 }
391 476
392 // Clear events 477 // Start read operation.
393 r.events_stopped.reset(); 478 r.shorts.write(|w| {
394 r.events_error.reset(); 479 if stop {
395 self.clear_errorsrc(); 480 w.lastrx_stop().enabled();
481 } else {
482 #[cfg(not(any(feature = "nrf52832", feature = "_nrf5340", feature = "_nrf9120")))]
483 w.lastrx_suspend().enabled();
484 }
485 w
486 });
487 #[cfg(any(feature = "nrf52832", feature = "_nrf5340", feature = "_nrf9120"))]
488 if !stop {
489 r.intenset.write(|w| w.lastrx().set());
490 }
396 491
397 if inten { 492 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
398 r.intenset.write(|w| w.stopped().set().error().set());
399 } else {
400 r.intenclr.write(|w| w.stopped().clear().error().clear());
401 }
402 493
403 // Start read operation. 494 if was_suspended {
404 r.shorts.write(|w| w.lastrx_stop().enabled()); 495 r.tasks_resume.write(|w| unsafe { w.bits(1) });
405 r.tasks_startrx.write(|w| unsafe { w.bits(1) }); 496 }
406 if buffer.is_empty() { 497
407 // With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STOP ourselves. 498 if buffer.is_empty() {
408 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 499 // With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STOP/SUSPEND ourselves.
500 if stop {
501 r.tasks_stop.write(|w| unsafe { w.bits(1) });
502 } else {
503 r.tasks_suspend.write(|w| unsafe { w.bits(1) });
504 }
505 }
506 }
507 [Operation::Write(buffer), rest @ ..] => {
508 let stop = stop && rest.is_empty();
509
510 // Set up DMA buffers.
511 unsafe {
512 self.set_tx_buffer(buffer, tx_ram_buffer)?;
513 }
514
515 // Start write operation.
516 r.shorts.write(|w| {
517 if stop {
518 w.lasttx_stop().enabled();
519 } else {
520 w.lasttx_suspend().enabled();
521 }
522 w
523 });
524
525 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
526
527 if was_suspended {
528 r.tasks_resume.write(|w| unsafe { w.bits(1) });
529 }
530
531 if buffer.is_empty() {
532 // With a zero-length buffer, LASTTX doesn't fire (because there's no last byte!), so do the STOP/SUSPEND ourselves.
533 if stop {
534 r.tasks_stop.write(|w| unsafe { w.bits(1) });
535 } else {
536 r.tasks_suspend.write(|w| unsafe { w.bits(1) });
537 }
538 }
539 }
540 [] => {
541 if stop {
542 if was_suspended {
543 r.tasks_resume.write(|w| unsafe { w.bits(1) });
544 }
545
546 r.tasks_stop.write(|w| unsafe { w.bits(1) });
547 }
548 }
409 } 549 }
550
410 Ok(()) 551 Ok(())
411 } 552 }
412 553
413 fn setup_write_read_from_ram( 554 fn check_operations(&mut self, operations: &mut [Operation<'_>]) -> Result<usize, Error> {
414 &mut self,
415 address: u8,
416 wr_buffer: &[u8],
417 rd_buffer: &mut [u8],
418 inten: bool,
419 ) -> Result<(), Error> {
420 let r = T::regs();
421
422 compiler_fence(SeqCst); 555 compiler_fence(SeqCst);
556 self.check_errorsrc()?;
423 557
424 r.address.write(|w| unsafe { w.address().bits(address) }); 558 match operations {
425 559 [Operation::Read(rd_buffer), Operation::Write(wr_buffer), ..]
426 // Set up DMA buffers. 560 | [Operation::Write(wr_buffer), Operation::Read(rd_buffer), ..]
427 unsafe { 561 if !rd_buffer.is_empty() && !wr_buffer.is_empty() =>
428 self.set_tx_buffer(wr_buffer)?; 562 {
429 self.set_rx_buffer(rd_buffer)?; 563 self.check_tx(wr_buffer.len())?;
564 self.check_rx(rd_buffer.len())?;
565 Ok(2)
566 }
567 [Operation::Read(buffer), ..] => {
568 self.check_rx(buffer.len())?;
569 Ok(1)
570 }
571 [Operation::Write(buffer), ..] => {
572 self.check_tx(buffer.len())?;
573 Ok(1)
574 }
575 [] => Ok(0),
430 } 576 }
577 }
431 578
432 // Clear events 579 // ===========================================
433 r.events_stopped.reset();
434 r.events_error.reset();
435 self.clear_errorsrc();
436 580
437 if inten { 581 /// Execute the provided operations on the I2C bus.
438 r.intenset.write(|w| w.stopped().set().error().set()); 582 ///
439 } else { 583 /// Each buffer must have a length of at most 255 bytes on the nRF52832
440 r.intenclr.write(|w| w.stopped().clear().error().clear()); 584 /// and at most 65535 bytes on the nRF52840.
585 ///
586 /// If `stop` is set, the transaction will be terminated with a STOP
587 /// condition and the Twim will be stopped. Otherwise, the bus will be
588 /// left busy via clock stretching and Twim will be suspended.
589 ///
590 /// The nrf52832, nrf5340, and nrf9120 do not have hardware support for
591 /// suspending following a read operation therefore it is emulated by the
592 /// interrupt handler. If the latency of servicing that interrupt is
593 /// longer than a byte worth of clocks on the bus, the SCL clock will
594 /// continue to run for one or more additional bytes. This applies to
595 /// consecutive read operations, certain write-read-write sequences, or
596 /// any sequence of operations ending in a read when `stop == false`.
597 pub fn blocking_transaction(
598 &mut self,
599 address: u8,
600 mut operations: &mut [Operation<'_>],
601 stop: bool,
602 ) -> Result<(), Error> {
603 let mut tx_ram_buffer = [MaybeUninit::uninit(); FORCE_COPY_BUFFER_SIZE];
604 while !operations.is_empty() {
605 self.setup_operations(address, operations, Some(&mut tx_ram_buffer), false, stop)?;
606 self.blocking_wait();
607 let consumed = self.check_operations(operations)?;
608 operations = &mut operations[consumed..];
609 }
610 Ok(())
611 }
612
613 /// Same as [`blocking_transaction`](Twim::blocking_transaction) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
614 pub fn blocking_transaction_from_ram(
615 &mut self,
616 address: u8,
617 mut operations: &mut [Operation<'_>],
618 stop: bool,
619 ) -> Result<(), Error> {
620 while !operations.is_empty() {
621 self.setup_operations(address, operations, None, false, stop)?;
622 self.blocking_wait();
623 let consumed = self.check_operations(operations)?;
624 operations = &mut operations[consumed..];
441 } 625 }
626 Ok(())
627 }
442 628
443 // Start write+read operation. 629 /// Execute the provided operations on the I2C bus with timeout.
444 r.shorts.write(|w| { 630 ///
445 w.lasttx_startrx().enabled(); 631 /// See [`blocking_transaction`].
446 w.lastrx_stop().enabled(); 632 #[cfg(feature = "time")]
447 w 633 pub fn blocking_transaction_timeout(
448 }); 634 &mut self,
449 r.tasks_starttx.write(|w| unsafe { w.bits(1) }); 635 address: u8,
450 if wr_buffer.is_empty() && rd_buffer.is_empty() { 636 mut operations: &mut [Operation<'_>],
451 // With a zero-length buffer, LASTRX/LASTTX doesn't fire (because there's no last byte!), so do the STOP ourselves. 637 stop: bool,
452 // TODO handle when only one of the buffers is zero length 638 timeout: Duration,
453 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 639 ) -> Result<(), Error> {
640 let mut tx_ram_buffer = [MaybeUninit::uninit(); FORCE_COPY_BUFFER_SIZE];
641 while !operations.is_empty() {
642 self.setup_operations(address, operations, Some(&mut tx_ram_buffer), false, stop)?;
643 self.blocking_wait_timeout(timeout)?;
644 let consumed = self.check_operations(operations)?;
645 operations = &mut operations[consumed..];
454 } 646 }
647 Ok(())
648 }
455 649
650 /// Same as [`blocking_transaction_timeout`](Twim::blocking_transaction_timeout) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
651 #[cfg(feature = "time")]
652 pub fn blocking_transaction_from_ram_timeout(
653 &mut self,
654 address: u8,
655 mut operations: &mut [Operation<'_>],
656 stop: bool,
657 timeout: Duration,
658 ) -> Result<(), Error> {
659 while !operations.is_empty() {
660 self.setup_operations(address, operations, None, false, stop)?;
661 self.blocking_wait_timeout(timeout)?;
662 let consumed = self.check_operations(operations)?;
663 operations = &mut operations[consumed..];
664 }
456 Ok(()) 665 Ok(())
457 } 666 }
458 667
459 fn setup_write_read( 668 /// Execute the provided operations on the I2C bus.
669 ///
670 /// Each buffer must have a length of at most 255 bytes on the nRF52832
671 /// and at most 65535 bytes on the nRF52840.
672 ///
673 /// If `stop` is set, the transaction will be terminated with a STOP
674 /// condition and the Twim will be stopped. Otherwise, the bus will be
675 /// left busy via clock stretching and Twim will be suspended.
676 ///
677 /// The nrf52832, nrf5340, and nrf9120 do not have hardware support for
678 /// suspending following a read operation therefore it is emulated by the
679 /// interrupt handler. If the latency of servicing that interrupt is
680 /// longer than a byte worth of clocks on the bus, the SCL clock will
681 /// continue to run for one or more additional bytes. This applies to
682 /// consecutive read operations, certain write-read-write sequences, or
683 /// any sequence of operations ending in a read when `stop == false`.
684 pub async fn transaction(
460 &mut self, 685 &mut self,
461 address: u8, 686 address: u8,
462 wr_buffer: &[u8], 687 mut operations: &mut [Operation<'_>],
463 rd_buffer: &mut [u8], 688 stop: bool,
464 inten: bool,
465 ) -> Result<(), Error> { 689 ) -> Result<(), Error> {
466 match self.setup_write_read_from_ram(address, wr_buffer, rd_buffer, inten) { 690 let mut tx_ram_buffer = [MaybeUninit::uninit(); FORCE_COPY_BUFFER_SIZE];
467 Ok(_) => Ok(()), 691 while !operations.is_empty() {
468 Err(Error::BufferNotInRAM) => { 692 self.setup_operations(address, operations, Some(&mut tx_ram_buffer), true, stop)?;
469 trace!("Copying TWIM tx buffer into RAM for DMA"); 693 self.async_wait().await;
470 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; 694 let consumed = self.check_operations(operations)?;
471 tx_ram_buf.copy_from_slice(wr_buffer); 695 operations = &mut operations[consumed..];
472 self.setup_write_read_from_ram(address, tx_ram_buf, rd_buffer, inten)
473 }
474 Err(error) => Err(error),
475 } 696 }
697 Ok(())
476 } 698 }
477 699
478 fn setup_write(&mut self, address: u8, wr_buffer: &[u8], inten: bool) -> Result<(), Error> { 700 /// Same as [`transaction`](Twim::transaction) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
479 match self.setup_write_from_ram(address, wr_buffer, inten) { 701 pub async fn transaction_from_ram(
480 Ok(_) => Ok(()), 702 &mut self,
481 Err(Error::BufferNotInRAM) => { 703 address: u8,
482 trace!("Copying TWIM tx buffer into RAM for DMA"); 704 mut operations: &mut [Operation<'_>],
483 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; 705 stop: bool,
484 tx_ram_buf.copy_from_slice(wr_buffer); 706 ) -> Result<(), Error> {
485 self.setup_write_from_ram(address, tx_ram_buf, inten) 707 while !operations.is_empty() {
486 } 708 self.setup_operations(address, operations, None, true, stop)?;
487 Err(error) => Err(error), 709 self.async_wait().await;
710 let consumed = self.check_operations(operations)?;
711 operations = &mut operations[consumed..];
488 } 712 }
713 Ok(())
489 } 714 }
490 715
716 // ===========================================
717
491 /// Write to an I2C slave. 718 /// Write to an I2C slave.
492 /// 719 ///
493 /// The buffer must have a length of at most 255 bytes on the nRF52832 720 /// The buffer must have a length of at most 255 bytes on the nRF52832
494 /// and at most 65535 bytes on the nRF52840. 721 /// and at most 65535 bytes on the nRF52840.
495 pub fn blocking_write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { 722 pub fn blocking_write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
496 self.setup_write(address, buffer, false)?; 723 self.blocking_transaction(address, &mut [Operation::Write(buffer)], true)
497 self.blocking_wait();
498 compiler_fence(SeqCst);
499 self.check_errorsrc()?;
500 self.check_tx(buffer.len())?;
501 Ok(())
502 } 724 }
503 725
504 /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. 726 /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
505 pub fn blocking_write_from_ram(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { 727 pub fn blocking_write_from_ram(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
506 self.setup_write_from_ram(address, buffer, false)?; 728 self.blocking_transaction_from_ram(address, &mut [Operation::Write(buffer)], true)
507 self.blocking_wait();
508 compiler_fence(SeqCst);
509 self.check_errorsrc()?;
510 self.check_tx(buffer.len())?;
511 Ok(())
512 } 729 }
513 730
514 /// Read from an I2C slave. 731 /// Read from an I2C slave.
@@ -516,12 +733,7 @@ impl<'d, T: Instance> Twim<'d, T> {
516 /// The buffer must have a length of at most 255 bytes on the nRF52832 733 /// The buffer must have a length of at most 255 bytes on the nRF52832
517 /// and at most 65535 bytes on the nRF52840. 734 /// and at most 65535 bytes on the nRF52840.
518 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 735 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
519 self.setup_read(address, buffer, false)?; 736 self.blocking_transaction(address, &mut [Operation::Read(buffer)], true)
520 self.blocking_wait();
521 compiler_fence(SeqCst);
522 self.check_errorsrc()?;
523 self.check_rx(buffer.len())?;
524 Ok(())
525 } 737 }
526 738
527 /// Write data to an I2C slave, then read data from the slave without 739 /// Write data to an I2C slave, then read data from the slave without
@@ -530,13 +742,11 @@ impl<'d, T: Instance> Twim<'d, T> {
530 /// The buffers must have a length of at most 255 bytes on the nRF52832 742 /// The buffers must have a length of at most 255 bytes on the nRF52832
531 /// and at most 65535 bytes on the nRF52840. 743 /// and at most 65535 bytes on the nRF52840.
532 pub fn blocking_write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> { 744 pub fn blocking_write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> {
533 self.setup_write_read(address, wr_buffer, rd_buffer, false)?; 745 self.blocking_transaction(
534 self.blocking_wait(); 746 address,
535 compiler_fence(SeqCst); 747 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
536 self.check_errorsrc()?; 748 true,
537 self.check_tx(wr_buffer.len())?; 749 )
538 self.check_rx(rd_buffer.len())?;
539 Ok(())
540 } 750 }
541 751
542 /// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. 752 /// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
@@ -546,13 +756,11 @@ impl<'d, T: Instance> Twim<'d, T> {
546 wr_buffer: &[u8], 756 wr_buffer: &[u8],
547 rd_buffer: &mut [u8], 757 rd_buffer: &mut [u8],
548 ) -> Result<(), Error> { 758 ) -> Result<(), Error> {
549 self.setup_write_read_from_ram(address, wr_buffer, rd_buffer, false)?; 759 self.blocking_transaction_from_ram(
550 self.blocking_wait(); 760 address,
551 compiler_fence(SeqCst); 761 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
552 self.check_errorsrc()?; 762 true,
553 self.check_tx(wr_buffer.len())?; 763 )
554 self.check_rx(rd_buffer.len())?;
555 Ok(())
556 } 764 }
557 765
558 // =========================================== 766 // ===========================================
@@ -562,12 +770,7 @@ impl<'d, T: Instance> Twim<'d, T> {
562 /// See [`blocking_write`]. 770 /// See [`blocking_write`].
563 #[cfg(feature = "time")] 771 #[cfg(feature = "time")]
564 pub fn blocking_write_timeout(&mut self, address: u8, buffer: &[u8], timeout: Duration) -> Result<(), Error> { 772 pub fn blocking_write_timeout(&mut self, address: u8, buffer: &[u8], timeout: Duration) -> Result<(), Error> {
565 self.setup_write(address, buffer, false)?; 773 self.blocking_transaction_timeout(address, &mut [Operation::Write(buffer)], true, timeout)
566 self.blocking_wait_timeout(timeout)?;
567 compiler_fence(SeqCst);
568 self.check_errorsrc()?;
569 self.check_tx(buffer.len())?;
570 Ok(())
571 } 774 }
572 775
573 /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. 776 /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
@@ -578,12 +781,7 @@ impl<'d, T: Instance> Twim<'d, T> {
578 buffer: &[u8], 781 buffer: &[u8],
579 timeout: Duration, 782 timeout: Duration,
580 ) -> Result<(), Error> { 783 ) -> Result<(), Error> {
581 self.setup_write_from_ram(address, buffer, false)?; 784 self.blocking_transaction_from_ram_timeout(address, &mut [Operation::Write(buffer)], true, timeout)
582 self.blocking_wait_timeout(timeout)?;
583 compiler_fence(SeqCst);
584 self.check_errorsrc()?;
585 self.check_tx(buffer.len())?;
586 Ok(())
587 } 785 }
588 786
589 /// Read from an I2C slave. 787 /// Read from an I2C slave.
@@ -592,12 +790,7 @@ impl<'d, T: Instance> Twim<'d, T> {
592 /// and at most 65535 bytes on the nRF52840. 790 /// and at most 65535 bytes on the nRF52840.
593 #[cfg(feature = "time")] 791 #[cfg(feature = "time")]
594 pub fn blocking_read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> { 792 pub fn blocking_read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> {
595 self.setup_read(address, buffer, false)?; 793 self.blocking_transaction_timeout(address, &mut [Operation::Read(buffer)], true, timeout)
596 self.blocking_wait_timeout(timeout)?;
597 compiler_fence(SeqCst);
598 self.check_errorsrc()?;
599 self.check_rx(buffer.len())?;
600 Ok(())
601 } 794 }
602 795
603 /// Write data to an I2C slave, then read data from the slave without 796 /// Write data to an I2C slave, then read data from the slave without
@@ -613,13 +806,12 @@ impl<'d, T: Instance> Twim<'d, T> {
613 rd_buffer: &mut [u8], 806 rd_buffer: &mut [u8],
614 timeout: Duration, 807 timeout: Duration,
615 ) -> Result<(), Error> { 808 ) -> Result<(), Error> {
616 self.setup_write_read(address, wr_buffer, rd_buffer, false)?; 809 self.blocking_transaction_timeout(
617 self.blocking_wait_timeout(timeout)?; 810 address,
618 compiler_fence(SeqCst); 811 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
619 self.check_errorsrc()?; 812 true,
620 self.check_tx(wr_buffer.len())?; 813 timeout,
621 self.check_rx(rd_buffer.len())?; 814 )
622 Ok(())
623 } 815 }
624 816
625 /// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. 817 /// Same as [`blocking_write_read`](Twim::blocking_write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
@@ -631,13 +823,12 @@ impl<'d, T: Instance> Twim<'d, T> {
631 rd_buffer: &mut [u8], 823 rd_buffer: &mut [u8],
632 timeout: Duration, 824 timeout: Duration,
633 ) -> Result<(), Error> { 825 ) -> Result<(), Error> {
634 self.setup_write_read_from_ram(address, wr_buffer, rd_buffer, false)?; 826 self.blocking_transaction_from_ram_timeout(
635 self.blocking_wait_timeout(timeout)?; 827 address,
636 compiler_fence(SeqCst); 828 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
637 self.check_errorsrc()?; 829 true,
638 self.check_tx(wr_buffer.len())?; 830 timeout,
639 self.check_rx(rd_buffer.len())?; 831 )
640 Ok(())
641 } 832 }
642 833
643 // =========================================== 834 // ===========================================
@@ -647,12 +838,7 @@ impl<'d, T: Instance> Twim<'d, T> {
647 /// The buffer must have a length of at most 255 bytes on the nRF52832 838 /// The buffer must have a length of at most 255 bytes on the nRF52832
648 /// and at most 65535 bytes on the nRF52840. 839 /// and at most 65535 bytes on the nRF52840.
649 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 840 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
650 self.setup_read(address, buffer, true)?; 841 self.transaction(address, &mut [Operation::Read(buffer)], true).await
651 self.async_wait().await;
652 compiler_fence(SeqCst);
653 self.check_errorsrc()?;
654 self.check_rx(buffer.len())?;
655 Ok(())
656 } 842 }
657 843
658 /// Write to an I2C slave. 844 /// Write to an I2C slave.
@@ -660,22 +846,13 @@ impl<'d, T: Instance> Twim<'d, T> {
660 /// The buffer must have a length of at most 255 bytes on the nRF52832 846 /// The buffer must have a length of at most 255 bytes on the nRF52832
661 /// and at most 65535 bytes on the nRF52840. 847 /// and at most 65535 bytes on the nRF52840.
662 pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { 848 pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
663 self.setup_write(address, buffer, true)?; 849 self.transaction(address, &mut [Operation::Write(buffer)], true).await
664 self.async_wait().await;
665 compiler_fence(SeqCst);
666 self.check_errorsrc()?;
667 self.check_tx(buffer.len())?;
668 Ok(())
669 } 850 }
670 851
671 /// Same as [`write`](Twim::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. 852 /// Same as [`write`](Twim::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
672 pub async fn write_from_ram(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { 853 pub async fn write_from_ram(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
673 self.setup_write_from_ram(address, buffer, true)?; 854 self.transaction_from_ram(address, &mut [Operation::Write(buffer)], true)
674 self.async_wait().await; 855 .await
675 compiler_fence(SeqCst);
676 self.check_errorsrc()?;
677 self.check_tx(buffer.len())?;
678 Ok(())
679 } 856 }
680 857
681 /// Write data to an I2C slave, then read data from the slave without 858 /// Write data to an I2C slave, then read data from the slave without
@@ -684,13 +861,12 @@ impl<'d, T: Instance> Twim<'d, T> {
684 /// The buffers must have a length of at most 255 bytes on the nRF52832 861 /// The buffers must have a length of at most 255 bytes on the nRF52832
685 /// and at most 65535 bytes on the nRF52840. 862 /// and at most 65535 bytes on the nRF52840.
686 pub async fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> { 863 pub async fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> {
687 self.setup_write_read(address, wr_buffer, rd_buffer, true)?; 864 self.transaction(
688 self.async_wait().await; 865 address,
689 compiler_fence(SeqCst); 866 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
690 self.check_errorsrc()?; 867 true,
691 self.check_tx(wr_buffer.len())?; 868 )
692 self.check_rx(rd_buffer.len())?; 869 .await
693 Ok(())
694 } 870 }
695 871
696 /// Same as [`write_read`](Twim::write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. 872 /// Same as [`write_read`](Twim::write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
@@ -700,13 +876,12 @@ impl<'d, T: Instance> Twim<'d, T> {
700 wr_buffer: &[u8], 876 wr_buffer: &[u8],
701 rd_buffer: &mut [u8], 877 rd_buffer: &mut [u8],
702 ) -> Result<(), Error> { 878 ) -> Result<(), Error> {
703 self.setup_write_read_from_ram(address, wr_buffer, rd_buffer, true)?; 879 self.transaction_from_ram(
704 self.async_wait().await; 880 address,
705 compiler_fence(SeqCst); 881 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
706 self.check_errorsrc()?; 882 true,
707 self.check_tx(wr_buffer.len())?; 883 )
708 self.check_rx(rd_buffer.len())?; 884 .await
709 Ok(())
710 } 885 }
711} 886}
712 887
@@ -777,16 +952,7 @@ mod eh02 {
777 type Error = Error; 952 type Error = Error;
778 953
779 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { 954 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
780 if slice_in_ram(bytes) { 955 self.blocking_write(addr, bytes)
781 self.blocking_write(addr, bytes)
782 } else {
783 let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..];
784 for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) {
785 buf[..chunk.len()].copy_from_slice(chunk);
786 self.blocking_write(addr, &buf[..chunk.len()])?;
787 }
788 Ok(())
789 }
790 } 956 }
791 } 957 }
792 958
@@ -832,47 +998,14 @@ impl<'d, T: Instance> embedded_hal_1::i2c::ErrorType for Twim<'d, T> {
832} 998}
833 999
834impl<'d, T: Instance> embedded_hal_1::i2c::I2c for Twim<'d, T> { 1000impl<'d, T: Instance> embedded_hal_1::i2c::I2c for Twim<'d, T> {
835 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 1001 fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
836 self.blocking_read(address, buffer) 1002 self.blocking_transaction(address, operations, true)
837 }
838
839 fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> {
840 self.blocking_write(address, buffer)
841 }
842
843 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
844 self.blocking_write_read(address, wr_buffer, rd_buffer)
845 }
846
847 fn transaction(
848 &mut self,
849 _address: u8,
850 _operations: &mut [embedded_hal_1::i2c::Operation<'_>],
851 ) -> Result<(), Self::Error> {
852 todo!();
853 } 1003 }
854} 1004}
855 1005
856impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> { 1006impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
857 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 1007 async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
858 self.read(address, read).await 1008 self.transaction(address, operations, true).await
859 }
860
861 async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
862 self.write(address, write).await
863 }
864 async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
865 self.write_read(address, write, read).await
866 }
867
868 async fn transaction(
869 &mut self,
870 address: u8,
871 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
872 ) -> Result<(), Self::Error> {
873 let _ = address;
874 let _ = operations;
875 todo!()
876 } 1009 }
877} 1010}
878 1011