1#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::sync::atomic::Ordering::SeqCst;
8use core::sync::atomic::compiler_fence;
9use core::task::Poll;
10
11use embassy_embedded_hal::SetConfig;
12use embassy_hal_internal::{Peri, PeripheralType};
13use embassy_sync::waitqueue::AtomicWaker;
14#[cfg(feature = "time")]
15use embassy_time::{Duration, Instant};
16use embedded_hal_1::i2c::Operation;
17pub use pac::twim::vals::Frequency;
18
19use crate::chip::EASY_DMA_SIZE;
20use crate::gpio::Pin as GpioPin;
21use crate::interrupt::typelevel::Interrupt;
22use crate::pac::gpio::vals as gpiovals;
23use crate::pac::twim::vals;
24use crate::util::slice_in_ram;
25use crate::{gpio, interrupt, pac};
26
27#[non_exhaustive]
29pub struct Config {
30 pub frequency: Frequency,
32
33 pub sda_high_drive: bool,
35
36 pub sda_pullup: bool,
41
42 pub scl_high_drive: bool,
44
45 pub scl_pullup: bool,
50}
51
52impl Default for Config {
53 fn default() -> Self {
54 Self {
55 frequency: Frequency::K100,
56 scl_high_drive: false,
57 sda_pullup: false,
58 sda_high_drive: false,
59 scl_pullup: false,
60 }
61 }
62}
63
64#[derive(Debug, Copy, Clone, Eq, PartialEq)]
66#[cfg_attr(feature = "defmt", derive(defmt::Format))]
67#[non_exhaustive]
68pub enum Error {
69 TxBufferTooLong,
71 RxBufferTooLong,
73 Transmit,
75 Receive,
77 RAMBufferTooSmall,
79 AddressNack,
81 DataNack,
83 Overrun,
85 Timeout,
87}
88
89pub struct InterruptHandler<T: Instance> {
91 _phantom: PhantomData<T>,
92}
93
94impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
95 unsafe fn on_interrupt() {
96 let r = T::regs();
97 let s = T::state();
98
99 if r.events_suspended().read() != 0 {
100 s.end_waker.wake();
101 r.intenclr().write(|w| w.set_suspended(true));
102 }
103 if r.events_stopped().read() != 0 {
104 s.end_waker.wake();
105 r.intenclr().write(|w| w.set_stopped(true));
106 }
107 if r.events_error().read() != 0 {
108 s.end_waker.wake();
109 r.intenclr().write(|w| w.set_error(true));
110 }
111 }
112}
113
114pub struct Twim<'d> {
116 r: pac::twim::Twim,
117 state: &'static State,
118 tx_ram_buffer: &'d mut [u8],
119 _p: PhantomData<&'d ()>,
120}
121
122impl<'d> Twim<'d> {
123 pub fn new<T: Instance>(
131 _twim: Peri<'d, T>,
132 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
133 sda: Peri<'d, impl GpioPin>,
134 scl: Peri<'d, impl GpioPin>,
135 config: Config,
136 tx_ram_buffer: &'d mut [u8],
137 ) -> Self {
138 let r = T::regs();
139
140 sda.conf().write(|w| {
142 w.set_dir(gpiovals::Dir::OUTPUT);
143 w.set_input(gpiovals::Input::CONNECT);
144 #[cfg(not(feature = "_nrf54l"))]
145 w.set_drive(match config.sda_high_drive {
146 true => gpiovals::Drive::H0D1,
147 false => gpiovals::Drive::S0D1,
148 });
149 #[cfg(feature = "_nrf54l")]
150 {
151 w.set_drive0(match config.sda_high_drive {
152 true => gpiovals::Drive::H,
153 false => gpiovals::Drive::S,
154 });
155 w.set_drive1(gpiovals::Drive::D);
156 }
157 if config.sda_pullup {
158 w.set_pull(gpiovals::Pull::PULLUP);
159 }
160 });
161 scl.conf().write(|w| {
162 w.set_dir(gpiovals::Dir::OUTPUT);
163 w.set_input(gpiovals::Input::CONNECT);
164 #[cfg(not(feature = "_nrf54l"))]
165 w.set_drive(match config.scl_high_drive {
166 true => gpiovals::Drive::H0D1,
167 false => gpiovals::Drive::S0D1,
168 });
169 #[cfg(feature = "_nrf54l")]
170 {
171 w.set_drive0(match config.scl_high_drive {
172 true => gpiovals::Drive::H,
173 false => gpiovals::Drive::S,
174 });
175 w.set_drive1(gpiovals::Drive::D);
176 }
177 if config.scl_pullup {
178 w.set_pull(gpiovals::Pull::PULLUP);
179 }
180 });
181
182 r.psel().sda().write_value(sda.psel_bits());
184 r.psel().scl().write_value(scl.psel_bits());
185
186 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
188
189 let mut twim = Self {
190 r: T::regs(),
191 state: T::state(),
192 tx_ram_buffer,
193 _p: PhantomData {},
194 };
195
196 Self::set_config(&mut twim, &config).unwrap();
198
199 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
201
202 T::Interrupt::unpend();
203 unsafe { T::Interrupt::enable() };
204
205 twim
206 }
207
208 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
210 let buffer = if slice_in_ram(buffer) {
211 buffer
212 } else {
213 if buffer.len() > self.tx_ram_buffer.len() {
214 return Err(Error::RAMBufferTooSmall);
215 }
216 trace!("Copying TWIM tx buffer into RAM for DMA");
217 let ram_buffer = &mut self.tx_ram_buffer[..buffer.len()];
218 ram_buffer.copy_from_slice(buffer);
219 &*ram_buffer
220 };
221
222 if buffer.len() > EASY_DMA_SIZE {
223 return Err(Error::TxBufferTooLong);
224 }
225
226 let r = self.r;
227
228 r.dma().tx().ptr().write_value(buffer.as_ptr() as u32);
232 r.dma().tx().maxcnt().write(|w|
233 w.set_maxcnt(buffer.len() as _));
240
241 Ok(())
242 }
243
244 unsafe fn set_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
246 if buffer.len() > EASY_DMA_SIZE {
250 return Err(Error::RxBufferTooLong);
251 }
252
253 let r = self.r;
254
255 r.dma().rx().ptr().write_value(buffer.as_mut_ptr() as u32);
259 r.dma().rx().maxcnt().write(|w|
260 w.set_maxcnt(buffer.len() as _));
270
271 Ok(())
272 }
273
274 fn clear_errorsrc(&mut self) {
275 let r = self.r;
276 r.errorsrc().write(|w| {
277 w.set_anack(true);
278 w.set_dnack(true);
279 w.set_overrun(true);
280 });
281 }
282
283 fn check_errorsrc(&mut self) -> Result<(), Error> {
285 let r = self.r;
286
287 let err = r.errorsrc().read();
288 if err.anack() {
289 return Err(Error::AddressNack);
290 }
291 if err.dnack() {
292 return Err(Error::DataNack);
293 }
294 if err.overrun() {
295 return Err(Error::Overrun);
296 }
297 Ok(())
298 }
299
300 fn check_rx(&self, len: usize) -> Result<(), Error> {
301 let r = self.r;
302 if r.dma().rx().amount().read().0 != len as u32 {
303 Err(Error::Receive)
304 } else {
305 Ok(())
306 }
307 }
308
309 fn check_tx(&self, len: usize) -> Result<(), Error> {
310 let r = self.r;
311 if r.dma().tx().amount().read().0 != len as u32 {
312 Err(Error::Transmit)
313 } else {
314 Ok(())
315 }
316 }
317
318 fn blocking_wait(&mut self) {
320 let r = self.r;
321 loop {
322 if r.events_suspended().read() != 0 || r.events_stopped().read() != 0 {
323 r.events_suspended().write_value(0);
324 r.events_stopped().write_value(0);
325 break;
326 }
327 if r.events_error().read() != 0 {
328 r.events_error().write_value(0);
329 r.tasks_stop().write_value(1);
330 }
331 }
332 }
333
334 #[cfg(feature = "time")]
336 fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<(), Error> {
337 let r = self.r;
338 let deadline = Instant::now() + timeout;
339 loop {
340 if r.events_suspended().read() != 0 || r.events_stopped().read() != 0 {
341 r.events_stopped().write_value(0);
342 break;
343 }
344 if r.events_error().read() != 0 {
345 r.events_error().write_value(0);
346 r.tasks_stop().write_value(1);
347 }
348 if Instant::now() > deadline {
349 r.tasks_stop().write_value(1);
350 return Err(Error::Timeout);
351 }
352 }
353
354 Ok(())
355 }
356
357 async fn async_wait(&mut self) -> Result<(), Error> {
359 poll_fn(|cx| {
360 let r = self.r;
361 let s = self.state;
362
363 s.end_waker.register(cx.waker());
364 if r.events_suspended().read() != 0 || r.events_stopped().read() != 0 {
365 r.events_stopped().write_value(0);
366
367 return Poll::Ready(Ok(()));
368 }
369
370 if r.events_error().read() != 0 {
372 r.events_error().write_value(0);
373 r.tasks_stop().write_value(1);
374 if let Err(e) = self.check_errorsrc() {
375 return Poll::Ready(Err(e));
376 } else {
377 return Poll::Ready(Err(Error::Timeout));
378 }
379 }
380
381 Poll::Pending
382 })
383 .await
384 }
385
386 fn setup_operations(
387 &mut self,
388 address: u8,
389 operations: &mut [Operation<'_>],
390 last_op: Option<&Operation<'_>>,
391 inten: bool,
392 ) -> Result<usize, Error> {
393 let r = self.r;
394
395 compiler_fence(SeqCst);
396
397 r.address().write(|w| w.set_address(address));
398
399 r.events_suspended().write_value(0);
400 r.events_stopped().write_value(0);
401 r.events_error().write_value(0);
402 self.clear_errorsrc();
403
404 if inten {
405 r.intenset().write(|w| {
406 w.set_suspended(true);
407 w.set_stopped(true);
408 w.set_error(true);
409 });
410 } else {
411 r.intenclr().write(|w| {
412 w.set_suspended(true);
413 w.set_stopped(true);
414 w.set_error(true);
415 });
416 }
417
418 assert!(!operations.is_empty());
419 match operations {
420 [Operation::Read(_), Operation::Read(_), ..] => {
421 panic!("Consecutive read operations are not supported!")
422 }
423 [Operation::Read(rd_buffer), Operation::Write(wr_buffer), rest @ ..] => {
424 let stop = rest.is_empty();
425
426 unsafe {
428 self.set_tx_buffer(wr_buffer)?;
429 self.set_rx_buffer(rd_buffer)?;
430 }
431
432 r.shorts().write(|w| {
433 w.set_lastrx_dma_tx_start(true);
434 if stop {
435 w.set_lasttx_stop(true);
436 } else {
437 w.set_lasttx_suspend(true);
438 }
439 });
440
441 r.tasks_dma().rx().start().write_value(1);
443 if last_op.is_some() {
444 r.tasks_resume().write_value(1);
445 }
446
447 if rd_buffer.is_empty() {
449 r.tasks_dma().tx().start().write_value(1);
451 }
452
453 Ok(2)
454 }
455 [Operation::Read(buffer)] => {
456 unsafe {
458 self.set_rx_buffer(buffer)?;
459 }
460
461 r.shorts().write(|w| w.set_lastrx_stop(true));
462
463 r.tasks_dma().rx().start().write_value(1);
465 if last_op.is_some() {
466 r.tasks_resume().write_value(1);
467 }
468
469 if buffer.is_empty() {
470 r.tasks_stop().write_value(1);
472 }
473
474 Ok(1)
475 }
476 [Operation::Write(wr_buffer), Operation::Read(rd_buffer)]
477 if !wr_buffer.is_empty() && !rd_buffer.is_empty() =>
478 {
479 unsafe {
481 self.set_tx_buffer(wr_buffer)?;
482 self.set_rx_buffer(rd_buffer)?;
483 }
484
485 r.shorts().write(|w| {
487 w.set_lasttx_dma_rx_start(true);
488 w.set_lastrx_stop(true);
489 });
490
491 r.tasks_dma().tx().start().write_value(1);
492 if last_op.is_some() {
493 r.tasks_resume().write_value(1);
494 }
495
496 Ok(2)
497 }
498 [Operation::Write(buffer), rest @ ..] => {
499 let stop = rest.is_empty();
500
501 unsafe {
503 self.set_tx_buffer(buffer)?;
504 }
505
506 r.shorts().write(|w| {
508 if stop {
509 w.set_lasttx_stop(true);
510 } else {
511 w.set_lasttx_suspend(true);
512 }
513 });
514
515 r.tasks_dma().tx().start().write_value(1);
516 if last_op.is_some() {
517 r.tasks_resume().write_value(1);
518 }
519
520 if buffer.is_empty() {
521 if stop {
523 r.tasks_stop().write_value(1);
524 } else {
525 r.tasks_suspend().write_value(1);
526 }
527 }
528
529 Ok(1)
530 }
531 [] => unreachable!(),
532 }
533 }
534
535 fn check_operations(&mut self, operations: &[Operation<'_>]) -> Result<(), Error> {
536 compiler_fence(SeqCst);
537 self.check_errorsrc()?;
538
539 assert!(operations.len() == 1 || operations.len() == 2);
540 match operations {
541 [Operation::Read(rd_buffer), Operation::Write(wr_buffer)]
542 | [Operation::Write(wr_buffer), Operation::Read(rd_buffer)] => {
543 self.check_rx(rd_buffer.len())?;
544 self.check_tx(wr_buffer.len())?;
545 }
546 [Operation::Read(buffer)] => {
547 self.check_rx(buffer.len())?;
548 }
549 [Operation::Write(buffer), ..] => {
550 self.check_tx(buffer.len())?;
551 }
552 _ => unreachable!(),
553 }
554 Ok(())
555 }
556
557 pub fn blocking_transaction(&mut self, address: u8, mut operations: &mut [Operation<'_>]) -> Result<(), Error> {
570 let mut last_op = None;
571 while !operations.is_empty() {
572 let ops = self.setup_operations(address, operations, last_op, false)?;
573 let (in_progress, rest) = operations.split_at_mut(ops);
574 self.blocking_wait();
575 self.check_operations(in_progress)?;
576 last_op = in_progress.last();
577 operations = rest;
578 }
579 Ok(())
580 }
581
582 #[cfg(feature = "time")]
586 pub fn blocking_transaction_timeout(
587 &mut self,
588 address: u8,
589 mut operations: &mut [Operation<'_>],
590 timeout: Duration,
591 ) -> Result<(), Error> {
592 let mut last_op = None;
593 while !operations.is_empty() {
594 let ops = self.setup_operations(address, operations, last_op, false)?;
595 let (in_progress, rest) = operations.split_at_mut(ops);
596 self.blocking_wait_timeout(timeout)?;
597 self.check_operations(in_progress)?;
598 last_op = in_progress.last();
599 operations = rest;
600 }
601 Ok(())
602 }
603
604 pub async fn transaction(&mut self, address: u8, mut operations: &mut [Operation<'_>]) -> Result<(), Error> {
615 let mut last_op = None;
616 while !operations.is_empty() {
617 let ops = self.setup_operations(address, operations, last_op, true)?;
618 let (in_progress, rest) = operations.split_at_mut(ops);
619 self.async_wait().await?;
620 self.check_operations(in_progress)?;
621 last_op = in_progress.last();
622 operations = rest;
623 }
624 Ok(())
625 }
626
627 pub fn blocking_write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
634 self.blocking_transaction(address, &mut [Operation::Write(buffer)])
635 }
636
637 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
642 self.blocking_transaction(address, &mut [Operation::Read(buffer)])
643 }
644
645 pub fn blocking_write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> {
651 self.blocking_transaction(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)])
652 }
653
654 #[cfg(feature = "time")]
660 pub fn blocking_write_timeout(&mut self, address: u8, buffer: &[u8], timeout: Duration) -> Result<(), Error> {
661 self.blocking_transaction_timeout(address, &mut [Operation::Write(buffer)], timeout)
662 }
663
664 #[cfg(feature = "time")]
669 pub fn blocking_read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> {
670 self.blocking_transaction_timeout(address, &mut [Operation::Read(buffer)], timeout)
671 }
672
673 #[cfg(feature = "time")]
679 pub fn blocking_write_read_timeout(
680 &mut self,
681 address: u8,
682 wr_buffer: &[u8],
683 rd_buffer: &mut [u8],
684 timeout: Duration,
685 ) -> Result<(), Error> {
686 self.blocking_transaction_timeout(
687 address,
688 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
689 timeout,
690 )
691 }
692
693 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
700 self.transaction(address, &mut [Operation::Read(buffer)]).await
701 }
702
703 pub async fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
708 self.transaction(address, &mut [Operation::Write(buffer)]).await
709 }
710
711 pub async fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Error> {
717 self.transaction(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)])
718 .await
719 }
720}
721
722impl<'a> Drop for Twim<'a> {
723 fn drop(&mut self) {
724 trace!("twim drop");
725
726 let r = self.r;
730 r.enable().write(|w| w.set_enable(vals::Enable::DISABLED));
731
732 gpio::deconfigure_pin(r.psel().sda().read());
733 gpio::deconfigure_pin(r.psel().scl().read());
734
735 trace!("twim drop: done");
736 }
737}
738
739pub(crate) struct State {
740 end_waker: AtomicWaker,
741}
742
743impl State {
744 pub(crate) const fn new() -> Self {
745 Self {
746 end_waker: AtomicWaker::new(),
747 }
748 }
749}
750
751pub(crate) trait SealedInstance {
752 fn regs() -> pac::twim::Twim;
753 fn state() -> &'static State;
754}
755
756#[allow(private_bounds)]
758pub trait Instance: SealedInstance + PeripheralType + 'static {
759 type Interrupt: interrupt::typelevel::Interrupt;
761}
762
763macro_rules! impl_twim {
764 ($type:ident, $pac_type:ident, $irq:ident) => {
765 impl crate::twim::SealedInstance for peripherals::$type {
766 fn regs() -> pac::twim::Twim {
767 pac::$pac_type
768 }
769 fn state() -> &'static crate::twim::State {
770 static STATE: crate::twim::State = crate::twim::State::new();
771 &STATE
772 }
773 }
774 impl crate::twim::Instance for peripherals::$type {
775 type Interrupt = crate::interrupt::typelevel::$irq;
776 }
777 };
778}
779
780mod eh02 {
783 use super::*;
784
785 impl<'a> embedded_hal_02::blocking::i2c::Write for Twim<'a> {
786 type Error = Error;
787
788 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
789 self.blocking_write(addr, bytes)
790 }
791 }
792
793 impl<'a> embedded_hal_02::blocking::i2c::Read for Twim<'a> {
794 type Error = Error;
795
796 fn read(&mut self, addr: u8, bytes: &mut [u8]) -> Result<(), Error> {
797 self.blocking_read(addr, bytes)
798 }
799 }
800
801 impl<'a> embedded_hal_02::blocking::i2c::WriteRead for Twim<'a> {
802 type Error = Error;
803
804 fn write_read<'w>(&mut self, addr: u8, bytes: &'w [u8], buffer: &'w mut [u8]) -> Result<(), Error> {
805 self.blocking_write_read(addr, bytes, buffer)
806 }
807 }
808}
809
810impl embedded_hal_1::i2c::Error for Error {
811 fn kind(&self) -> embedded_hal_1::i2c::ErrorKind {
812 match *self {
813 Self::TxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
814 Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
815 Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other,
816 Self::Receive => embedded_hal_1::i2c::ErrorKind::Other,
817 Self::RAMBufferTooSmall => embedded_hal_1::i2c::ErrorKind::Other,
818 Self::AddressNack => {
819 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address)
820 }
821 Self::DataNack => {
822 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Data)
823 }
824 Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun,
825 Self::Timeout => embedded_hal_1::i2c::ErrorKind::Other,
826 }
827 }
828}
829
830impl<'d> embedded_hal_1::i2c::ErrorType for Twim<'d> {
831 type Error = Error;
832}
833
834impl<'d> embedded_hal_1::i2c::I2c for Twim<'d> {
835 fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
836 self.blocking_transaction(address, operations)
837 }
838}
839
840impl<'d> embedded_hal_async::i2c::I2c for Twim<'d> {
841 async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
842 self.transaction(address, operations).await
843 }
844}
845
846impl<'d> SetConfig for Twim<'d> {
847 type Config = Config;
848 type ConfigError = ();
849 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
850 let r = self.r;
851 r.frequency().write(|w| w.set_frequency(config.frequency));
852
853 Ok(())
854 }
855}