1#![macro_use]
4
5use core::future::{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_hal_internal::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(feature = "time")]
14use embassy_time::{Duration, Instant};
15
16use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
17use crate::gpio::Pin as GpioPin;
18use crate::interrupt::typelevel::Interrupt;
19use crate::pac::gpio::vals as gpiovals;
20use crate::pac::twis::vals;
21use crate::util::slice_in_ram_or;
22use crate::{gpio, interrupt, pac};
23
24#[non_exhaustive]
26pub struct Config {
27 pub address0: u8,
29
30 pub address1: Option<u8>,
32
33 pub orc: u8,
38
39 pub sda_high_drive: bool,
41
42 pub sda_pullup: bool,
47
48 pub scl_high_drive: bool,
50
51 pub scl_pullup: bool,
56}
57
58impl Default for Config {
59 fn default() -> Self {
60 Self {
61 address0: 0x55,
62 address1: None,
63 orc: 0x00,
64 scl_high_drive: false,
65 sda_pullup: false,
66 sda_high_drive: false,
67 scl_pullup: false,
68 }
69 }
70}
71
72#[derive(Debug, Copy, Clone, Eq, PartialEq)]
73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74enum Status {
75 Read,
76 Write,
77}
78
79#[derive(Debug, Copy, Clone, Eq, PartialEq)]
81#[cfg_attr(feature = "defmt", derive(defmt::Format))]
82#[non_exhaustive]
83pub enum Error {
84 TxBufferTooLong,
86 RxBufferTooLong,
88 DataNack,
90 Bus,
92 BufferNotInRAM,
94 Overflow,
96 OverRead,
98 Timeout,
100}
101
102#[derive(Debug, Copy, Clone, Eq, PartialEq)]
104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105pub enum Command {
106 Read,
108 WriteRead(usize),
110 Write(usize),
112}
113
114pub struct InterruptHandler<T: Instance> {
116 _phantom: PhantomData<T>,
117}
118
119impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
120 unsafe fn on_interrupt() {
121 let r = T::regs();
122 let s = T::state();
123
124 if r.events_read().read() != 0 || r.events_write().read() != 0 {
125 s.waker.wake();
126 r.intenclr().write(|w| {
127 w.set_read(true);
128 w.set_write(true);
129 });
130 }
131 if r.events_stopped().read() != 0 {
132 s.waker.wake();
133 r.intenclr().write(|w| w.set_stopped(true));
134 }
135 if r.events_error().read() != 0 {
136 s.waker.wake();
137 r.intenclr().write(|w| w.set_error(true));
138 }
139 }
140}
141
142pub struct Twis<'d> {
144 r: pac::twis::Twis,
145 state: &'static State,
146 _p: PhantomData<&'d ()>,
147}
148
149impl<'d> Twis<'d> {
150 pub fn new<T: Instance>(
152 _twis: Peri<'d, T>,
153 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
154 sda: Peri<'d, impl GpioPin>,
155 scl: Peri<'d, impl GpioPin>,
156 config: Config,
157 ) -> Self {
158 let r = T::regs();
159
160 sda.conf().write(|w| {
162 w.set_dir(gpiovals::Dir::INPUT);
163 w.set_input(gpiovals::Input::CONNECT);
164 #[cfg(not(feature = "_nrf54l"))]
165 w.set_drive(match config.sda_high_drive {
166 true => gpiovals::Drive::H0D1,
167 false => gpiovals::Drive::S0D1,
168 });
169 #[cfg(feature = "_nrf54l")]
170 {
171 w.set_drive0(match config.sda_high_drive {
172 true => gpiovals::Drive::H,
173 false => gpiovals::Drive::S,
174 });
175 w.set_drive1(gpiovals::Drive::D);
176 }
177 if config.sda_pullup {
178 w.set_pull(gpiovals::Pull::PULLUP);
179 }
180 });
181 scl.conf().write(|w| {
182 w.set_dir(gpiovals::Dir::INPUT);
183 w.set_input(gpiovals::Input::CONNECT);
184 #[cfg(not(feature = "_nrf54l"))]
185 w.set_drive(match config.scl_high_drive {
186 true => gpiovals::Drive::H0D1,
187 false => gpiovals::Drive::S0D1,
188 });
189 #[cfg(feature = "_nrf54l")]
190 {
191 w.set_drive0(match config.scl_high_drive {
192 true => gpiovals::Drive::H,
193 false => gpiovals::Drive::S,
194 });
195 w.set_drive1(gpiovals::Drive::D);
196 }
197 if config.sda_pullup {
198 w.set_pull(gpiovals::Pull::PULLUP);
199 }
200 });
201
202 r.psel().sda().write_value(sda.psel_bits());
204 r.psel().scl().write_value(scl.psel_bits());
205
206 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
208
209 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
211
212 r.address(0).write(|w| w.set_address(config.address0));
214 r.config().write(|w| w.set_address0(true));
215 if let Some(address1) = config.address1 {
216 r.address(1).write(|w| w.set_address(address1));
217 r.config().modify(|w| w.set_address1(true));
218 }
219
220 r.orc().write(|w| w.set_orc(config.orc));
222
223 r.shorts().write(|w| w.set_read_suspend(true));
225
226 T::Interrupt::unpend();
227 unsafe { T::Interrupt::enable() };
228
229 Self {
230 r: T::regs(),
231 state: T::state(),
232 _p: PhantomData,
233 }
234 }
235
236 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
238 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
239
240 if buffer.len() > EASY_DMA_SIZE {
241 return Err(Error::TxBufferTooLong);
242 }
243
244 let r = self.r;
245
246 r.dma().tx().ptr().write_value(buffer.as_ptr() as u32);
250 r.dma().tx().maxcnt().write(|w|
251 w.set_maxcnt(buffer.len() as _));
258
259 Ok(())
260 }
261
262 unsafe fn set_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
264 if buffer.len() > EASY_DMA_SIZE {
268 return Err(Error::RxBufferTooLong);
269 }
270
271 let r = self.r;
272
273 r.dma().rx().ptr().write_value(buffer.as_mut_ptr() as u32);
277 r.dma().rx().maxcnt().write(|w|
278 w.set_maxcnt(buffer.len() as _));
288
289 Ok(())
290 }
291
292 fn clear_errorsrc(&mut self) {
293 let r = self.r;
294 r.errorsrc().write(|w| {
295 w.set_overflow(true);
296 w.set_overread(true);
297 w.set_dnack(true);
298 });
299 }
300
301 pub fn address_match(&self) -> u8 {
303 let r = self.r;
304 r.address(r.match_().read().0 as usize).read().address()
305 }
306
307 pub fn address_match_index(&self) -> usize {
309 self.r.match_().read().0 as _
310 }
311
312 fn blocking_listen_wait(&mut self) -> Result<Status, Error> {
314 let r = self.r;
315 loop {
316 if r.events_error().read() != 0 {
317 r.events_error().write_value(0);
318 r.tasks_stop().write_value(1);
319 while r.events_stopped().read() == 0 {}
320 return Err(Error::Overflow);
321 }
322 if r.events_stopped().read() != 0 {
323 r.events_stopped().write_value(0);
324 return Err(Error::Bus);
325 }
326 if r.events_read().read() != 0 {
327 r.events_read().write_value(0);
328 return Ok(Status::Read);
329 }
330 if r.events_write().read() != 0 {
331 r.events_write().write_value(0);
332 return Ok(Status::Write);
333 }
334 }
335 }
336
337 fn blocking_listen_wait_end(&mut self, status: Status) -> Result<Command, Error> {
339 let r = self.r;
340 loop {
341 if r.events_error().read() != 0 {
343 r.events_error().write_value(0);
344 r.tasks_stop().write_value(1);
345 return Err(Error::Overflow);
346 } else if r.events_stopped().read() != 0 {
347 r.events_stopped().write_value(0);
348 return match status {
349 Status::Read => Ok(Command::Read),
350 Status::Write => {
351 let n = r.dma().rx().amount().read().0 as usize;
352 Ok(Command::Write(n))
353 }
354 };
355 } else if r.events_read().read() != 0 {
356 r.events_read().write_value(0);
357 let n = r.dma().rx().amount().read().0 as usize;
358 return Ok(Command::WriteRead(n));
359 }
360 }
361 }
362
363 fn blocking_wait(&mut self) -> Result<usize, Error> {
365 let r = self.r;
366 loop {
367 if r.events_error().read() != 0 {
369 r.events_error().write_value(0);
370 r.tasks_stop().write_value(1);
371 let errorsrc = r.errorsrc().read();
372 if errorsrc.overread() {
373 return Err(Error::OverRead);
374 } else if errorsrc.dnack() {
375 return Err(Error::DataNack);
376 } else {
377 return Err(Error::Bus);
378 }
379 } else if r.events_stopped().read() != 0 {
380 r.events_stopped().write_value(0);
381 let n = r.dma().tx().amount().read().0 as usize;
382 return Ok(n);
383 }
384 }
385 }
386
387 #[cfg(feature = "time")]
389 fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<usize, Error> {
390 let r = self.r;
391 let deadline = Instant::now() + timeout;
392 loop {
393 if r.events_error().read() != 0 {
395 r.events_error().write_value(0);
396 r.tasks_stop().write_value(1);
397 let errorsrc = r.errorsrc().read();
398 if errorsrc.overread() {
399 return Err(Error::OverRead);
400 } else if errorsrc.dnack() {
401 return Err(Error::DataNack);
402 } else {
403 return Err(Error::Bus);
404 }
405 } else if r.events_stopped().read() != 0 {
406 r.events_stopped().write_value(0);
407 let n = r.dma().tx().amount().read().0 as usize;
408 return Ok(n);
409 } else if Instant::now() > deadline {
410 r.tasks_stop().write_value(1);
411 return Err(Error::Timeout);
412 }
413 }
414 }
415
416 #[cfg(feature = "time")]
418 fn blocking_listen_wait_timeout(&mut self, timeout: Duration) -> Result<Status, Error> {
419 let r = self.r;
420 let deadline = Instant::now() + timeout;
421 loop {
422 if r.events_error().read() != 0 {
423 r.events_error().write_value(0);
424 r.tasks_stop().write_value(1);
425 while r.events_stopped().read() == 0 {}
426 return Err(Error::Overflow);
427 }
428 if r.events_stopped().read() != 0 {
429 r.events_stopped().write_value(0);
430 return Err(Error::Bus);
431 }
432 if r.events_read().read() != 0 {
433 r.events_read().write_value(0);
434 return Ok(Status::Read);
435 }
436 if r.events_write().read() != 0 {
437 r.events_write().write_value(0);
438 return Ok(Status::Write);
439 }
440 if Instant::now() > deadline {
441 r.tasks_stop().write_value(1);
442 return Err(Error::Timeout);
443 }
444 }
445 }
446
447 #[cfg(feature = "time")]
449 fn blocking_listen_wait_end_timeout(&mut self, status: Status, timeout: Duration) -> Result<Command, Error> {
450 let r = self.r;
451 let deadline = Instant::now() + timeout;
452 loop {
453 if r.events_error().read() != 0 {
455 r.events_error().write_value(0);
456 r.tasks_stop().write_value(1);
457 return Err(Error::Overflow);
458 } else if r.events_stopped().read() != 0 {
459 r.events_stopped().write_value(0);
460 return match status {
461 Status::Read => Ok(Command::Read),
462 Status::Write => {
463 let n = r.dma().rx().amount().read().0 as usize;
464 Ok(Command::Write(n))
465 }
466 };
467 } else if r.events_read().read() != 0 {
468 r.events_read().write_value(0);
469 let n = r.dma().rx().amount().read().0 as usize;
470 return Ok(Command::WriteRead(n));
471 } else if Instant::now() > deadline {
472 r.tasks_stop().write_value(1);
473 return Err(Error::Timeout);
474 }
475 }
476 }
477
478 fn async_wait(&mut self) -> impl Future<Output = Result<usize, Error>> {
480 let r = self.r;
481 let s = self.state;
482 poll_fn(move |cx| {
483 s.waker.register(cx.waker());
484
485 if r.events_error().read() != 0 {
487 r.events_error().write_value(0);
488 r.tasks_stop().write_value(1);
489 let errorsrc = r.errorsrc().read();
490 if errorsrc.overread() {
491 return Poll::Ready(Err(Error::OverRead));
492 } else if errorsrc.dnack() {
493 return Poll::Ready(Err(Error::DataNack));
494 } else {
495 return Poll::Ready(Err(Error::Bus));
496 }
497 } else if r.events_stopped().read() != 0 {
498 r.events_stopped().write_value(0);
499 let n = r.dma().tx().amount().read().0 as usize;
500 return Poll::Ready(Ok(n));
501 }
502
503 Poll::Pending
504 })
505 }
506
507 fn async_listen_wait(&mut self) -> impl Future<Output = Result<Status, Error>> {
509 let r = self.r;
510 let s = self.state;
511 poll_fn(move |cx| {
512 s.waker.register(cx.waker());
513
514 if r.events_error().read() != 0 {
516 r.events_error().write_value(0);
517 r.tasks_stop().write_value(1);
518 return Poll::Ready(Err(Error::Overflow));
519 } else if r.events_read().read() != 0 {
520 r.events_read().write_value(0);
521 return Poll::Ready(Ok(Status::Read));
522 } else if r.events_write().read() != 0 {
523 r.events_write().write_value(0);
524 return Poll::Ready(Ok(Status::Write));
525 } else if r.events_stopped().read() != 0 {
526 r.events_stopped().write_value(0);
527 return Poll::Ready(Err(Error::Bus));
528 }
529 Poll::Pending
530 })
531 }
532
533 fn async_listen_wait_end(&mut self, status: Status) -> impl Future<Output = Result<Command, Error>> {
535 let r = self.r;
536 let s = self.state;
537 poll_fn(move |cx| {
538 s.waker.register(cx.waker());
539
540 if r.events_error().read() != 0 {
542 r.events_error().write_value(0);
543 r.tasks_stop().write_value(1);
544 return Poll::Ready(Err(Error::Overflow));
545 } else if r.events_stopped().read() != 0 {
546 r.events_stopped().write_value(0);
547 return match status {
548 Status::Read => Poll::Ready(Ok(Command::Read)),
549 Status::Write => {
550 let n = r.dma().rx().amount().read().0 as usize;
551 Poll::Ready(Ok(Command::Write(n)))
552 }
553 };
554 } else if r.events_read().read() != 0 {
555 r.events_read().write_value(0);
556 let n = r.dma().rx().amount().read().0 as usize;
557 return Poll::Ready(Ok(Command::WriteRead(n)));
558 }
559 Poll::Pending
560 })
561 }
562
563 fn setup_respond_from_ram(&mut self, buffer: &[u8], inten: bool) -> Result<(), Error> {
564 let r = self.r;
565
566 compiler_fence(SeqCst);
567
568 unsafe { self.set_tx_buffer(buffer)? };
570
571 r.events_stopped().write_value(0);
573 r.events_error().write_value(0);
574 self.clear_errorsrc();
575
576 if inten {
577 r.intenset().write(|w| {
578 w.set_stopped(true);
579 w.set_error(true);
580 });
581 } else {
582 r.intenclr().write(|w| {
583 w.set_stopped(true);
584 w.set_error(true);
585 });
586 }
587
588 r.tasks_preparetx().write_value(1);
590 r.tasks_resume().write_value(1);
591 Ok(())
592 }
593
594 fn setup_respond(&mut self, wr_buffer: &[u8], inten: bool) -> Result<(), Error> {
595 match self.setup_respond_from_ram(wr_buffer, inten) {
596 Ok(_) => Ok(()),
597 Err(Error::BufferNotInRAM) => {
598 trace!("Copying TWIS tx buffer into RAM for DMA");
599 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
600 tx_ram_buf.copy_from_slice(wr_buffer);
601 self.setup_respond_from_ram(tx_ram_buf, inten)
602 }
603 Err(error) => Err(error),
604 }
605 }
606
607 fn setup_listen(&mut self, buffer: &mut [u8], inten: bool) -> Result<(), Error> {
608 let r = self.r;
609 compiler_fence(SeqCst);
610
611 unsafe { self.set_rx_buffer(buffer)? };
613
614 r.events_read().write_value(0);
616 r.events_write().write_value(0);
617 r.events_stopped().write_value(0);
618 r.events_error().write_value(0);
619 self.clear_errorsrc();
620
621 if inten {
622 r.intenset().write(|w| {
623 w.set_stopped(true);
624 w.set_error(true);
625 w.set_read(true);
626 w.set_write(true);
627 });
628 } else {
629 r.intenclr().write(|w| {
630 w.set_stopped(true);
631 w.set_error(true);
632 w.set_read(true);
633 w.set_write(true);
634 });
635 }
636
637 r.tasks_preparerx().write_value(1);
639
640 Ok(())
641 }
642
643 fn setup_listen_end(&mut self, inten: bool) -> Result<(), Error> {
644 let r = self.r;
645 compiler_fence(SeqCst);
646
647 r.events_read().write_value(0);
649 r.events_write().write_value(0);
650 r.events_stopped().write_value(0);
651 r.events_error().write_value(0);
652 self.clear_errorsrc();
653
654 if inten {
655 r.intenset().write(|w| {
656 w.set_stopped(true);
657 w.set_error(true);
658 w.set_read(true);
659 });
660 } else {
661 r.intenclr().write(|w| {
662 w.set_stopped(true);
663 w.set_error(true);
664 w.set_read(true);
665 });
666 }
667
668 Ok(())
669 }
670
671 pub fn blocking_listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
677 self.setup_listen(buffer, false)?;
678 let status = self.blocking_listen_wait()?;
679 if status == Status::Write {
680 self.setup_listen_end(false)?;
681 let command = self.blocking_listen_wait_end(status)?;
682 return Ok(command);
683 }
684 Ok(Command::Read)
685 }
686
687 pub fn blocking_respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
692 self.setup_respond(buffer, false)?;
693 self.blocking_wait()
694 }
695
696 pub fn blocking_respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
699 self.setup_respond_from_ram(buffer, false)?;
700 self.blocking_wait()
701 }
702
703 #[cfg(feature = "time")]
711 pub fn blocking_listen_timeout(&mut self, buffer: &mut [u8], timeout: Duration) -> Result<Command, Error> {
712 self.setup_listen(buffer, false)?;
713 let status = self.blocking_listen_wait_timeout(timeout)?;
714 if status == Status::Write {
715 self.setup_listen_end(false)?;
716 let command = self.blocking_listen_wait_end_timeout(status, timeout)?;
717 return Ok(command);
718 }
719 Ok(Command::Read)
720 }
721
722 #[cfg(feature = "time")]
726 pub fn blocking_respond_to_read_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<usize, Error> {
727 self.setup_respond(buffer, false)?;
728 self.blocking_wait_timeout(timeout)
729 }
730
731 #[cfg(feature = "time")]
734 pub fn blocking_respond_to_read_from_ram_timeout(
735 &mut self,
736 buffer: &[u8],
737 timeout: Duration,
738 ) -> Result<usize, Error> {
739 self.setup_respond_from_ram(buffer, false)?;
740 self.blocking_wait_timeout(timeout)
741 }
742
743 pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
751 self.setup_listen(buffer, true)?;
752 let status = self.async_listen_wait().await?;
753 if status == Status::Write {
754 self.setup_listen_end(true)?;
755 let command = self.async_listen_wait_end(status).await?;
756 return Ok(command);
757 }
758 Ok(Command::Read)
759 }
760
761 pub async fn respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
766 self.setup_respond(buffer, true)?;
767 self.async_wait().await
768 }
769
770 pub async fn respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
772 self.setup_respond_from_ram(buffer, true)?;
773 self.async_wait().await
774 }
775}
776
777impl<'a> Drop for Twis<'a> {
778 fn drop(&mut self) {
779 trace!("twis drop");
780
781 let r = self.r;
785 r.enable().write(|w| w.set_enable(vals::Enable::DISABLED));
786
787 gpio::deconfigure_pin(r.psel().sda().read());
788 gpio::deconfigure_pin(r.psel().scl().read());
789
790 trace!("twis drop: done");
791 }
792}
793
794pub(crate) struct State {
795 waker: AtomicWaker,
796}
797
798impl State {
799 pub(crate) const fn new() -> Self {
800 Self {
801 waker: AtomicWaker::new(),
802 }
803 }
804}
805
806pub(crate) trait SealedInstance {
807 fn regs() -> pac::twis::Twis;
808 fn state() -> &'static State;
809}
810
811#[allow(private_bounds)]
813pub trait Instance: SealedInstance + PeripheralType + 'static {
814 type Interrupt: interrupt::typelevel::Interrupt;
816}
817
818macro_rules! impl_twis {
819 ($type:ident, $pac_type:ident, $irq:ident) => {
820 impl crate::twis::SealedInstance for peripherals::$type {
821 fn regs() -> pac::twis::Twis {
822 pac::$pac_type
823 }
824 fn state() -> &'static crate::twis::State {
825 static STATE: crate::twis::State = crate::twis::State::new();
826 &STATE
827 }
828 }
829 impl crate::twis::Instance for peripherals::$type {
830 type Interrupt = crate::interrupt::typelevel::$irq;
831 }
832 };
833}