diff options
| author | Dion Dokter <[email protected]> | 2021-10-12 13:35:08 +0200 |
|---|---|---|
| committer | Dion Dokter <[email protected]> | 2021-10-12 13:35:08 +0200 |
| commit | ddcee446c1da46b00d2088cfa1f75481b1737cc7 (patch) | |
| tree | a08e99635452b79b3d1a445831d3197061521b1f /embassy-nrf/src/uarte.rs | |
| parent | 2c2c284482ee57595ad4eef542f4867f6f87bf12 (diff) | |
Added anomaly workaround from the HAL to improve the UARTE
Diffstat (limited to 'embassy-nrf/src/uarte.rs')
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 56 |
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(); |
