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 componet offers a SoftwareReset() function which I can use in my application. It is defined like this in the component:

void KIN1_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 KIN1_IS_USING_KINETIS_SDK
  SCB_AIRCR = (0x5FA<<SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk;
#else
  SCB_AIRCR = SCB_AIRCR_VECTKEY(0x5FA) | SCB_AIRCR_SYSRESETREQ_MASK;
#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:

Advertisements

41 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

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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