aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-11-22 21:50:42 +0000
committerGitHub <[email protected]>2022-11-22 21:50:42 +0000
commit83b199a8744ddbba93b929f59606f0518c6f9ce1 (patch)
treef680920a62effeaa675a649248f449d179fc238e
parent61be0e75c83961a42fc1d844159f1fed7d8afbea (diff)
parentcf900a8a3f048428cc1209763f4188366818ab8a (diff)
Merge #1056
1056: embassy-nrf: Add TWIS module r=Dirbaio a=kalkyl Verified to be working on nrf9160 Co-authored-by: kalkyl <[email protected]> Co-authored-by: Henrik Alsér <[email protected]>
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs3
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs3
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs3
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs3
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs5
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs1
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs5
-rw-r--r--embassy-nrf/src/lib.rs1
-rw-r--r--embassy-nrf/src/twis.rs759
-rw-r--r--examples/nrf/src/bin/twis.rs46
13 files changed, 835 insertions, 0 deletions
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 11a6840c8..bf4019c13 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -135,6 +135,8 @@ impl_spis!(SPI0, SPIS0, SPIM0_SPIS0_SPI0);
135 135
136impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); 136impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
137 137
138impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
139
138impl_timer!(TIMER0, TIMER0, TIMER0); 140impl_timer!(TIMER0, TIMER0, TIMER0);
139impl_timer!(TIMER1, TIMER1, TIMER1); 141impl_timer!(TIMER1, TIMER1, TIMER1);
140impl_timer!(TIMER2, TIMER2, TIMER2); 142impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 3614cd229..6c28a3bea 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -141,6 +141,8 @@ impl_spis!(SPI0, SPIS0, SPIM0_SPIS0_SPI0);
141 141
142impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); 142impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
143 143
144impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
145
144impl_pwm!(PWM0, PWM0, PWM0); 146impl_pwm!(PWM0, PWM0, PWM0);
145 147
146impl_timer!(TIMER0, TIMER0, TIMER0); 148impl_timer!(TIMER0, TIMER0, TIMER0);
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index dc4a8660e..e7214cf5c 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -143,6 +143,8 @@ impl_spis!(SPI1, SPIS1, SPIM1_SPIS1_SPI1);
143 143
144impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); 144impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
145 145
146impl_twis!(TWISPI0, TWIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
147
146impl_pwm!(PWM0, PWM0, PWM0); 148impl_pwm!(PWM0, PWM0, PWM0);
147 149
148impl_timer!(TIMER0, TIMER0, TIMER0); 150impl_timer!(TIMER0, TIMER0, TIMER0);
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index 7668920bd..21d1d16cc 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -142,6 +142,9 @@ impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
142impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 142impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
143impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 143impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
144 144
145impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
146impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
147
145impl_timer!(TIMER0, TIMER0, TIMER0); 148impl_timer!(TIMER0, TIMER0, TIMER0);
146impl_timer!(TIMER1, TIMER1, TIMER1); 149impl_timer!(TIMER1, TIMER1, TIMER1);
147impl_timer!(TIMER2, TIMER2, TIMER2); 150impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index 851643b55..879600adb 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -153,6 +153,9 @@ impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
153impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 153impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
154impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 154impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
155 155
156impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
157impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
158
156impl_pwm!(PWM0, PWM0, PWM0); 159impl_pwm!(PWM0, PWM0, PWM0);
157impl_pwm!(PWM1, PWM1, PWM1); 160impl_pwm!(PWM1, PWM1, PWM1);
158impl_pwm!(PWM2, PWM2, PWM2); 161impl_pwm!(PWM2, PWM2, PWM2);
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 5342ba8c2..d406c32c2 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -181,6 +181,9 @@ impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
181impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 181impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
182impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 182impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
183 183
184impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
185impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
186
184impl_pwm!(PWM0, PWM0, PWM0); 187impl_pwm!(PWM0, PWM0, PWM0);
185impl_pwm!(PWM1, PWM1, PWM1); 188impl_pwm!(PWM1, PWM1, PWM1);
186impl_pwm!(PWM2, PWM2, PWM2); 189impl_pwm!(PWM2, PWM2, PWM2);
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index a330aef8b..f9e271c97 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -184,6 +184,9 @@ impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
184impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 184impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
185impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); 185impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
186 186
187impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
188impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
189
187impl_pwm!(PWM0, PWM0, PWM0); 190impl_pwm!(PWM0, PWM0, PWM0);
188impl_pwm!(PWM1, PWM1, PWM1); 191impl_pwm!(PWM1, PWM1, PWM1);
189impl_pwm!(PWM2, PWM2, PWM2); 192impl_pwm!(PWM2, PWM2, PWM2);
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 1c027ec02..39fb9a9bf 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -371,6 +371,11 @@ impl_twim!(UARTETWISPI1, TWIM1, SERIAL1);
371impl_twim!(UARTETWISPI2, TWIM2, SERIAL2); 371impl_twim!(UARTETWISPI2, TWIM2, SERIAL2);
372impl_twim!(UARTETWISPI3, TWIM3, SERIAL3); 372impl_twim!(UARTETWISPI3, TWIM3, SERIAL3);
373 373
374impl_twis!(UARTETWISPI0, TWIS0, SERIAL0);
375impl_twis!(UARTETWISPI1, TWIS1, SERIAL1);
376impl_twis!(UARTETWISPI2, TWIS2, SERIAL2);
377impl_twis!(UARTETWISPI3, TWIS3, SERIAL3);
378
374impl_pwm!(PWM0, PWM0, PWM0); 379impl_pwm!(PWM0, PWM0, PWM0);
375impl_pwm!(PWM1, PWM1, PWM1); 380impl_pwm!(PWM1, PWM1, PWM1);
376impl_pwm!(PWM2, PWM2, PWM2); 381impl_pwm!(PWM2, PWM2, PWM2);
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index 3bcd44fcb..b8ee7745b 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -240,6 +240,7 @@ impl_uarte!(UARTETWISPI0, UARTE0, SERIAL0);
240impl_spim!(UARTETWISPI0, SPIM0, SERIAL0); 240impl_spim!(UARTETWISPI0, SPIM0, SERIAL0);
241impl_spis!(UARTETWISPI0, SPIS0, SERIAL0); 241impl_spis!(UARTETWISPI0, SPIS0, SERIAL0);
242impl_twim!(UARTETWISPI0, TWIM0, SERIAL0); 242impl_twim!(UARTETWISPI0, TWIM0, SERIAL0);
243impl_twis!(UARTETWISPI0, TWIS0, SERIAL0);
243 244
244impl_timer!(TIMER0, TIMER0, TIMER0); 245impl_timer!(TIMER0, TIMER0, TIMER0);
245impl_timer!(TIMER1, TIMER1, TIMER1); 246impl_timer!(TIMER1, TIMER1, TIMER1);
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 0dfa112fe..a47c0a397 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -285,6 +285,11 @@ impl_twim!(UARTETWISPI1, TWIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
285impl_twim!(UARTETWISPI2, TWIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2); 285impl_twim!(UARTETWISPI2, TWIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
286impl_twim!(UARTETWISPI3, TWIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3); 286impl_twim!(UARTETWISPI3, TWIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
287 287
288impl_twis!(UARTETWISPI0, TWIS0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
289impl_twis!(UARTETWISPI1, TWIS1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
290impl_twis!(UARTETWISPI2, TWIS2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
291impl_twis!(UARTETWISPI3, TWIS3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
292
288impl_pwm!(PWM0, PWM0, PWM0); 293impl_pwm!(PWM0, PWM0, PWM0);
289impl_pwm!(PWM1, PWM1, PWM1); 294impl_pwm!(PWM1, PWM1, PWM1);
290impl_pwm!(PWM2, PWM2, PWM2); 295impl_pwm!(PWM2, PWM2, PWM2);
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 5726f1181..dc6f16867 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -101,6 +101,7 @@ pub mod spis;
101pub mod temp; 101pub mod temp;
102pub mod timer; 102pub mod timer;
103pub mod twim; 103pub mod twim;
104pub mod twis;
104pub mod uarte; 105pub mod uarte;
105#[cfg(any( 106#[cfg(any(
106 feature = "_nrf5340-app", 107 feature = "_nrf5340-app",
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs
new file mode 100644
index 000000000..4091b017e
--- /dev/null
+++ b/embassy-nrf/src/twis.rs
@@ -0,0 +1,759 @@
1#![macro_use]
2
3//! HAL interface to the TWIS peripheral.
4//!
5//! See product specification:
6//!
7//! - nRF52832: Section 33
8//! - nRF52840: Section 6.31
9use core::future::{poll_fn, Future};
10use core::sync::atomic::compiler_fence;
11use core::sync::atomic::Ordering::SeqCst;
12use core::task::Poll;
13
14use embassy_hal_common::{into_ref, PeripheralRef};
15use embassy_sync::waitqueue::AtomicWaker;
16#[cfg(feature = "time")]
17use embassy_time::{Duration, Instant};
18
19use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
20use crate::gpio::Pin as GpioPin;
21use crate::interrupt::{Interrupt, InterruptExt};
22use crate::util::slice_in_ram_or;
23use crate::{gpio, pac, Peripheral};
24
25#[non_exhaustive]
26pub struct Config {
27 pub address0: u8,
28 pub address1: Option<u8>,
29 pub orc: u8,
30 pub sda_high_drive: bool,
31 pub sda_pullup: bool,
32 pub scl_high_drive: bool,
33 pub scl_pullup: bool,
34}
35
36impl Default for Config {
37 fn default() -> Self {
38 Self {
39 address0: 0x55,
40 address1: None,
41 orc: 0x00,
42 scl_high_drive: false,
43 sda_pullup: false,
44 sda_high_drive: false,
45 scl_pullup: false,
46 }
47 }
48}
49
50#[derive(Debug, Copy, Clone, Eq, PartialEq)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52enum Status {
53 Read,
54 Write,
55}
56
57#[derive(Debug, Copy, Clone, Eq, PartialEq)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59#[non_exhaustive]
60pub enum Error {
61 TxBufferTooLong,
62 RxBufferTooLong,
63 DataNack,
64 Bus,
65 DMABufferNotInDataMemory,
66 Overflow,
67 OverRead,
68 Timeout,
69}
70
71#[derive(Debug, Copy, Clone, Eq, PartialEq)]
72#[cfg_attr(feature = "defmt", derive(defmt::Format))]
73pub enum Command {
74 Read,
75 WriteRead(usize),
76 Write(usize),
77}
78
79/// Interface to a TWIS instance using EasyDMA to offload the transmission and reception workload.
80///
81/// For more details about EasyDMA, consult the module documentation.
82pub struct Twis<'d, T: Instance> {
83 _p: PeripheralRef<'d, T>,
84}
85
86impl<'d, T: Instance> Twis<'d, T> {
87 pub fn new(
88 twis: impl Peripheral<P = T> + 'd,
89 irq: impl Peripheral<P = T::Interrupt> + 'd,
90 sda: impl Peripheral<P = impl GpioPin> + 'd,
91 scl: impl Peripheral<P = impl GpioPin> + 'd,
92 config: Config,
93 ) -> Self {
94 into_ref!(twis, irq, sda, scl);
95
96 let r = T::regs();
97
98 // Configure pins
99 sda.conf().write(|w| {
100 w.dir().input();
101 w.input().connect();
102 if config.sda_high_drive {
103 w.drive().h0d1();
104 } else {
105 w.drive().s0d1();
106 }
107 if config.sda_pullup {
108 w.pull().pullup();
109 }
110 w
111 });
112 scl.conf().write(|w| {
113 w.dir().input();
114 w.input().connect();
115 if config.scl_high_drive {
116 w.drive().h0d1();
117 } else {
118 w.drive().s0d1();
119 }
120 if config.scl_pullup {
121 w.pull().pullup();
122 }
123 w
124 });
125
126 // Select pins.
127 r.psel.sda.write(|w| unsafe { w.bits(sda.psel_bits()) });
128 r.psel.scl.write(|w| unsafe { w.bits(scl.psel_bits()) });
129
130 // Enable TWIS instance.
131 r.enable.write(|w| w.enable().enabled());
132
133 // Disable all events interrupts
134 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
135
136 // Set address
137 r.address[0].write(|w| unsafe { w.address().bits(config.address0) });
138 r.config.write(|w| w.address0().enabled());
139 if let Some(address1) = config.address1 {
140 r.address[1].write(|w| unsafe { w.address().bits(address1) });
141 r.config.modify(|_r, w| w.address1().enabled());
142 }
143
144 // Set over-read character
145 r.orc.write(|w| unsafe { w.orc().bits(config.orc) });
146
147 // Generate suspend on read event
148 r.shorts.write(|w| w.read_suspend().enabled());
149
150 irq.set_handler(Self::on_interrupt);
151 irq.unpend();
152 irq.enable();
153
154 Self { _p: twis }
155 }
156
157 fn on_interrupt(_: *mut ()) {
158 let r = T::regs();
159 let s = T::state();
160
161 if r.events_read.read().bits() != 0 || r.events_write.read().bits() != 0 {
162 s.waker.wake();
163 r.intenclr.modify(|_r, w| w.read().clear().write().clear());
164 }
165 if r.events_stopped.read().bits() != 0 {
166 s.waker.wake();
167 r.intenclr.modify(|_r, w| w.stopped().clear());
168 }
169 if r.events_error.read().bits() != 0 {
170 s.waker.wake();
171 r.intenclr.modify(|_r, w| w.error().clear());
172 }
173 }
174
175 /// Set TX buffer, checking that it is in RAM and has suitable length.
176 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
177 slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
178
179 if buffer.len() > EASY_DMA_SIZE {
180 return Err(Error::TxBufferTooLong);
181 }
182
183 let r = T::regs();
184
185 r.txd.ptr.write(|w|
186 // We're giving the register a pointer to the stack. Since we're
187 // waiting for the I2C transaction to end before this stack pointer
188 // becomes invalid, there's nothing wrong here.
189 //
190 // The PTR field is a full 32 bits wide and accepts the full range
191 // of values.
192 w.ptr().bits(buffer.as_ptr() as u32));
193 r.txd.maxcnt.write(|w|
194 // We're giving it the length of the buffer, so no danger of
195 // accessing invalid memory. We have verified that the length of the
196 // buffer fits in an `u8`, so the cast to `u8` is also fine.
197 //
198 // The MAXCNT field is 8 bits wide and accepts the full range of
199 // values.
200 w.maxcnt().bits(buffer.len() as _));
201
202 Ok(())
203 }
204
205 /// Set RX buffer, checking that it has suitable length.
206 unsafe fn set_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
207 // NOTE: RAM slice check is not necessary, as a mutable
208 // slice can only be built from data located in RAM.
209
210 if buffer.len() > EASY_DMA_SIZE {
211 return Err(Error::RxBufferTooLong);
212 }
213
214 let r = T::regs();
215
216 r.rxd.ptr.write(|w|
217 // We're giving the register a pointer to the stack. Since we're
218 // waiting for the I2C transaction to end before this stack pointer
219 // becomes invalid, there's nothing wrong here.
220 //
221 // The PTR field is a full 32 bits wide and accepts the full range
222 // of values.
223 w.ptr().bits(buffer.as_mut_ptr() as u32));
224 r.rxd.maxcnt.write(|w|
225 // We're giving it the length of the buffer, so no danger of
226 // accessing invalid memory. We have verified that the length of the
227 // buffer fits in an `u8`, so the cast to the type of maxcnt
228 // is also fine.
229 //
230 // Note that that nrf52840 maxcnt is a wider
231 // type than a u8, so we use a `_` cast rather than a `u8` cast.
232 // The MAXCNT field is thus at least 8 bits wide and accepts the
233 // full range of values that fit in a `u8`.
234 w.maxcnt().bits(buffer.len() as _));
235
236 Ok(())
237 }
238
239 fn clear_errorsrc(&mut self) {
240 let r = T::regs();
241 r.errorsrc
242 .write(|w| w.overflow().bit(true).overread().bit(true).dnack().bit(true));
243 }
244
245 /// Returns matched address for latest command.
246 pub fn address_match(&self) -> u8 {
247 let r = T::regs();
248 r.address[r.match_.read().bits() as usize].read().address().bits()
249 }
250
251 /// Returns the index of the address matched in the latest command.
252 pub fn address_match_index(&self) -> usize {
253 T::regs().match_.read().bits() as _
254 }
255
256 /// Wait for read, write, stop or error
257 fn blocking_listen_wait(&mut self) -> Result<Status, Error> {
258 let r = T::regs();
259 loop {
260 if r.events_error.read().bits() != 0 {
261 r.events_error.reset();
262 r.tasks_stop.write(|w| unsafe { w.bits(1) });
263 while r.events_stopped.read().bits() == 0 {}
264 return Err(Error::Overflow);
265 }
266 if r.events_stopped.read().bits() != 0 {
267 r.events_stopped.reset();
268 return Err(Error::Bus);
269 }
270 if r.events_read.read().bits() != 0 {
271 r.events_read.reset();
272 return Ok(Status::Read);
273 }
274 if r.events_write.read().bits() != 0 {
275 r.events_write.reset();
276 return Ok(Status::Write);
277 }
278 }
279 }
280
281 /// Wait for stop, repeated start or error
282 fn blocking_listen_wait_end(&mut self, status: Status) -> Result<Command, Error> {
283 let r = T::regs();
284 loop {
285 // stop if an error occured
286 if r.events_error.read().bits() != 0 {
287 r.events_error.reset();
288 r.tasks_stop.write(|w| unsafe { w.bits(1) });
289 return Err(Error::Overflow);
290 } else if r.events_stopped.read().bits() != 0 {
291 r.events_stopped.reset();
292 return match status {
293 Status::Read => Ok(Command::Read),
294 Status::Write => {
295 let n = r.rxd.amount.read().bits() as usize;
296 Ok(Command::Write(n))
297 }
298 };
299 } else if r.events_read.read().bits() != 0 {
300 r.events_read.reset();
301 let n = r.rxd.amount.read().bits() as usize;
302 return Ok(Command::WriteRead(n));
303 }
304 }
305 }
306
307 /// Wait for stop or error
308 fn blocking_wait(&mut self) -> Result<usize, Error> {
309 let r = T::regs();
310 loop {
311 // stop if an error occured
312 if r.events_error.read().bits() != 0 {
313 r.events_error.reset();
314 r.tasks_stop.write(|w| unsafe { w.bits(1) });
315 let errorsrc = r.errorsrc.read();
316 if errorsrc.overread().is_detected() {
317 return Err(Error::OverRead);
318 } else if errorsrc.dnack().is_received() {
319 return Err(Error::DataNack);
320 } else {
321 return Err(Error::Bus);
322 }
323 } else if r.events_stopped.read().bits() != 0 {
324 r.events_stopped.reset();
325 let n = r.txd.amount.read().bits() as usize;
326 return Ok(n);
327 }
328 }
329 }
330
331 /// Wait for stop or error with timeout
332 #[cfg(feature = "time")]
333 fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<usize, Error> {
334 let r = T::regs();
335 let deadline = Instant::now() + timeout;
336 loop {
337 // stop if an error occured
338 if r.events_error.read().bits() != 0 {
339 r.events_error.reset();
340 r.tasks_stop.write(|w| unsafe { w.bits(1) });
341 let errorsrc = r.errorsrc.read();
342 if errorsrc.overread().is_detected() {
343 return Err(Error::OverRead);
344 } else if errorsrc.dnack().is_received() {
345 return Err(Error::DataNack);
346 } else {
347 return Err(Error::Bus);
348 }
349 } else if r.events_stopped.read().bits() != 0 {
350 r.events_stopped.reset();
351 let n = r.txd.amount.read().bits() as usize;
352 return Ok(n);
353 } else if Instant::now() > deadline {
354 r.tasks_stop.write(|w| unsafe { w.bits(1) });
355 return Err(Error::Timeout);
356 }
357 }
358 }
359
360 /// Wait for read, write, stop or error with timeout
361 #[cfg(feature = "time")]
362 fn blocking_listen_wait_timeout(&mut self, timeout: Duration) -> Result<Status, Error> {
363 let r = T::regs();
364 let deadline = Instant::now() + timeout;
365 loop {
366 if r.events_error.read().bits() != 0 {
367 r.events_error.reset();
368 r.tasks_stop.write(|w| unsafe { w.bits(1) });
369 while r.events_stopped.read().bits() == 0 {}
370 return Err(Error::Overflow);
371 }
372 if r.events_stopped.read().bits() != 0 {
373 r.events_stopped.reset();
374 return Err(Error::Bus);
375 }
376 if r.events_read.read().bits() != 0 {
377 r.events_read.reset();
378 return Ok(Status::Read);
379 }
380 if r.events_write.read().bits() != 0 {
381 r.events_write.reset();
382 return Ok(Status::Write);
383 }
384 if Instant::now() > deadline {
385 r.tasks_stop.write(|w| unsafe { w.bits(1) });
386 return Err(Error::Timeout);
387 }
388 }
389 }
390
391 /// Wait for stop, repeated start or error with timeout
392 #[cfg(feature = "time")]
393 fn blocking_listen_wait_end_timeout(&mut self, status: Status, timeout: Duration) -> Result<Command, Error> {
394 let r = T::regs();
395 let deadline = Instant::now() + timeout;
396 loop {
397 // stop if an error occured
398 if r.events_error.read().bits() != 0 {
399 r.events_error.reset();
400 r.tasks_stop.write(|w| unsafe { w.bits(1) });
401 return Err(Error::Overflow);
402 } else if r.events_stopped.read().bits() != 0 {
403 r.events_stopped.reset();
404 return match status {
405 Status::Read => Ok(Command::Read),
406 Status::Write => {
407 let n = r.rxd.amount.read().bits() as usize;
408 Ok(Command::Write(n))
409 }
410 };
411 } else if r.events_read.read().bits() != 0 {
412 r.events_read.reset();
413 let n = r.rxd.amount.read().bits() as usize;
414 return Ok(Command::WriteRead(n));
415 } else if Instant::now() > deadline {
416 r.tasks_stop.write(|w| unsafe { w.bits(1) });
417 return Err(Error::Timeout);
418 }
419 }
420 }
421
422 /// Wait for stop or error
423 fn async_wait(&mut self) -> impl Future<Output = Result<usize, Error>> {
424 poll_fn(move |cx| {
425 let r = T::regs();
426 let s = T::state();
427
428 s.waker.register(cx.waker());
429
430 // stop if an error occured
431 if r.events_error.read().bits() != 0 {
432 r.events_error.reset();
433 r.tasks_stop.write(|w| unsafe { w.bits(1) });
434 let errorsrc = r.errorsrc.read();
435 if errorsrc.overread().is_detected() {
436 return Poll::Ready(Err(Error::OverRead));
437 } else if errorsrc.dnack().is_received() {
438 return Poll::Ready(Err(Error::DataNack));
439 } else {
440 return Poll::Ready(Err(Error::Bus));
441 }
442 } else if r.events_stopped.read().bits() != 0 {
443 r.events_stopped.reset();
444 let n = r.txd.amount.read().bits() as usize;
445 return Poll::Ready(Ok(n));
446 }
447
448 Poll::Pending
449 })
450 }
451
452 /// Wait for read or write
453 fn async_listen_wait(&mut self) -> impl Future<Output = Result<Status, Error>> {
454 poll_fn(move |cx| {
455 let r = T::regs();
456 let s = T::state();
457
458 s.waker.register(cx.waker());
459
460 // stop if an error occured
461 if r.events_error.read().bits() != 0 {
462 r.events_error.reset();
463 r.tasks_stop.write(|w| unsafe { w.bits(1) });
464 return Poll::Ready(Err(Error::Overflow));
465 } else if r.events_read.read().bits() != 0 {
466 r.events_read.reset();
467 return Poll::Ready(Ok(Status::Read));
468 } else if r.events_write.read().bits() != 0 {
469 r.events_write.reset();
470 return Poll::Ready(Ok(Status::Write));
471 } else if r.events_stopped.read().bits() != 0 {
472 r.events_stopped.reset();
473 return Poll::Ready(Err(Error::Bus));
474 }
475 Poll::Pending
476 })
477 }
478
479 /// Wait for stop, repeated start or error
480 fn async_listen_wait_end(&mut self, status: Status) -> impl Future<Output = Result<Command, Error>> {
481 poll_fn(move |cx| {
482 let r = T::regs();
483 let s = T::state();
484
485 s.waker.register(cx.waker());
486
487 // stop if an error occured
488 if r.events_error.read().bits() != 0 {
489 r.events_error.reset();
490 r.tasks_stop.write(|w| unsafe { w.bits(1) });
491 return Poll::Ready(Err(Error::Overflow));
492 } else if r.events_stopped.read().bits() != 0 {
493 r.events_stopped.reset();
494 return match status {
495 Status::Read => Poll::Ready(Ok(Command::Read)),
496 Status::Write => {
497 let n = r.rxd.amount.read().bits() as usize;
498 Poll::Ready(Ok(Command::Write(n)))
499 }
500 };
501 } else if r.events_read.read().bits() != 0 {
502 r.events_read.reset();
503 let n = r.rxd.amount.read().bits() as usize;
504 return Poll::Ready(Ok(Command::WriteRead(n)));
505 }
506 Poll::Pending
507 })
508 }
509
510 fn setup_respond_from_ram(&mut self, buffer: &[u8], inten: bool) -> Result<(), Error> {
511 let r = T::regs();
512
513 compiler_fence(SeqCst);
514
515 // Set up the DMA write.
516 unsafe { self.set_tx_buffer(buffer)? };
517
518 // Clear events
519 r.events_stopped.reset();
520 r.events_error.reset();
521 self.clear_errorsrc();
522
523 if inten {
524 r.intenset.write(|w| w.stopped().set().error().set());
525 } else {
526 r.intenclr.write(|w| w.stopped().clear().error().clear());
527 }
528
529 // Start write operation.
530 r.tasks_preparetx.write(|w| unsafe { w.bits(1) });
531 r.tasks_resume.write(|w| unsafe { w.bits(1) });
532 Ok(())
533 }
534
535 fn setup_respond(&mut self, wr_buffer: &[u8], inten: bool) -> Result<(), Error> {
536 match self.setup_respond_from_ram(wr_buffer, inten) {
537 Ok(_) => Ok(()),
538 Err(Error::DMABufferNotInDataMemory) => {
539 trace!("Copying TWIS tx buffer into RAM for DMA");
540 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
541 tx_ram_buf.copy_from_slice(wr_buffer);
542 self.setup_respond_from_ram(&tx_ram_buf, inten)
543 }
544 Err(error) => Err(error),
545 }
546 }
547
548 fn setup_listen(&mut self, buffer: &mut [u8], inten: bool) -> Result<(), Error> {
549 let r = T::regs();
550 compiler_fence(SeqCst);
551
552 // Set up the DMA read.
553 unsafe { self.set_rx_buffer(buffer)? };
554
555 // Clear events
556 r.events_read.reset();
557 r.events_write.reset();
558 r.events_stopped.reset();
559 r.events_error.reset();
560 self.clear_errorsrc();
561
562 if inten {
563 r.intenset
564 .write(|w| w.stopped().set().error().set().read().set().write().set());
565 } else {
566 r.intenclr
567 .write(|w| w.stopped().clear().error().clear().read().clear().write().clear());
568 }
569
570 // Start read operation.
571 r.tasks_preparerx.write(|w| unsafe { w.bits(1) });
572
573 Ok(())
574 }
575
576 fn setup_listen_end(&mut self, inten: bool) -> Result<(), Error> {
577 let r = T::regs();
578 compiler_fence(SeqCst);
579
580 // Clear events
581 r.events_read.reset();
582 r.events_write.reset();
583 r.events_stopped.reset();
584 r.events_error.reset();
585 self.clear_errorsrc();
586
587 if inten {
588 r.intenset.write(|w| w.stopped().set().error().set().read().set());
589 } else {
590 r.intenclr.write(|w| w.stopped().clear().error().clear().read().clear());
591 }
592
593 Ok(())
594 }
595
596 /// Wait for commands from an I2C master.
597 /// `buffer` is provided in case master does a 'write' and is unused for 'read'.
598 /// The buffer must have a length of at most 255 bytes on the nRF52832
599 /// and at most 65535 bytes on the nRF52840.
600 /// To know which one of the addresses were matched, call `address_match` or `address_match_index`
601 pub fn blocking_listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
602 self.setup_listen(buffer, false)?;
603 let status = self.blocking_listen_wait()?;
604 if status == Status::Write {
605 self.setup_listen_end(false)?;
606 let command = self.blocking_listen_wait_end(status)?;
607 return Ok(command);
608 }
609 Ok(Command::Read)
610 }
611
612 /// Respond to an I2C master READ command.
613 /// Returns the number of bytes written.
614 /// The buffer must have a length of at most 255 bytes on the nRF52832
615 /// and at most 65535 bytes on the nRF52840.
616 pub fn blocking_respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
617 self.setup_respond(buffer, false)?;
618 self.blocking_wait()
619 }
620
621 /// Same as [`blocking_respond_to_read`](Twis::blocking_respond_to_read) but will fail instead of copying data into RAM.
622 /// Consult the module level documentation to learn more.
623 pub fn blocking_respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
624 self.setup_respond_from_ram(buffer, false)?;
625 self.blocking_wait()
626 }
627
628 // ===========================================
629
630 /// Wait for commands from an I2C master, with timeout.
631 /// `buffer` is provided in case master does a 'write' and is unused for 'read'.
632 /// The buffer must have a length of at most 255 bytes on the nRF52832
633 /// and at most 65535 bytes on the nRF52840.
634 /// To know which one of the addresses were matched, call `address_match` or `address_match_index`
635 #[cfg(feature = "time")]
636 pub fn blocking_listen_timeout(&mut self, buffer: &mut [u8], timeout: Duration) -> Result<Command, Error> {
637 self.setup_listen(buffer, false)?;
638 let status = self.blocking_listen_wait_timeout(timeout)?;
639 if status == Status::Write {
640 self.setup_listen_end(false)?;
641 let command = self.blocking_listen_wait_end_timeout(status, timeout)?;
642 return Ok(command);
643 }
644 Ok(Command::Read)
645 }
646
647 /// Respond to an I2C master READ command with timeout.
648 /// Returns the number of bytes written.
649 /// See [`blocking_respond_to_read`].
650 #[cfg(feature = "time")]
651 pub fn blocking_respond_to_read_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<usize, Error> {
652 self.setup_respond(buffer, false)?;
653 self.blocking_wait_timeout(timeout)
654 }
655
656 /// Same as [`blocking_respond_to_read_timeout`](Twis::blocking_respond_to_read_timeout) but will fail instead of copying data into RAM.
657 /// Consult the module level documentation to learn more.
658 #[cfg(feature = "time")]
659 pub fn blocking_respond_to_read_from_ram_timeout(
660 &mut self,
661 buffer: &[u8],
662 timeout: Duration,
663 ) -> Result<usize, Error> {
664 self.setup_respond_from_ram(buffer, false)?;
665 self.blocking_wait_timeout(timeout)
666 }
667
668 // ===========================================
669
670 /// Wait asynchronously for commands from an I2C master.
671 /// `buffer` is provided in case master does a 'write' and is unused for 'read'.
672 /// The buffer must have a length of at most 255 bytes on the nRF52832
673 /// and at most 65535 bytes on the nRF52840.
674 /// To know which one of the addresses were matched, call `address_match` or `address_match_index`
675 pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
676 self.setup_listen(buffer, true)?;
677 let status = self.async_listen_wait().await?;
678 if status == Status::Write {
679 self.setup_listen_end(true)?;
680 let command = self.async_listen_wait_end(status).await?;
681 return Ok(command);
682 }
683 Ok(Command::Read)
684 }
685
686 /// Respond to an I2C master READ command, asynchronously.
687 /// Returns the number of bytes written.
688 /// The buffer must have a length of at most 255 bytes on the nRF52832
689 /// and at most 65535 bytes on the nRF52840.
690 pub async fn respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
691 self.setup_respond(buffer, true)?;
692 self.async_wait().await
693 }
694
695 /// Same as [`respond_to_read`](Twis::respond_to_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
696 pub async fn respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
697 self.setup_respond_from_ram(buffer, true)?;
698 self.async_wait().await
699 }
700}
701
702impl<'a, T: Instance> Drop for Twis<'a, T> {
703 fn drop(&mut self) {
704 trace!("twis drop");
705
706 // TODO: check for abort
707
708 // disable!
709 let r = T::regs();
710 r.enable.write(|w| w.enable().disabled());
711
712 gpio::deconfigure_pin(r.psel.sda.read().bits());
713 gpio::deconfigure_pin(r.psel.scl.read().bits());
714
715 trace!("twis drop: done");
716 }
717}
718
719pub(crate) mod sealed {
720 use super::*;
721
722 pub struct State {
723 pub waker: AtomicWaker,
724 }
725
726 impl State {
727 pub const fn new() -> Self {
728 Self {
729 waker: AtomicWaker::new(),
730 }
731 }
732 }
733
734 pub trait Instance {
735 fn regs() -> &'static pac::twis0::RegisterBlock;
736 fn state() -> &'static State;
737 }
738}
739
740pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
741 type Interrupt: Interrupt;
742}
743
744macro_rules! impl_twis {
745 ($type:ident, $pac_type:ident, $irq:ident) => {
746 impl crate::twis::sealed::Instance for peripherals::$type {
747 fn regs() -> &'static pac::twis0::RegisterBlock {
748 unsafe { &*pac::$pac_type::ptr() }
749 }
750 fn state() -> &'static crate::twis::sealed::State {
751 static STATE: crate::twis::sealed::State = crate::twis::sealed::State::new();
752 &STATE
753 }
754 }
755 impl crate::twis::Instance for peripherals::$type {
756 type Interrupt = crate::interrupt::$irq;
757 }
758 };
759}
diff --git a/examples/nrf/src/bin/twis.rs b/examples/nrf/src/bin/twis.rs
new file mode 100644
index 000000000..54cba9494
--- /dev/null
+++ b/examples/nrf/src/bin/twis.rs
@@ -0,0 +1,46 @@
1//! TWIS example
2
3#![no_std]
4#![no_main]
5#![feature(type_alias_impl_trait)]
6
7use defmt::*;
8use embassy_executor::Spawner;
9use embassy_nrf::interrupt;
10use embassy_nrf::twis::{self, Command, Twis};
11use {defmt_rtt as _, panic_probe as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default());
16
17 let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
18 let mut config = twis::Config::default();
19 // Set i2c address
20 config.address0 = 0x55;
21 let mut i2c = Twis::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
22
23 info!("Listening...");
24 loop {
25 let response = [1, 2, 3, 4, 5, 6, 7, 8];
26 // This buffer is used if the i2c master performs a Write or WriteRead
27 let mut buf = [0u8; 16];
28 match i2c.listen(&mut buf).await {
29 Ok(Command::Read) => {
30 info!("Got READ command. Respond with data:\n{:?}\n", response);
31 if let Err(e) = i2c.respond_to_read(&response).await {
32 error!("{:?}", e);
33 }
34 }
35 Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]),
36 Ok(Command::WriteRead(n)) => {
37 info!("Got WRITE/READ command with data:\n{:?}", buf[..n]);
38 info!("Respond with data:\n{:?}\n", response);
39 if let Err(e) = i2c.respond_to_read(&response).await {
40 error!("{:?}", e);
41 }
42 }
43 Err(e) => error!("{:?}", e),
44 }
45 }
46}