aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/uarte.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 320426060..15ebcdd57 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -114,6 +114,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
114 irq.enable(); 114 irq.enable();
115 115
116 // Enable 116 // Enable
117 Self::apply_workaround_for_enable_anomaly();
117 r.enable.write(|w| w.enable().enabled()); 118 r.enable.write(|w| w.enable().enabled());
118 119
119 Self { 120 Self {
@@ -121,6 +122,61 @@ impl<'d, T: Instance> Uarte<'d, T> {
121 } 122 }
122 } 123 }
123 124
125 #[cfg(not(any(feature = "nrf9160", feature = "nrf5340")))]
126 fn apply_workaround_for_enable_anomaly() {
127 // Do nothing
128 }
129
130 #[cfg(any(feature = "nrf9160", feature = "nrf5340"))]
131 fn apply_workaround_for_enable_anomaly() {
132 use core::ops::Deref;
133
134 let r = T::regs();
135
136 // Apply workaround for anomalies:
137 // - nRF9160 - anomaly 23
138 // - nRF5340 - anomaly 44
139 let rxenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x564) as *const u32;
140 let txenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x568) as *const u32;
141
142 // NB Safety: This is taken from Nordic's driver -
143 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
144 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
145 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
146 }
147
148 // NB Safety: This is taken from Nordic's driver -
149 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
150 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
151 r.enable.write(|w| w.enable().enabled());
152 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
153
154 let mut workaround_succeded = false;
155 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
156 // On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
157 // (resulting in 12 bits per data byte sent), this may take up to 40 ms.
158 for _ in 0..40000 {
159 // NB Safety: This is taken from Nordic's driver -
160 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
161 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
162 workaround_succeded = true;
163 break;
164 } else {
165 // Need to sleep for 1us here
166 }
167 }
168
169 if !workaround_succeded {
170 panic!("Failed to apply workaround for UART");
171 }
172
173 let errors = r.errorsrc.read().bits();
174 // NB Safety: safe to write back the bits we just read to clear them
175 r.errorsrc.write(|w| unsafe { w.bits(errors) });
176 r.enable.write(|w| w.enable().disabled());
177 }
178 }
179
124 fn on_interrupt(_: *mut ()) { 180 fn on_interrupt(_: *mut ()) {
125 let r = T::regs(); 181 let r = T::regs();
126 let s = T::state(); 182 let s = T::state();