How to Reset an ARM Cortex-M with Software

There are cases when I need to do a reset of the device by software. For example I have loaded the application image with the bootloader, and then I need to perform a reset of the microcontroller to do a restart. As a human user I can press the reset button on the board. But how to do this from the software and application running on the board, without user manual intervention? Or if I simply want to reset the system for whatever reason?

Performing a Software System Reset with Kinetis Design Studio
Performing a Software System Reset with Kinetis Design Studio

Using Watchdog Timeout

In the past I have used the following approach for other microcontroller (e.g. the Freescale S08 and S12 devices):

  1. Setting up a watchdog timer
  2. Then when I want to do a reset, I do *not* kick (serve) the watchdog timer any more
  3. As a result, the WDT (watchdog timer) or COP (Computer operating properly) will timeout, and will reset the part

That approach is working, but well is not the easiest way. Especially as on ARM Cortex-M there is a better way :-).

Using ARM System Reset

The ARM Cortex-M which includes the Freescale Kinetis series cores have a System Reset functionality available in the AICR (Application Interrupt and Reset Control Register):

AIRCR Register (Source: ARM Infocenter)
AIRCR Register (Source: ARM Infocenter)

So all I need to write a 0x05FA to VECTKEY with a 1 to SYSRESETREQ :-).

The easiest way is if I used the KinetisTools Processor Expert component from SourceForge (see “McuOnEclipse Releases on SourceForge“):

KinetisTools Processor Expert Component
KinetisTools Processor Expert Component

This component offers a SoftwareReset() function which I can use in my application. It is defined like this in the component:

