aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-12-08 01:43:25 +0000
committerGitHub <[email protected]>2021-12-08 01:43:25 +0000
commit6081b36356878f969457c80b6069f7fefcde6a29 (patch)
tree8d2d1e40bc8d14df64647b0bff18b847c8dd31bc
parentc574b0eb7331292f1b8af278402da5af50fedf5d (diff)
parent090a7adf78cd6d9dea8fee773523c53a03ae63d5 (diff)
Merge #525
525: Applies the Uarte patch r=huntc a=huntc Applies the Nordic workaround found in the `Uarte` for the nRF9160 and nRF5340 to the `BufferedUarte`. Co-authored-by: huntc <[email protected]>
-rw-r--r--embassy-nrf/src/buffered_uarte.rs3
-rw-r--r--embassy-nrf/src/uarte.rs110
2 files changed, 56 insertions, 57 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 5468f6c0b..9b0451c12 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -22,7 +22,7 @@ use crate::pac;
22use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 22use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
23use crate::timer::Instance as TimerInstance; 23use crate::timer::Instance as TimerInstance;
24use crate::timer::{Frequency, Timer}; 24use crate::timer::{Frequency, Timer};
25use crate::uarte::{Config, Instance as UarteInstance}; 25use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance};
26 26
27// Re-export SVD variants to allow user to directly set values 27// Re-export SVD variants to allow user to directly set values
28pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 28pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
@@ -132,6 +132,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
132 irq.pend(); 132 irq.pend();
133 133
134 // Enable UARTE instance 134 // Enable UARTE instance
135 apply_workaround_for_enable_anomaly(&r);
135 r.enable.write(|w| w.enable().enabled()); 136 r.enable.write(|w| w.enable().enabled());
136 137
137 // BAUDRATE register values are `baudrate * 2^32 / 16000000` 138 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 60e69e032..72dcd41b2 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -116,7 +116,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
116 irq.enable(); 116 irq.enable();
117 117
118 // Enable 118 // Enable
119 Self::apply_workaround_for_enable_anomaly(); 119 apply_workaround_for_enable_anomaly(&r);
120 r.enable.write(|w| w.enable().enabled()); 120 r.enable.write(|w| w.enable().enabled());
121 121
122 Self { 122 Self {
@@ -124,61 +124,6 @@ impl<'d, T: Instance> Uarte<'d, T> {
124 } 124 }
125 } 125 }
126 126
127 #[cfg(not(any(feature = "_nrf9160", feature = "nrf5340")))]
128 fn apply_workaround_for_enable_anomaly() {
129 // Do nothing
130 }
131
132 #[cfg(any(feature = "_nrf9160", feature = "nrf5340"))]
133 fn apply_workaround_for_enable_anomaly() {
134 use core::ops::Deref;
135
136 let r = T::regs();
137
138 // Apply workaround for anomalies:
139 // - nRF9160 - anomaly 23
140 // - nRF5340 - anomaly 44
141 let rxenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x564) as *const u32;
142 let txenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x568) as *const u32;
143
144 // NB Safety: This is taken from Nordic's driver -
145 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
146 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
147 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
148 }
149
150 // NB Safety: This is taken from Nordic's driver -
151 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
152 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
153 r.enable.write(|w| w.enable().enabled());
154 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
155
156 let mut workaround_succeded = false;
157 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
158 // On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
159 // (resulting in 12 bits per data byte sent), this may take up to 40 ms.
160 for _ in 0..40000 {
161 // NB Safety: This is taken from Nordic's driver -
162 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
163 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
164 workaround_succeded = true;
165 break;
166 } else {
167 // Need to sleep for 1us here
168 }
169 }
170
171 if !workaround_succeded {
172 panic!("Failed to apply workaround for UART");
173 }
174
175 let errors = r.errorsrc.read().bits();
176 // NB Safety: safe to write back the bits we just read to clear them
177 r.errorsrc.write(|w| unsafe { w.bits(errors) });
178 r.enable.write(|w| w.enable().disabled());
179 }
180 }
181
182 fn on_interrupt(_: *mut ()) { 127 fn on_interrupt(_: *mut ()) {
183 let r = T::regs(); 128 let r = T::regs();
184 let s = T::state(); 129 let s = T::state();
@@ -330,6 +275,59 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
330 } 275 }
331} 276}
332 277
278#[cfg(not(any(feature = "_nrf9160", feature = "nrf5340")))]
279pub(in crate) fn apply_workaround_for_enable_anomaly(_r: &crate::pac::uarte0::RegisterBlock) {
280 // Do nothing
281}
282
283#[cfg(any(feature = "_nrf9160", feature = "nrf5340"))]
284pub(in crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::RegisterBlock) {
285 use core::ops::Deref;
286
287 // Apply workaround for anomalies:
288 // - nRF9160 - anomaly 23
289 // - nRF5340 - anomaly 44
290 let rxenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x564) as *const u32;
291 let txenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x568) as *const u32;
292
293 // NB Safety: This is taken from Nordic's driver -
294 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
295 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
296 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
297 }
298
299 // NB Safety: This is taken from Nordic's driver -
300 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
301 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
302 r.enable.write(|w| w.enable().enabled());
303 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
304
305 let mut workaround_succeded = false;
306 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
307 // On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
308 // (resulting in 12 bits per data byte sent), this may take up to 40 ms.
309 for _ in 0..40000 {
310 // NB Safety: This is taken from Nordic's driver -
311 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
312 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
313 workaround_succeded = true;
314 break;
315 } else {
316 // Need to sleep for 1us here
317 }
318 }
319
320 if !workaround_succeded {
321 panic!("Failed to apply workaround for UART");
322 }
323
324 let errors = r.errorsrc.read().bits();
325 // NB Safety: safe to write back the bits we just read to clear them
326 r.errorsrc.write(|w| unsafe { w.bits(errors) });
327 r.enable.write(|w| w.enable().disabled());
328 }
329}
330
333/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels, 331/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
334/// allowing it to implement the ReadUntilIdle trait. 332/// allowing it to implement the ReadUntilIdle trait.
335pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { 333pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {