Programatically resetting an embedded system (ARM Cortex)

I'm developing a system based on the nrf52 hal (nrf52833-hal to be exact) and RTIC.

What I'm looking for is to reset the system programmatically. What would be the best way?

I found that Nordic points to the NVIC_SystemReset() C function, but I can't seem find the equivalent of that in the HAL nor PAC... I did find cortex_m::peripheral::SCB::sys_reset() which seems to work, but I'm not sure if all parts (and if not, what parts) of the system are reset. (at least my RTT debug session isn't broken when issuing this command, which could be a nice feature though).

As I'm using RTIC, maybe there's an 'RTIC-idiomatic' way to do system resets.

Another option would be to setup the WDT (watchdog) and have it timeout. (this way I used to reset my AVR systems in the past...)

Anyone want's to chime in on this topic?

I'm guessing you haven't Googled "NVIC_SystemReset". Most of the posts are of the "doesn't work" sort. That's been my experience with soft resets in general.

I'd go with the watchdog. There are just so many possible unintended consequences with soft resets.

There have been a few people on the Arduino forum that have built external reset circuits. You can't use a digital I/O pin; the timing doesn't work out. The goal is often to trigger the reset for all devices instead of just the processor. That would be another possible choice.

Haven't looked into NVIC_SystemReset specifically.. (I did see people had problems with it.. but really anything you search for in relation to embedded, you'll find people having problems with.. ;))

Another option would be just panicing the program and have the panic handler do its thing. I see my panic handler (panic-probe) triggers a HardFault to invoke the the system reset:

        // Trigger a `HardFault` via `udf` instruction.

        // If `UsageFault` is enabled, we disable that first, since otherwise `udf` will cause that
        // exception instead of `HardFault`.
        #[cfg(not(any(armv6m, armv8m_base)))]
            const SHCSR: *mut u32 = 0xE000ED24usize as _;
            const USGFAULTENA: usize = 18;

            unsafe {
                let mut shcsr = core::ptr::read_volatile(SHCSR);
                shcsr &= !(1 << USGFAULTENA);
                core::ptr::write_volatile(SHCSR, shcsr);


I think the answer should be


This is also used in the panic-reset crate

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.