{"record":{"id":"fbd954c11a742be8","repo":"embassy-rs/embassy","slug":"failed-to-apply-workaround-for-uart","errorCode":null,"errorMessage":"Failed to apply workaround for UART","messagePattern":"Failed to apply workaround for UART","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"embassy-nrf/src/uarte.rs","lineNumber":1229,"sourceCode":"            // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197\n            if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {\n                workaround_succeded = true;\n                break;\n            } else {\n                // Need to sleep for 1us here\n\n                // Get the worst case clock speed\n                #[cfg(feature = \"_nrf9160\")]\n                const CLOCK_SPEED: u32 = 64_000_000;\n                #[cfg(feature = \"_nrf5340\")]\n                const CLOCK_SPEED: u32 = 128_000_000;\n\n                cortex_m::asm::delay(CLOCK_SPEED / 1_000_000);\n            }\n        }\n\n        if !workaround_succeded {\n            panic!(\"Failed to apply workaround for UART\");\n        }\n\n        // write back the bits we just read to clear them\n        let errors = r.errorsrc().read();\n        r.errorsrc().write_value(errors);\n        r.enable().write(|w| w.set_enable(vals::Enable::Disabled));\n    }\n}\n\npub(crate) fn drop_tx_rx(r: pac::uarte::Uarte, s: &State) {\n    if s.tx_rx_refcount.fetch_sub(1, Ordering::Relaxed) == 1 {\n        // Finally we can disable, and we do so for the peripheral\n        // i.e. not just rx concerns.\n        r.enable().write(|w| w.set_enable(vals::Enable::Disabled));\n\n        gpio::deconfigure_pin(r.psel().rxd().read());\n        gpio::deconfigure_pin(r.psel().txd().read());\n        gpio::deconfigure_pin(r.psel().rts().read());","sourceCodeStart":1211,"sourceCodeEnd":1247,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-nrf/src/uarte.rs#L1211-L1247","documentation":"This is a workaround routine for the nRF52840 UARTE 'enable during ongoing DMA' anomaly (errata). The function repeatedly delays and toggles the ENABLE register expecting a specific readback; if the expected state is never observed after the retry loop, `workaround_succeded` remains false and it panics. Reaching this panic means the errata workaround could not be applied and the UART may misbehave.","triggerScenarios":"Calling the UARTE driver code path that invokes `apply_workaround_for_enable_anomaly` (e.g. stopping/starting RX on an affected nRF52840 chip) when the ENABLE register never reaches the state the workaround loop waits for within its delay/retry budget.","commonSituations":"Running on silicon revisions not targeted by the workaround's assumptions; clock speed mismatch making the fixed `delay(CLOCK_SPEED / 1_000_000)` budget insufficient; using the driver on hardware where the errata workaround sequence is invalid.","solutions":["Verify the target chip/silicon revision is one the workaround supports (nRF52840 errata 173-class issues) and that the correct feature/chip selection is compiled in.","Ensure CLOCK_SPEED is set correctly for the actual clock so the delay loop waits long enough.","Update embassy-nrf to the latest version, where the workaround timing may have been corrected.","File an issue with the embassy-nrf maintainers if the panic reproduces on supported silicon — it indicates an internal invariant violation."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust panics are not catchable in embedded firmware; treat as fatal.\n// Guard by verifying chip/feature support at build time:\n#[cfg(all(target_chip = \"nrf52840\", feature = \"_nrf52840_anomaly\"))]\ncompile_error!(\"verify UARTE enable-anomaly workaround applies to your silicon revision\");","preventionTips":["Compile for a chip/silicon revision explicitly supported by embassy-nrf's errata workarounds.","Keep embassy-nrf updated so workaround timing fixes are picked up.","Test RX start/stop paths on real hardware during bring-up, not only in simulation."],"tags":["embedded","uart","nrf","errata","hardware-workaround","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}