aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorJakob <[email protected]>2025-05-14 18:57:49 +0200
committerGitHub <[email protected]>2025-05-14 18:57:49 +0200
commitb17da5b79470cb6b9877ec9fd5682062f7a37aec (patch)
tree4d60a3e4b9404a8b566b069358d700a6cfb5f8b2 /embassy-nrf/src
parenta71642ca01190d1a8f8bd652bd41d8a9539fe2ee (diff)
parentb9ed61cdd99be4a58a757a0eb32c1fa77a696d6a (diff)
Merge branch 'embassy-rs:main' into update_doc_comment_for_adc_read
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs5
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs5
-rw-r--r--embassy-nrf/src/ipc.rs363
-rw-r--r--embassy-nrf/src/lib.rs2
-rw-r--r--embassy-nrf/src/radio/ble.rs394
-rw-r--r--embassy-nrf/src/radio/ieee802154.rs7
-rw-r--r--embassy-nrf/src/radio/mod.rs8
-rw-r--r--embassy-nrf/src/twim.rs171
8 files changed, 409 insertions, 546 deletions
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 0103fa7ae..99cf29487 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -262,6 +262,9 @@ embassy_hal_internal::peripherals! {
262 PPI_GROUP4, 262 PPI_GROUP4,
263 PPI_GROUP5, 263 PPI_GROUP5,
264 264
265 // IPC
266 IPC,
267
265 // GPIO port 0 268 // GPIO port 0
266 #[cfg(feature = "lfxo-pins-as-gpio")] 269 #[cfg(feature = "lfxo-pins-as-gpio")]
267 P0_00, 270 P0_00,
@@ -327,6 +330,8 @@ embassy_hal_internal::peripherals! {
327 EGU5, 330 EGU5,
328} 331}
329 332
333impl_ipc!(IPC, IPC, IPC);
334
330impl_usb!(USBD, USBD, USBD); 335impl_usb!(USBD, USBD, USBD);
331 336
332impl_uarte!(SERIAL0, UARTE0, SERIAL0); 337impl_uarte!(SERIAL0, UARTE0, SERIAL0);
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index 22d33d080..c2932be31 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -141,6 +141,9 @@ embassy_hal_internal::peripherals! {
141 PPI_GROUP4, 141 PPI_GROUP4,
142 PPI_GROUP5, 142 PPI_GROUP5,
143 143
144 // IPC
145 IPC,
146
144 // GPIO port 0 147 // GPIO port 0
145 P0_00, 148 P0_00,
146 P0_01, 149 P0_01,
@@ -200,6 +203,8 @@ embassy_hal_internal::peripherals! {
200 EGU0, 203 EGU0,
201} 204}
202 205
206impl_ipc!(IPC, IPC, IPC);
207
203impl_uarte!(SERIAL0, UARTE0, SERIAL0); 208impl_uarte!(SERIAL0, UARTE0, SERIAL0);
204impl_spim!(SERIAL0, SPIM0, SERIAL0); 209impl_spim!(SERIAL0, SPIM0, SERIAL0);
205impl_spis!(SERIAL0, SPIS0, SERIAL0); 210impl_spis!(SERIAL0, SPIS0, SERIAL0);
diff --git a/embassy-nrf/src/ipc.rs b/embassy-nrf/src/ipc.rs
new file mode 100644
index 000000000..a8a08c911
--- /dev/null
+++ b/embassy-nrf/src/ipc.rs
@@ -0,0 +1,363 @@
1//! InterProcessor Communication (IPC)
2
3#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::task::Poll;
8
9use embassy_hal_internal::{Peri, PeripheralType};
10use embassy_sync::waitqueue::AtomicWaker;
11
12use crate::interrupt::typelevel::Interrupt;
13use crate::{interrupt, pac, ppi};
14
15const EVENT_COUNT: usize = 16;
16
17/// IPC Event
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub enum EventNumber {
20 /// IPC Event 0
21 Event0 = 0,
22 /// IPC Event 1
23 Event1 = 1,
24 /// IPC Event 2
25 Event2 = 2,
26 /// IPC Event 3
27 Event3 = 3,
28 /// IPC Event 4
29 Event4 = 4,
30 /// IPC Event 5
31 Event5 = 5,
32 /// IPC Event 6
33 Event6 = 6,
34 /// IPC Event 7
35 Event7 = 7,
36 /// IPC Event 8
37 Event8 = 8,
38 /// IPC Event 9
39 Event9 = 9,
40 /// IPC Event 10
41 Event10 = 10,
42 /// IPC Event 11
43 Event11 = 11,
44 /// IPC Event 12
45 Event12 = 12,
46 /// IPC Event 13
47 Event13 = 13,
48 /// IPC Event 14
49 Event14 = 14,
50 /// IPC Event 15
51 Event15 = 15,
52}
53
54const EVENTS: [EventNumber; EVENT_COUNT] = [
55 EventNumber::Event0,
56 EventNumber::Event1,
57 EventNumber::Event2,
58 EventNumber::Event3,
59 EventNumber::Event4,
60 EventNumber::Event5,
61 EventNumber::Event6,
62 EventNumber::Event7,
63 EventNumber::Event8,
64 EventNumber::Event9,
65 EventNumber::Event10,
66 EventNumber::Event11,
67 EventNumber::Event12,
68 EventNumber::Event13,
69 EventNumber::Event14,
70 EventNumber::Event15,
71];
72
73/// IPC Channel
74#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
75pub enum IpcChannel {
76 /// IPC Channel 0
77 Channel0,
78 /// IPC Channel 1
79 Channel1,
80 /// IPC Channel 2
81 Channel2,
82 /// IPC Channel 3
83 Channel3,
84 /// IPC Channel 4
85 Channel4,
86 /// IPC Channel 5
87 Channel5,
88 /// IPC Channel 6
89 Channel6,
90 /// IPC Channel 7
91 Channel7,
92 /// IPC Channel 8
93 Channel8,
94 /// IPC Channel 9
95 Channel9,
96 /// IPC Channel 10
97 Channel10,
98 /// IPC Channel 11
99 Channel11,
100 /// IPC Channel 12
101 Channel12,
102 /// IPC Channel 13
103 Channel13,
104 /// IPC Channel 14
105 Channel14,
106 /// IPC Channel 15
107 Channel15,
108}
109
110impl IpcChannel {
111 fn mask(self) -> u32 {
112 1 << (self as u32)
113 }
114}
115
116/// Interrupt Handler
117pub struct InterruptHandler<T: Instance> {
118 _phantom: PhantomData<T>,
119}
120
121impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
122 unsafe fn on_interrupt() {
123 let regs = T::regs();
124
125 // Check if an event was generated, and if it was, trigger the corresponding waker
126 for event in EVENTS {
127 if regs.events_receive(event as usize).read() & 0x01 == 0x01 {
128 regs.intenclr().write(|w| w.0 = 0x01 << event as u32);
129 T::state().wakers[event as usize].wake();
130 }
131 }
132 }
133}
134
135/// IPC driver
136#[non_exhaustive]
137pub struct Ipc<'d, T: Instance> {
138 /// Event 0
139 pub event0: Event<'d, T>,
140 /// Event 1
141 pub event1: Event<'d, T>,
142 /// Event 2
143 pub event2: Event<'d, T>,
144 /// Event 3
145 pub event3: Event<'d, T>,
146 /// Event 4
147 pub event4: Event<'d, T>,
148 /// Event 5
149 pub event5: Event<'d, T>,
150 /// Event 6
151 pub event6: Event<'d, T>,
152 /// Event 7
153 pub event7: Event<'d, T>,
154 /// Event 8
155 pub event8: Event<'d, T>,
156 /// Event 9
157 pub event9: Event<'d, T>,
158 /// Event 10
159 pub event10: Event<'d, T>,
160 /// Event 11
161 pub event11: Event<'d, T>,
162 /// Event 12
163 pub event12: Event<'d, T>,
164 /// Event 13
165 pub event13: Event<'d, T>,
166 /// Event 14
167 pub event14: Event<'d, T>,
168 /// Event 15
169 pub event15: Event<'d, T>,
170}
171
172impl<'d, T: Instance> Ipc<'d, T> {
173 /// Create a new IPC driver.
174 pub fn new(
175 _p: Peri<'d, T>,
176 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
177 ) -> Self {
178 T::Interrupt::unpend();
179 unsafe { T::Interrupt::enable() };
180
181 let _phantom = PhantomData;
182 #[rustfmt::skip]
183 let r = Self { // attributes on expressions are experimental
184 event0: Event { number: EventNumber::Event0, _phantom },
185 event1: Event { number: EventNumber::Event1, _phantom },
186 event2: Event { number: EventNumber::Event2, _phantom },
187 event3: Event { number: EventNumber::Event3, _phantom },
188 event4: Event { number: EventNumber::Event4, _phantom },
189 event5: Event { number: EventNumber::Event5, _phantom },
190 event6: Event { number: EventNumber::Event6, _phantom },
191 event7: Event { number: EventNumber::Event7, _phantom },
192 event8: Event { number: EventNumber::Event8, _phantom },
193 event9: Event { number: EventNumber::Event9, _phantom },
194 event10: Event { number: EventNumber::Event10, _phantom },
195 event11: Event { number: EventNumber::Event11, _phantom },
196 event12: Event { number: EventNumber::Event12, _phantom },
197 event13: Event { number: EventNumber::Event13, _phantom },
198 event14: Event { number: EventNumber::Event14, _phantom },
199 event15: Event { number: EventNumber::Event15, _phantom },
200 };
201 r
202 }
203}
204
205/// IPC event
206pub struct Event<'d, T: Instance> {
207 number: EventNumber,
208 _phantom: PhantomData<&'d T>,
209}
210
211impl<'d, T: Instance> Event<'d, T> {
212 /// Trigger the event.
213 pub fn trigger(&self) {
214 let nr = self.number;
215 T::regs().tasks_send(nr as usize).write_value(1);
216 }
217
218 /// Wait for the event to be triggered.
219 pub async fn wait(&mut self) {
220 let regs = T::regs();
221 let nr = self.number as usize;
222 regs.intenset().write(|w| w.0 = 1 << nr);
223 poll_fn(|cx| {
224 T::state().wakers[nr].register(cx.waker());
225
226 if regs.events_receive(nr).read() == 1 {
227 regs.events_receive(nr).write_value(0x00);
228 Poll::Ready(())
229 } else {
230 Poll::Pending
231 }
232 })
233 .await;
234 }
235
236 /// Returns the [`EventNumber`] of the event.
237 pub fn number(&self) -> EventNumber {
238 self.number
239 }
240
241 /// Create a handle that can trigger the event.
242 pub fn trigger_handle(&self) -> EventTrigger<'d, T> {
243 EventTrigger {
244 number: self.number,
245 _phantom: PhantomData,
246 }
247 }
248
249 /// Configure the channels the event will broadcast to
250 pub fn configure_trigger<I: IntoIterator<Item = IpcChannel>>(&mut self, channels: I) {
251 T::regs().send_cnf(self.number as usize).write(|w| {
252 for channel in channels {
253 w.0 |= channel.mask();
254 }
255 })
256 }
257
258 /// Configure the channels the event will listen on
259 pub fn configure_wait<I: IntoIterator<Item = IpcChannel>>(&mut self, channels: I) {
260 T::regs().receive_cnf(self.number as usize).write(|w| {
261 for channel in channels {
262 w.0 |= channel.mask();
263 }
264 });
265 }
266
267 /// Get the task for the IPC event to use with PPI.
268 pub fn task(&self) -> ppi::Task<'d> {
269 let nr = self.number as usize;
270 let regs = T::regs();
271 ppi::Task::from_reg(regs.tasks_send(nr))
272 }
273
274 /// Get the event for the IPC event to use with PPI.
275 pub fn event(&self) -> ppi::Event<'d> {
276 let nr = self.number as usize;
277 let regs = T::regs();
278 ppi::Event::from_reg(regs.events_receive(nr))
279 }
280
281 /// Reborrow into a "child" Event.
282 ///
283 /// `self` will stay borrowed until the child Event is dropped.
284 pub fn reborrow(&mut self) -> Event<'_, T> {
285 Self { ..*self }
286 }
287
288 /// Steal an IPC event by number.
289 ///
290 /// # Safety
291 ///
292 /// The event number must not be in use by another [`Event`].
293 pub unsafe fn steal(number: EventNumber) -> Self {
294 Self {
295 number,
296 _phantom: PhantomData,
297 }
298 }
299}
300
301/// A handle that can trigger an IPC event.
302///
303/// This `struct` is returned by [`Event::trigger_handle`].
304#[derive(Debug, Copy, Clone)]
305pub struct EventTrigger<'d, T: Instance> {
306 number: EventNumber,
307 _phantom: PhantomData<&'d T>,
308}
309
310impl<T: Instance> EventTrigger<'_, T> {
311 /// Trigger the event.
312 pub fn trigger(&self) {
313 let nr = self.number;
314 T::regs().tasks_send(nr as usize).write_value(1);
315 }
316
317 /// Returns the [`EventNumber`] of the event.
318 pub fn number(&self) -> EventNumber {
319 self.number
320 }
321}
322
323pub(crate) struct State {
324 wakers: [AtomicWaker; EVENT_COUNT],
325}
326
327impl State {
328 pub(crate) const fn new() -> Self {
329 Self {
330 wakers: [const { AtomicWaker::new() }; EVENT_COUNT],
331 }
332 }
333}
334
335pub(crate) trait SealedInstance {
336 fn regs() -> pac::ipc::Ipc;
337 fn state() -> &'static State;
338}
339
340/// IPC peripheral instance.
341#[allow(private_bounds)]
342pub trait Instance: PeripheralType + SealedInstance + 'static + Send {
343 /// Interrupt for this peripheral.
344 type Interrupt: interrupt::typelevel::Interrupt;
345}
346
347macro_rules! impl_ipc {
348 ($type:ident, $pac_type:ident, $irq:ident) => {
349 impl crate::ipc::SealedInstance for peripherals::$type {
350 fn regs() -> pac::ipc::Ipc {
351 pac::$pac_type
352 }
353
354 fn state() -> &'static crate::ipc::State {
355 static STATE: crate::ipc::State = crate::ipc::State::new();
356 &STATE
357 }
358 }
359 impl crate::ipc::Instance for peripherals::$type {
360 type Interrupt = crate::interrupt::typelevel::$irq;
361 }
362 };
363}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 07ba2f6d4..5bce65a98 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -88,6 +88,8 @@ pub mod gpiote;
88#[cfg(not(feature = "_nrf54l"))] // TODO 88#[cfg(not(feature = "_nrf54l"))] // TODO
89#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))] 89#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
90pub mod i2s; 90pub mod i2s;
91#[cfg(feature = "_nrf5340")]
92pub mod ipc;
91#[cfg(not(feature = "_nrf54l"))] // TODO 93#[cfg(not(feature = "_nrf54l"))] // TODO
92#[cfg(any( 94#[cfg(any(
93 feature = "nrf52832", 95 feature = "nrf52832",
diff --git a/embassy-nrf/src/radio/ble.rs b/embassy-nrf/src/radio/ble.rs
deleted file mode 100644
index d42bbe5f6..000000000
--- a/embassy-nrf/src/radio/ble.rs
+++ /dev/null
@@ -1,394 +0,0 @@
1//! Radio driver implementation focused on Bluetooth Low-Energy transmission.
2
3use core::future::poll_fn;
4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll;
6
7use embassy_hal_internal::drop::OnDrop;
8pub use pac::radio::vals::Mode;
9#[cfg(not(feature = "_nrf51"))]
10use pac::radio::vals::Plen as PreambleLength;
11
12use crate::interrupt::typelevel::Interrupt;
13use crate::pac::radio::vals;
14use crate::radio::*;
15pub use crate::radio::{Error, TxPower};
16use crate::util::slice_in_ram_or;
17use crate::Peri;
18
19/// Radio driver.
20pub struct Radio<'d, T: Instance> {
21 _p: Peri<'d, T>,
22}
23
24impl<'d, T: Instance> Radio<'d, T> {
25 /// Create a new radio driver.
26 pub fn new(
27 radio: Peri<'d, T>,
28 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
29 ) -> Self {
30 let r = T::regs();
31
32 r.pcnf1().write(|w| {
33 // It is 0 bytes long in a standard BLE packet
34 w.set_statlen(0);
35 // MaxLen configures the maximum packet payload plus add-on size in
36 // number of bytes that can be transmitted or received by the RADIO. This feature can be used to ensure
37 // that the RADIO does not overwrite, or read beyond, the RAM assigned to the packet payload. This means
38 // that if the packet payload length defined by PCNF1.STATLEN and the LENGTH field in the packet specifies a
39 // packet larger than MAXLEN, the payload will be truncated at MAXLEN
40 //
41 // To simplify the implementation, It is setted as the maximum value
42 // and the length of the packet is controlled only by the LENGTH field in the packet
43 w.set_maxlen(255);
44 // Configure the length of the address field in the packet
45 // The prefix after the address fields is always appended, so is always 1 byte less than the size of the address
46 // The base address is truncated from the least significant byte if the BALEN is less than 4
47 //
48 // BLE address is always 4 bytes long
49 w.set_balen(3); // 3 bytes base address (+ 1 prefix);
50 // Configure the endianess
51 // For BLE is always little endian (LSB first)
52 w.set_endian(vals::Endian::LITTLE);
53 // Data whitening is used to avoid long sequences of zeros or
54 // ones, e.g., 0b0000000 or 0b1111111, in the data bit stream.
55 // The whitener and de-whitener are defined the same way,
56 // using a 7-bit linear feedback shift register with the
57 // polynomial x7 + x4 + 1.
58 //
59 // In BLE Whitening shall be applied on the PDU and CRC of all
60 // Link Layer packets and is performed after the CRC generation
61 // in the transmitter. No other parts of the packets are whitened.
62 // De-whitening is performed before the CRC checking in the receiver
63 // Before whitening or de-whitening, the shift register should be
64 // initialized based on the channel index.
65 w.set_whiteen(true);
66 });
67
68 // Configure CRC
69 r.crccnf().write(|w| {
70 // In BLE the CRC shall be calculated on the PDU of all Link Layer
71 // packets (even if the packet is encrypted).
72 // It skips the address field
73 w.set_skipaddr(vals::Skipaddr::SKIP);
74 // In BLE 24-bit CRC = 3 bytes
75 w.set_len(vals::Len::THREE);
76 });
77
78 // Ch map between 2400 MHZ .. 2500 MHz
79 // All modes use this range
80 #[cfg(not(feature = "_nrf51"))]
81 r.frequency().write(|w| w.set_map(vals::Map::DEFAULT));
82
83 // Configure shortcuts to simplify and speed up sending and receiving packets.
84 r.shorts().write(|w| {
85 // start transmission/recv immediately after ramp-up
86 // disable radio when transmission/recv is done
87 w.set_ready_start(true);
88 w.set_end_disable(true);
89 });
90
91 // Enable NVIC interrupt
92 T::Interrupt::unpend();
93 unsafe { T::Interrupt::enable() };
94
95 Self { _p: radio }
96 }
97
98 fn state(&self) -> RadioState {
99 super::state(T::regs())
100 }
101
102 /// Set the radio mode
103 ///
104 /// The radio must be disabled before calling this function
105 pub fn set_mode(&mut self, mode: Mode) {
106 assert!(self.state() == RadioState::DISABLED);
107
108 let r = T::regs();
109 r.mode().write(|w| w.set_mode(mode));
110
111 #[cfg(not(feature = "_nrf51"))]
112 r.pcnf0().write(|w| {
113 w.set_plen(match mode {
114 Mode::BLE_1MBIT => PreambleLength::_8BIT,
115 Mode::BLE_2MBIT => PreambleLength::_16BIT,
116 #[cfg(any(
117 feature = "nrf52811",
118 feature = "nrf52820",
119 feature = "nrf52833",
120 feature = "nrf52840",
121 feature = "_nrf5340-net"
122 ))]
123 Mode::BLE_LR125KBIT | Mode::BLE_LR500KBIT => PreambleLength::LONG_RANGE,
124 _ => unimplemented!(),
125 })
126 });
127 }
128
129 /// Set the header size changing the S1's len field
130 ///
131 /// The radio must be disabled before calling this function
132 pub fn set_header_expansion(&mut self, use_s1_field: bool) {
133 assert!(self.state() == RadioState::DISABLED);
134
135 let r = T::regs();
136
137 // s1 len in bits
138 let s1len: u8 = match use_s1_field {
139 false => 0,
140 true => 8,
141 };
142
143 r.pcnf0().write(|w| {
144 // Configure S0 to 1 byte length, this will represent the Data/Adv header flags
145 w.set_s0len(true);
146 // Configure the length (in bits) field to 1 byte length, this will represent the length of the payload
147 // and also be used to know how many bytes to read/write from/to the buffer
148 w.set_lflen(0);
149 // Configure the lengh (in bits) of bits in the S1 field. It could be used to represent the CTEInfo for data packages in BLE.
150 w.set_s1len(s1len);
151 });
152 }
153
154 /// Set initial data whitening value
155 /// Data whitening is used to avoid long sequences of zeros or ones, e.g., 0b0000000 or 0b1111111, in the data bit stream
156 /// On BLE the initial value is the channel index | 0x40
157 ///
158 /// The radio must be disabled before calling this function
159 pub fn set_whitening_init(&mut self, whitening_init: u8) {
160 assert!(self.state() == RadioState::DISABLED);
161
162 let r = T::regs();
163
164 r.datawhiteiv().write(|w| w.set_datawhiteiv(whitening_init));
165 }
166
167 /// Set the central frequency to be used
168 /// It should be in the range 2400..2500
169 ///
170 /// [The radio must be disabled before calling this function](https://devzone.nordicsemi.com/f/nordic-q-a/15829/radio-frequency-change)
171 pub fn set_frequency(&mut self, frequency: u32) {
172 assert!(self.state() == RadioState::DISABLED);
173 assert!((2400..=2500).contains(&frequency));
174
175 let r = T::regs();
176
177 r.frequency().write(|w| w.set_frequency((frequency - 2400) as u8));
178 }
179
180 /// Set the acess address
181 /// This address is always constants for advertising
182 /// And a random value generate on each connection
183 /// It is used to filter the packages
184 ///
185 /// The radio must be disabled before calling this function
186 pub fn set_access_address(&mut self, access_address: u32) {
187 assert!(self.state() == RadioState::DISABLED);
188
189 let r = T::regs();
190
191 // Configure logical address
192 // The byte ordering on air is always least significant byte first for the address
193 // So for the address 0xAA_BB_CC_DD, the address on air will be DD CC BB AA
194 // The package order is BASE, PREFIX so BASE=0xBB_CC_DD and PREFIX=0xAA
195 r.prefix0().write(|w| w.set_ap0((access_address >> 24) as u8));
196
197 // The base address is truncated from the least significant byte (because the BALEN is less than 4)
198 // So it shifts the address to the right
199 r.base0().write_value(access_address << 8);
200
201 // Don't match tx address
202 r.txaddress().write(|w| w.set_txaddress(0));
203
204 // Match on logical address
205 // This config only filter the packets by the address,
206 // so only packages send to the previous address
207 // will finish the reception (TODO: check the explanation)
208 r.rxaddresses().write(|w| {
209 w.set_addr0(true);
210 w.set_addr1(true);
211 w.set_addr2(true);
212 w.set_addr3(true);
213 w.set_addr4(true);
214 });
215 }
216
217 /// Set the CRC polynomial
218 /// It only uses the 24 least significant bits
219 ///
220 /// The radio must be disabled before calling this function
221 pub fn set_crc_poly(&mut self, crc_poly: u32) {
222 assert!(self.state() == RadioState::DISABLED);
223
224 let r = T::regs();
225
226 r.crcpoly().write(|w| {
227 // Configure the CRC polynomial
228 // Each term in the CRC polynomial is mapped to a bit in this
229 // register which index corresponds to the term's exponent.
230 // The least significant term/bit is hard-wired internally to
231 // 1, and bit number 0 of the register content is ignored by
232 // the hardware. The following example is for an 8 bit CRC
233 // polynomial: x8 + x7 + x3 + x2 + 1 = 1 1000 1101 .
234 w.set_crcpoly(crc_poly & 0xFFFFFF)
235 });
236 }
237
238 /// Set the CRC init value
239 /// It only uses the 24 least significant bits
240 /// The CRC initial value varies depending of the PDU type
241 ///
242 /// The radio must be disabled before calling this function
243 pub fn set_crc_init(&mut self, crc_init: u32) {
244 assert!(self.state() == RadioState::DISABLED);
245
246 let r = T::regs();
247
248 r.crcinit().write(|w| w.set_crcinit(crc_init & 0xFFFFFF));
249 }
250
251 /// Set the radio tx power
252 ///
253 /// The radio must be disabled before calling this function
254 pub fn set_tx_power(&mut self, tx_power: TxPower) {
255 assert!(self.state() == RadioState::DISABLED);
256
257 let r = T::regs();
258
259 r.txpower().write(|w| w.set_txpower(tx_power));
260 }
261
262 /// Set buffer to read/write
263 ///
264 /// This method is unsound. You should guarantee that the buffer will live
265 /// for the life time of the transmission or if the buffer will be modified.
266 /// Also if the buffer is smaller than the packet length, the radio will
267 /// read/write memory out of the buffer bounds.
268 fn set_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
269 slice_in_ram_or(buffer, Error::BufferNotInRAM)?;
270
271 let r = T::regs();
272
273 // Here it consider that the length of the packet is
274 // correctly set in the buffer, otherwise it will send
275 // unowned regions of memory
276 let ptr = buffer.as_ptr();
277
278 // Configure the payload
279 r.packetptr().write_value(ptr as u32);
280
281 Ok(())
282 }
283
284 /// Send packet
285 /// If the length byte in the package is greater than the buffer length
286 /// the radio will read memory out of the buffer bounds
287 pub async fn transmit(&mut self, buffer: &[u8]) -> Result<(), Error> {
288 self.set_buffer(buffer)?;
289
290 let r = T::regs();
291 self.trigger_and_wait_end(move || {
292 // Initialize the transmission
293 // trace!("txen");
294
295 r.tasks_txen().write_value(1);
296 })
297 .await;
298
299 Ok(())
300 }
301
302 /// Receive packet
303 /// If the length byte in the received package is greater than the buffer length
304 /// the radio will write memory out of the buffer bounds
305 pub async fn receive(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
306 self.set_buffer(buffer)?;
307
308 let r = T::regs();
309 self.trigger_and_wait_end(move || {
310 // Initialize the transmission
311 // trace!("rxen");
312 r.tasks_rxen().write_value(1);
313 })
314 .await;
315
316 Ok(())
317 }
318
319 async fn trigger_and_wait_end(&mut self, trigger: impl FnOnce()) {
320 let r = T::regs();
321 let s = T::state();
322
323 // If the Future is dropped before the end of the transmission
324 // it disable the interrupt and stop the transmission
325 // to keep the state consistent
326 let drop = OnDrop::new(|| {
327 trace!("radio drop: stopping");
328
329 r.intenclr().write(|w| w.set_end(true));
330
331 r.tasks_stop().write_value(1);
332
333 r.events_end().write_value(0);
334
335 trace!("radio drop: stopped");
336 });
337
338 // trace!("radio:enable interrupt");
339 // Clear some remnant side-effects (TODO: check if this is necessary)
340 r.events_end().write_value(0);
341
342 // Enable interrupt
343 r.intenset().write(|w| w.set_end(true));
344
345 compiler_fence(Ordering::SeqCst);
346
347 // Trigger the transmission
348 trigger();
349
350 // On poll check if interrupt happen
351 poll_fn(|cx| {
352 s.event_waker.register(cx.waker());
353 if r.events_end().read() == 1 {
354 // trace!("radio:end");
355 return core::task::Poll::Ready(());
356 }
357 Poll::Pending
358 })
359 .await;
360
361 compiler_fence(Ordering::SeqCst);
362 r.events_end().write_value(0); // ACK
363
364 // Everthing ends fine, so it disable the drop
365 drop.defuse();
366 }
367
368 /// Disable the radio
369 fn disable(&mut self) {
370 let r = T::regs();
371
372 compiler_fence(Ordering::SeqCst);
373 // If it is already disabled, do nothing
374 if self.state() != RadioState::DISABLED {
375 trace!("radio:disable");
376 // Trigger the disable task
377 r.tasks_disable().write_value(1);
378
379 // Wait until the radio is disabled
380 while r.events_disabled().read() == 0 {}
381
382 compiler_fence(Ordering::SeqCst);
383
384 // Acknowledge it
385 r.events_disabled().write_value(0);
386 }
387 }
388}
389
390impl<'d, T: Instance> Drop for Radio<'d, T> {
391 fn drop(&mut self) {
392 self.disable();
393 }
394}
diff --git a/embassy-nrf/src/radio/ieee802154.rs b/embassy-nrf/src/radio/ieee802154.rs
index 2f0bcbe04..7f4f8f462 100644
--- a/embassy-nrf/src/radio/ieee802154.rs
+++ b/embassy-nrf/src/radio/ieee802154.rs
@@ -5,10 +5,11 @@ use core::task::Poll;
5 5
6use embassy_hal_internal::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
7 7
8use super::{state, Error, Instance, InterruptHandler, RadioState, TxPower}; 8use super::{Error, Instance, InterruptHandler, TxPower};
9use crate::interrupt::typelevel::Interrupt; 9use crate::interrupt::typelevel::Interrupt;
10use crate::interrupt::{self}; 10use crate::interrupt::{self};
11use crate::pac::radio::vals; 11use crate::pac::radio::vals;
12pub use crate::pac::radio::vals::State as RadioState;
12use crate::Peri; 13use crate::Peri;
13 14
14/// Default (IEEE compliant) Start of Frame Delimiter 15/// Default (IEEE compliant) Start of Frame Delimiter
@@ -200,7 +201,7 @@ impl<'d, T: Instance> Radio<'d, T> {
200 201
201 /// Get the current radio state 202 /// Get the current radio state
202 fn state(&self) -> RadioState { 203 fn state(&self) -> RadioState {
203 state(T::regs()) 204 T::regs().state().read().state()
204 } 205 }
205 206
206 /// Moves the radio from any state to the DISABLED state 207 /// Moves the radio from any state to the DISABLED state
@@ -293,7 +294,7 @@ impl<'d, T: Instance> Radio<'d, T> {
293 r.shorts().write(|_| {}); 294 r.shorts().write(|_| {});
294 r.tasks_stop().write_value(1); 295 r.tasks_stop().write_value(1);
295 loop { 296 loop {
296 match state(r) { 297 match r.state().read().state() {
297 RadioState::DISABLED | RadioState::RX_IDLE => break, 298 RadioState::DISABLED | RadioState::RX_IDLE => break,
298 _ => (), 299 _ => (),
299 } 300 }
diff --git a/embassy-nrf/src/radio/mod.rs b/embassy-nrf/src/radio/mod.rs
index 982436266..608ef9024 100644
--- a/embassy-nrf/src/radio/mod.rs
+++ b/embassy-nrf/src/radio/mod.rs
@@ -6,7 +6,6 @@
6#![macro_use] 6#![macro_use]
7 7
8/// Bluetooth Low Energy Radio driver. 8/// Bluetooth Low Energy Radio driver.
9pub mod ble;
10#[cfg(any( 9#[cfg(any(
11 feature = "nrf52811", 10 feature = "nrf52811",
12 feature = "nrf52820", 11 feature = "nrf52820",
@@ -21,7 +20,6 @@ use core::marker::PhantomData;
21 20
22use embassy_hal_internal::PeripheralType; 21use embassy_hal_internal::PeripheralType;
23use embassy_sync::waitqueue::AtomicWaker; 22use embassy_sync::waitqueue::AtomicWaker;
24use pac::radio::vals::State as RadioState;
25pub use pac::radio::vals::Txpower as TxPower; 23pub use pac::radio::vals::Txpower as TxPower;
26 24
27use crate::{interrupt, pac}; 25use crate::{interrupt, pac};
@@ -82,6 +80,7 @@ macro_rules! impl_radio {
82 pac::$pac_type 80 pac::$pac_type
83 } 81 }
84 82
83 #[allow(unused)]
85 fn state() -> &'static crate::radio::State { 84 fn state() -> &'static crate::radio::State {
86 static STATE: crate::radio::State = crate::radio::State::new(); 85 static STATE: crate::radio::State = crate::radio::State::new();
87 &STATE 86 &STATE
@@ -99,8 +98,3 @@ pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
99 /// Interrupt for this peripheral. 98 /// Interrupt for this peripheral.
100 type Interrupt: interrupt::typelevel::Interrupt; 99 type Interrupt: interrupt::typelevel::Interrupt;
101} 100}
102
103/// Get the state of the radio
104pub(crate) fn state(radio: pac::radio::Radio) -> RadioState {
105 radio.state().read().state()
106}
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 083b54b99..3d5e841d1 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -4,7 +4,6 @@
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;
8use core::sync::atomic::compiler_fence; 7use core::sync::atomic::compiler_fence;
9use core::sync::atomic::Ordering::SeqCst; 8use core::sync::atomic::Ordering::SeqCst;
10use core::task::Poll; 9use core::task::Poll;
@@ -17,7 +16,7 @@ use embassy_time::{Duration, Instant};
17use embedded_hal_1::i2c::Operation; 16use embedded_hal_1::i2c::Operation;
18pub use pac::twim::vals::Frequency; 17pub use pac::twim::vals::Frequency;
19 18
20use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 19use crate::chip::EASY_DMA_SIZE;
21use crate::gpio::Pin as GpioPin; 20use crate::gpio::Pin as GpioPin;
22use crate::interrupt::typelevel::Interrupt; 21use crate::interrupt::typelevel::Interrupt;
23use crate::pac::gpio::vals as gpiovals; 22use crate::pac::gpio::vals as gpiovals;
@@ -75,8 +74,8 @@ pub enum Error {
75 Transmit, 74 Transmit,
76 /// Data reception failed. 75 /// Data reception failed.
77 Receive, 76 Receive,
78 /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash. 77 /// The buffer is not in data RAM and is larger than the RAM buffer. It's most likely in flash, and nRF's DMA cannot access flash.
79 BufferNotInRAM, 78 RAMBufferTooSmall,
80 /// Didn't receive an ACK bit after the address byte. Address might be wrong, or the i2c device chip might not be connected properly. 79 /// Didn't receive an ACK bit after the address byte. Address might be wrong, or the i2c device chip might not be connected properly.
81 AddressNack, 80 AddressNack,
82 /// Didn't receive an ACK bit after a data byte. 81 /// Didn't receive an ACK bit after a data byte.
@@ -115,16 +114,24 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
115/// TWI driver. 114/// TWI driver.
116pub struct Twim<'d, T: Instance> { 115pub struct Twim<'d, T: Instance> {
117 _p: Peri<'d, T>, 116 _p: Peri<'d, T>,
117 tx_ram_buffer: &'d mut [u8],
118} 118}
119 119
120impl<'d, T: Instance> Twim<'d, T> { 120impl<'d, T: Instance> Twim<'d, T> {
121 /// Create a new TWI driver. 121 /// Create a new TWI driver.
122 ///
123 /// `tx_ram_buffer` is required if any write operations will be performed with data that is not in RAM.
124 /// Usually this is static data that the compiler locates in flash instead of RAM. The `tx_ram_buffer`
125 /// needs to be at least as large as the largest write operation that will be executed with a buffer
126 /// that is not in RAM. If all write operations will be performed from RAM, an empty buffer (`&[]`) may
127 /// be used.
122 pub fn new( 128 pub fn new(
123 twim: Peri<'d, T>, 129 twim: Peri<'d, T>,
124 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 130 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
125 sda: Peri<'d, impl GpioPin>, 131 sda: Peri<'d, impl GpioPin>,
126 scl: Peri<'d, impl GpioPin>, 132 scl: Peri<'d, impl GpioPin>,
127 config: Config, 133 config: Config,
134 tx_ram_buffer: &'d mut [u8],
128 ) -> Self { 135 ) -> Self {
129 let r = T::regs(); 136 let r = T::regs();
130 137
@@ -159,7 +166,10 @@ impl<'d, T: Instance> Twim<'d, T> {
159 // Enable TWIM instance. 166 // Enable TWIM instance.
160 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED)); 167 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
161 168
162 let mut twim = Self { _p: twim }; 169 let mut twim = Self {
170 _p: twim,
171 tx_ram_buffer,
172 };
163 173
164 // Apply runtime peripheral configuration 174 // Apply runtime peripheral configuration
165 Self::set_config(&mut twim, &config).unwrap(); 175 Self::set_config(&mut twim, &config).unwrap();
@@ -174,21 +184,17 @@ impl<'d, T: Instance> Twim<'d, T> {
174 } 184 }
175 185
176 /// Set TX buffer, checking that it is in RAM and has suitable length. 186 /// Set TX buffer, checking that it is in RAM and has suitable length.
177 unsafe fn set_tx_buffer( 187 unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
178 &mut self,
179 buffer: &[u8],
180 ram_buffer: Option<&mut [MaybeUninit<u8>; FORCE_COPY_BUFFER_SIZE]>,
181 ) -> Result<(), Error> {
182 let buffer = if slice_in_ram(buffer) { 188 let buffer = if slice_in_ram(buffer) {
183 buffer 189 buffer
184 } else { 190 } else {
185 let ram_buffer = ram_buffer.ok_or(Error::BufferNotInRAM)?; 191 if buffer.len() > self.tx_ram_buffer.len() {
192 return Err(Error::RAMBufferTooSmall);
193 }
186 trace!("Copying TWIM tx buffer into RAM for DMA"); 194 trace!("Copying TWIM tx buffer into RAM for DMA");
187 let ram_buffer = &mut ram_buffer[..buffer.len()]; 195 let ram_buffer = &mut self.tx_ram_buffer[..buffer.len()];
188 // Inline implementation of the nightly API MaybeUninit::copy_from_slice(ram_buffer, buffer) 196 ram_buffer.copy_from_slice(buffer);
189 let uninit_src: &[MaybeUninit<u8>] = unsafe { core::mem::transmute(buffer) }; 197 &*ram_buffer
190 ram_buffer.copy_from_slice(uninit_src);
191 unsafe { &*(ram_buffer as *const [MaybeUninit<u8>] as *const [u8]) }
192 }; 198 };
193 199
194 if buffer.len() > EASY_DMA_SIZE { 200 if buffer.len() > EASY_DMA_SIZE {
@@ -358,7 +364,6 @@ impl<'d, T: Instance> Twim<'d, T> {
358 &mut self, 364 &mut self,
359 address: u8, 365 address: u8,
360 operations: &mut [Operation<'_>], 366 operations: &mut [Operation<'_>],
361 tx_ram_buffer: Option<&mut [MaybeUninit<u8>; FORCE_COPY_BUFFER_SIZE]>,
362 last_op: Option<&Operation<'_>>, 367 last_op: Option<&Operation<'_>>,
363 inten: bool, 368 inten: bool,
364 ) -> Result<usize, Error> { 369 ) -> Result<usize, Error> {
@@ -397,7 +402,7 @@ impl<'d, T: Instance> Twim<'d, T> {
397 402
398 // Set up DMA buffers. 403 // Set up DMA buffers.
399 unsafe { 404 unsafe {
400 self.set_tx_buffer(wr_buffer, tx_ram_buffer)?; 405 self.set_tx_buffer(wr_buffer)?;
401 self.set_rx_buffer(rd_buffer)?; 406 self.set_rx_buffer(rd_buffer)?;
402 } 407 }
403 408
@@ -450,7 +455,7 @@ impl<'d, T: Instance> Twim<'d, T> {
450 { 455 {
451 // Set up DMA buffers. 456 // Set up DMA buffers.
452 unsafe { 457 unsafe {
453 self.set_tx_buffer(wr_buffer, tx_ram_buffer)?; 458 self.set_tx_buffer(wr_buffer)?;
454 self.set_rx_buffer(rd_buffer)?; 459 self.set_rx_buffer(rd_buffer)?;
455 } 460 }
456 461
@@ -472,7 +477,7 @@ impl<'d, T: Instance> Twim<'d, T> {
472 477
473 // Set up DMA buffers. 478 // Set up DMA buffers.
474 unsafe { 479 unsafe {
475 self.set_tx_buffer(buffer, tx_ram_buffer)?; 480 self.set_tx_buffer(buffer)?;
476 } 481 }
477 482
478 // Start write operation. 483 // Start write operation.
@@ -539,28 +544,9 @@ impl<'d, T: Instance> Twim<'d, T> {
539 /// An `Operation::Write` following an `Operation::Read` must have a 544 /// An `Operation::Write` following an `Operation::Read` must have a
540 /// non-empty buffer. 545 /// non-empty buffer.
541 pub fn blocking_transaction(&mut self, address: u8, mut operations: &mut [Operation<'_>]) -> Result<(), Error> { 546 pub fn blocking_transaction(&mut self, address: u8, mut operations: &mut [Operation<'_>]) -> Result<(), Error> {
542 let mut tx_ram_buffer = [MaybeUninit::uninit(); FORCE_COPY_BUFFER_SIZE];
543 let mut last_op = None; 547 let mut last_op = None;
544 while !operations.is_empty() { 548 while !operations.is_empty() {
545 let ops = self.setup_operations(address, operations, Some(&mut tx_ram_buffer), last_op, false)?; 549 let ops = self.setup_operations(address, operations, last_op, false)?;
546 let (in_progress, rest) = operations.split_at_mut(ops);
547 self.blocking_wait();
548 self.check_operations(in_progress)?;
549 last_op = in_progress.last();
550 operations = rest;
551 }
552 Ok(())
553 }
554
555 /// Same as [`blocking_transaction`](Twim::blocking_transaction) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
556 pub fn blocking_transaction_from_ram(
557 &mut self,
558 address: u8,
559 mut operations: &mut [Operation<'_>],
560 ) -> Result<(), Error> {
561 let mut last_op = None;
562 while !operations.is_empty() {
563 let ops = self.setup_operations(address, operations, None, last_op, false)?;
564 let (in_progress, rest) = operations.split_at_mut(ops); 550 let (in_progress, rest) = operations.split_at_mut(ops);
565 self.blocking_wait(); 551 self.blocking_wait();
566 self.check_operations(in_progress)?; 552 self.check_operations(in_progress)?;
@@ -580,30 +566,9 @@ impl<'d, T: Instance> Twim<'d, T> {
580 mut operations: &mut [Operation<'_>], 566 mut operations: &mut [Operation<'_>],
581 timeout: Duration, 567 timeout: Duration,
582 ) -> Result<(), Error> { 568 ) -> Result<(), Error> {
583 let mut tx_ram_buffer = [MaybeUninit::uninit(); FORCE_COPY_BUFFER_SIZE];
584 let mut last_op = None;
585 while !operations.is_empty() {
586 let ops = self.setup_operations(address, operations, Some(&mut tx_ram_buffer), last_op, false)?;
587 let (in_progress, rest) = operations.split_at_mut(ops);
588 self.blocking_wait_timeout(timeout)?;
589 self.check_operations(in_progress)?;
590 last_op = in_progress.last();
591 operations = rest;
592 }
593 Ok(())
594 }
595
596 /// 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.
597 #[cfg(feature = "time")]
598 pub fn blocking_transaction_from_ram_timeout(
599 &mut self,
600 address: u8,
601 mut operations: &mut [Operation<'_>],
602 timeout: Duration,
603 ) -> Result<(), Error> {
604 let mut last_op = None; 569 let mut last_op = None;
605 while !operations.is_empty() { 570 while !operations.is_empty() {
606 let ops = self.setup_operations(address, operations, None, last_op, false)?; 571 let ops = self.setup_operations(address, operations, last_op, false)?;
607 let (in_progress, rest) = operations.split_at_mut(ops); 572 let (in_progress, rest) = operations.split_at_mut(ops);
608 self.blocking_wait_timeout(timeout)?; 573 self.blocking_wait_timeout(timeout)?;
609 self.check_operations(in_progress)?; 574 self.check_operations(in_progress)?;
@@ -624,28 +589,9 @@ impl<'d, T: Instance> Twim<'d, T> {
624 /// An `Operation::Write` following an `Operation::Read` must have a 589 /// An `Operation::Write` following an `Operation::Read` must have a
625 /// non-empty buffer. 590 /// non-empty buffer.
626 pub async fn transaction(&mut self, address: u8, mut operations: &mut [Operation<'_>]) -> Result<(), Error> { 591 pub async fn transaction(&mut self, address: u8, mut operations: &mut [Operation<'_>]) -> Result<(), Error> {
627 let mut tx_ram_buffer = [MaybeUninit::uninit(); FORCE_COPY_BUFFER_SIZE];
628 let mut last_op = None;
629 while !operations.is_empty() {
630 let ops = self.setup_operations(address, operations, Some(&mut tx_ram_buffer), last_op, true)?;
631 let (in_progress, rest) = operations.split_at_mut(ops);
632 self.async_wait().await?;
633 self.check_operations(in_progress)?;
634 last_op = in_progress.last();
635 operations = rest;
636 }
637 Ok(())
638 }
639
640 /// Same as [`transaction`](Twim::transaction) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
641 pub async fn transaction_from_ram(
642 &mut self,
643 address: u8,
644 mut operations: &mut [Operation<'_>],
645 ) -> Result<(), Error> {
646 let mut last_op = None; 592 let mut last_op = None;
647 while !operations.is_empty() { 593 while !operations.is_empty() {
648 let ops = self.setup_operations(address, operations, None, last_op, true)?; 594 let ops = self.setup_operations(address, operations, last_op, true)?;
649 let (in_progress, rest) = operations.split_at_mut(ops); 595 let (in_progress, rest) = operations.split_at_mut(ops);
650 self.async_wait().await?; 596 self.async_wait().await?;
651 self.check_operations(in_progress)?; 597 self.check_operations(in_progress)?;
@@ -665,11 +611,6 @@ impl<'d, T: Instance> Twim<'d, T> {
665 self.blocking_transaction(address, &mut [Operation::Write(buffer)]) 611 self.blocking_transaction(address, &mut [Operation::Write(buffer)])
666 } 612 }
667 613
668 /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
669 pub fn blocking_write_from_ram(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
670 self.blocking_transaction_from_ram(address, &mut [Operation::Write(buffer)])
671 }
672
673 /// Read from an I2C slave. 614 /// Read from an I2C slave.
674 /// 615 ///
675 /// The buffer must have a length of at most 255 bytes on the nRF52832 616 /// The buffer must have a length of at most 255 bytes on the nRF52832
@@ -687,16 +628,6 @@ impl<'d, T: Instance> Twim<'d, T> {
687 self.blocking_transaction(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)]) 628 self.blocking_transaction(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)])
688 } 629 }
689 630
690 /// 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.
691 pub fn blocking_write_read_from_ram(
692 &mut self,
693 address: u8,
694 wr_buffer: &[u8],
695 rd_buffer: &mut [u8],
696 ) -> Result<(), Error> {
697 self.blocking_transaction_from_ram(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)])
698 }
699
700 // =========================================== 631 // ===========================================
701 632
702 /// Write to an I2C slave with timeout. 633 /// Write to an I2C slave with timeout.
@@ -707,17 +638,6 @@ impl<'d, T: Instance> Twim<'d, T> {
707 self.blocking_transaction_timeout(address, &mut [Operation::Write(buffer)], timeout) 638 self.blocking_transaction_timeout(address, &mut [Operation::Write(buffer)], timeout)
708 } 639 }
709 640
710 /// Same as [`blocking_write`](Twim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
711 #[cfg(feature = "time")]
712 pub fn blocking_write_from_ram_timeout(
713 &mut self,
714 address: u8,
715 buffer: &[u8],
716 timeout: Duration,
717 ) -> Result<(), Error> {
718 self.blocking_transaction_from_ram_timeout(address, &mut [Operation::Write(buffer)], timeout)
719 }
720
721 /// Read from an I2C slave. 641 /// Read from an I2C slave.
722 /// 642 ///
723 /// The buffer must have a length of at most 255 bytes on the nRF52832 643 /// The buffer must have a length of at most 255 bytes on the nRF52832
@@ -747,22 +667,6 @@ impl<'d, T: Instance> Twim<'d, T> {
747 ) 667 )
748 } 668 }
749 669
750 /// 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.
751 #[cfg(feature = "time")]
752 pub fn blocking_write_read_from_ram_timeout(
753 &mut self,
754 address: u8,
755 wr_buffer: &[u8],
756 rd_buffer: &mut [u8],
757 timeout: Duration,
758 ) -> Result<(), Error> {
759 self.blocking_transaction_from_ram_timeout(
760 address,
761 &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)],
762 timeout,
763 )
764 }
765
766 // =========================================== 670 // ===========================================
767 671
768 /// Read from an I2C slave. 672 /// Read from an I2C slave.
@@ -781,12 +685,6 @@ impl<'d, T: Instance> Twim<'d, T> {
781 self.transaction(address, &mut [Operation::Write(buffer)]).await 685 self.transaction(address, &mut [Operation::Write(buffer)]).await
782 } 686 }
783 687
784 /// Same as [`write`](Twim::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
785 pub async fn write_from_ram(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> {
786 self.transaction_from_ram(address, &mut [Operation::Write(buffer)])
787 .await
788 }
789
790 /// Write data to an I2C slave, then read data from the slave without 688 /// Write data to an I2C slave, then read data from the slave without
791 /// triggering a stop condition between the two. 689 /// triggering a stop condition between the two.
792 /// 690 ///
@@ -796,17 +694,6 @@ impl<'d, T: Instance> Twim<'d, T> {
796 self.transaction(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)]) 694 self.transaction(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)])
797 .await 695 .await
798 } 696 }
799
800 /// Same as [`write_read`](Twim::write_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
801 pub async fn write_read_from_ram(
802 &mut self,
803 address: u8,
804 wr_buffer: &[u8],
805 rd_buffer: &mut [u8],
806 ) -> Result<(), Error> {
807 self.transaction_from_ram(address, &mut [Operation::Write(wr_buffer), Operation::Read(rd_buffer)])
808 .await
809 }
810} 697}
811 698
812impl<'a, T: Instance> Drop for Twim<'a, T> { 699impl<'a, T: Instance> Drop for Twim<'a, T> {
@@ -904,7 +791,7 @@ impl embedded_hal_1::i2c::Error for Error {
904 Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, 791 Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other,
905 Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other, 792 Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other,
906 Self::Receive => embedded_hal_1::i2c::ErrorKind::Other, 793 Self::Receive => embedded_hal_1::i2c::ErrorKind::Other,
907 Self::BufferNotInRAM => embedded_hal_1::i2c::ErrorKind::Other, 794 Self::RAMBufferTooSmall => embedded_hal_1::i2c::ErrorKind::Other,
908 Self::AddressNack => { 795 Self::AddressNack => {
909 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address) 796 embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address)
910 } 797 }