void McuArmTools_SoftwareReset(void)
{
  /* Generic way to request a reset from software for ARM Cortex */
  /* See https://community.freescale.com/thread/99740
     To write to this register, you must write 0x5FA to the VECTKEY field, otherwise the processor ignores the write.
     SYSRESETREQ will cause a system reset asynchronously, so need to wait afterwards.
   */
#if McuLib_CONFIG_CPU_IS_ARM_CORTEX_M
#if McuLib_CONFIG_PEX_SDK_USED
  SCB_AIRCR = SCB_AIRCR_VECTKEY(0x5FA) | SCB_AIRCR_SYSRESETREQ_MASK;
#elif McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_S32K
  S32_SCB->AIRCR = S32_SCB_AIRCR_VECTKEY(0x5FA) | S32_SCB_AIRCR_SYSRESETREQ_MASK;
#elif McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_RPI_PICO
  #define SCB_AIRCR                          (*((uint32_t*)(0xe0000000+0xed0c)))
  #define SCB_AIRCR_VECTKEY_Pos              16U                                            /*!< SCB AIRCR: VECTKEY Position */
  #define SCB_AIRCR_SYSRESETREQ_Pos           2U                                            /*!< SCB AIRCR: SYSRESETREQ Position */
  #define SCB_AIRCR_SYSRESETREQ_Msk          (1UL << SCB_AIRCR_SYSRESETREQ_Pos)             /*!< SCB AIRCR: SYSRESETREQ Mask */

  SCB_AIRCR = (0x5FA<<SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk;
#else
  SCB->AIRCR = (0x5FA<<SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk;
#endif
#endif
  for(;;) {
    /* wait until reset */
  }
}

So all what you need is to have such a piece of code in your application to do a system reset.

That component features as well an optional command line interface. That way I can reset the target with a command from the shell 🙂

Reset System from the Shell
Reset System from the Shell

Summary

To reset an ARM Cortex M by software, I can use the AIRCR register. Either I can do this directly, or using my KinetisTools component for Processor Expert :-).

As an additional note: there is a sticky ‘System Reset Status’ register available (I think on most Kinetis devices) which reports the reason for the reset. A good idea is to read that register at startup time and e.g. print the reset reason to the console (Thanks Charles for that cool idea!).

Happy resetting 🙂

Links:

51 thoughts on “How to Reset an ARM Cortex-M with Software

  1. Pingback: McuOnEclipse Components: 05-July-2015 Release | MCU on Eclipse

  2. I am extrapolating from this that KDS provides no command to reset the processor from either the menu system or the toolbar? I have spent most of my career using classical embedded tools and am still sometimes taken aback by the things Eclipse cannot do.

    I have used one other Eclipse derivative (Code Composer Studio) and that feature was built in.

    Like

  3. Ok, I did find that, but the description text: (Restart a process or debug target without terminating and re- launching) was so abstruse, I didn’t recognize it.

    Thanks, Erich!

    Like

  4. This reset usualy works for us, but sometimes it doesn’t… I’ve noticed that the user guide says: SYSRESETREQ -> asserts a proc_reset_signal.
    This is intended to force a large system reset of all major components **except for debug**.

    What does it mean? Debug means that I am currently debugging using a JTAG, or does it mean that I am running a “debug” configuration compiled image?

    Also, I’ve found that the AIRCR register has two more bits:
    VECTRESET & VECTCLRACTIVE, which we should reset whenever we write to this register, “otherwise behavior is Unpredictable”. Can this be the case…?

    Thanks!
    Lior.

    Like

    • Hi Lior,
      it means that it does not reset the debug logic on the chip (has nothing to do with hardware).
      I have not seen any issues on my side with the proposed way.

      I see this note:
      Note

      SYSRESETREQ is cleared by a system reset, which means that asserting VECTRESET at the same time may cause SYSRESETREQ to be cleared in the same cycle as it is written to. This may prevent the external system from seeing SYSRESETREQ. It is therefore recommended that VECTRESET and SYSRESETREQ be used exclusively and never both written to 1 at the same time.

      Like

      • Thanks, Erich!
        So, in other words, is it recommended to clear both bits (VECTRESET & VECTCLRACTIVE) at the same time that I set SYSRESETREQ – in order to prevent it to interfere with the reset action?

        Like

  5. Hey,
    I’ve noticed that maybe there is another option for Cortex-M3, which is to use RSTC_CR.
    Have anyone tried this option?

    Thanks,
    Lior.

    Like

  6. Pingback: Debugging ARM Cortex-M0+ HardFaults | MCU on Eclipse

  7. HI! I had a problem with de watchdog. I initialize the watchdog, I do not refresh in the loop and the core doesn t reset. All the registers are initialize ok beacause y see them in the debuger.
    ¿Does anyone know if there is another register to enable the clock or something similar?

    Like

    • Which device, and which debugger? The watchdog functions depend on the device implementation, and I have seen debuggers which disable the watchdog (so you can debug).
      Do you have the same if you run the board without the debugger?

      Like

  8. Hi, thanks for your great posts! I’m getting an error when I try to Generate Processor Expert Code:
    “Description Resource Path Location Type
    Generator: FAILURE: at line 72: “Shell”/Shell has not assigned the component (file: Drivers\sw\KinetisTools.drv) WT4 KIN1 Processor Expert Problem”

    If I tick the checkbox to use a shell (and add the required components for that) then it builds just fine. The problem seems to only occur when I try to use the KinetisTools without a shell. Any suggestions?

    Like

  9. Hi Erich,

    The given information is useful foe me, i wanted to read the reset reason as well. i have tried to read the reset reason using the CPUDBGSCRATCH register, but in the this memory (0xe010200c) always i can see 0xFFFFFFFC values. can you please suggest how exactly i can read the reset reason.

    Thanks in advance.

    Like

  10. Hi Erich,
    Thank you for your explanation.
    I’m working with power modes and using FRDM-KL02z board, I tried to use this method to exit the stop mode, I wrote “KIN1_SoftwareReset();” after calling the enter stop mode function but it is not working. Do you have any idea why it is not working ?as I’m expecting to exit the stop mode into normal run mode.

    Regards
    Banu

    Like

    • Hi Banu,
      I have not used it in such a sitution. But if you are in stop mode, then no instructions get executed. So you need first to exit stop mode and then do the reset?

      Like

      • Hi Erich,
        Yes, I need to exit the stop mode into the normal run, this can happen by either using reset or interrupt(WFI). I’m not sure how to use the WFI so I’m thinking if there is software reset code that let the M0+ exit the stop mode?

        Regards
        Banu

        Like

  11. Hi Erich,
    Thanks for quick reply.
    Yes, I tried ” __asm(“wfi”);” but didn’t work, my code is simply as below, I tried to place the “__asm(“wfi”);” after and before calling the enter stop mode function, do you have any idea why?

    int main(void)

    {
    PE_low_level_init();

    unsigned int i,j;
    PWM1_Enable();
    for(i=0;i<5000;i++)
    for(;;) {
    {
    enter_stop();
    PWM1_Disable();
    for(i=0;i<5000;i++)
    PWM1_Enable();
    for(i=0;i<50000;i++);
    }
    }
    void enter_stop(void)
    {
    volatile unsigned int dummyread;

    SMC_PMCTRL &= ~SMC_PMCTRL_STOPM_MASK; //mask=0x7u
    SMC_PMCTRL |= SMC_PMCTRL_STOPM(0);
    /*wait for write to complete to SMC before stopping core */
    dummyread = SMC_PMCTRL;
    deepsleep();
    }
    void deepsleep (void)
    {
    /* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
    SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK; //0x4u
    #ifdef CMSIS
    __wfi();
    #else
    /* WFI instruction will start entry into STOP mode */
    __asm("WFI");
    #endif

    }

    Like

  12. Hi Erich,
    I added TimerInt components and put the interrupt period 2sec, then wrote in the events.c a wakeup_flag and modify the below code in main.c please check:
    PWM1_Enable();
    for(i=0;i<5000;i++)
    for(;;) {
    for(i=0;i<1000;i++)
    enter_stop();
    wake_up_int_Enable();
    if (Wakeup_flag==0)
    {
    deepsleep();
    PWM1_Disable();
    for(i=0;i<5000;i++)
    PWM1_Enable();
    for(i=0;i<5000;i++)
    }
    Wakeup_flag==1;
    }
    I enabled the wake_up_int and then checked the wakeup_flag in events.c and then called the deepsleep function which is the same as in the above post but still has the same issue, the MCU enter the stop mode any stay there 🙁.

    Regards
    Banu

    Like

      • Thank you for the quick reply.
        I modified it as below:
        /*****Main.c****/
        unsigned char Wakeup_flag=0;
        PWM1_Enable();
        for(i=0;i<5000;i++)
        for(;;) {
        for(i=0;i<1000;i++)
        wake_up_int_Enable();
        if (Wakeup_flag==0)
        {
        enter_stop();
        deepsleep();
        PWM1_Disable();
        for(i=0;i<5000;i++)
        PWM1_Enable();
        for(i=0;i<5000;i++)
        }
        Wakeup_flag=1;
        }

        /**********Events.c*****/
        void wake_up_int_OnInterrupt(void)
        {
        /* Write your code here … */
        Wakeup_flag=0;
        LED1_On();
        }

        Still the same issue.

        Like

  13. Pingback: FreeRTOS: how to End and Restart the Scheduler | MCU on Eclipse

  14. @Erich,

    Could you quickly explain in this comment or in a new series on LPC55S69 how one can reset the processor in both security states?

    Thank you!

    Like

  15. @Erich,

    Could you quickly explain in this comment or in a new series on LPC55S69 how one can reset the processor in both security states?

    Thank you!

    Could you quickly explain in this comment or in a new series on LPC55S69 how one can reset the processor in both security states?

    Thank you!

    Like

  16. Thank you Erich again for the helpful tutoring. When using MCUXpresso, use NVIC_SystemReset (); as found in a file called “core_cm0plus.h”. Happy Resetting.

    Like

  17. Hi Erich,

    I have a situation where a soft reset does not work on at least 2 of by NXP Kinetis K8x boards, whether invoked by the watchdog, or explicitly with __NVIC_SystemReset(). The MCU stops/freezes and only restarts with a POR.

    What can prevent the ARM CM4 MCU from resetting?

    Liked by 1 person

    • I have not observed something like this, but have not used K8x, so it might be K8x specific.
      But the watchdog itself should do a reset: are you saying that you call __NVIC_SystemReset() within the watchdog (unlikely?)?
      The other thought I have: I had some K6x devices which uses some boot port (EZport or something like that). With some voltage applied to a pin, the device was booting into a bootloader mode. Maybe something like this is the case for your K8x?

      Liked by 1 person

      • Yes, you are right on 2 counts:
        1) This is K81/K82 specific, and
        2) This was boot mode specific

        In our case there is a PN5190 NFC frontend using the K81’s NMI pin for its IRQ. The SDK’s default Flash Configuration block configures the boot behavior to allow NMI reset and the select the boot source (ROM). The PN5190 asserted the IRQ in its normal operation, but a side-effect was the failure of a subsequent system reset. I checked this theory: If the PN5190 was never accessed, then the system reset always worked as expected.

        To fix this I had to change the FOPT settings in the Flash Configuration Block to a) block NMI Interrupts, and b) select boot source as internal flash.

        Of course, on POR the FOPT is all 0xFFFF…, which allows the startup and hides the FOPT misconfiguration.

        Like

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.