Software reset in Arduino Zero

I need now to reset my Zero board using software reset, i.e. when some conditions are met in the sketch, I try to reboot the board.

My reasond for using a software reset instead of a hardware one, are related to a multifunction swicth, that can triggers several functions:

    1. ligthning the display (short push)
    1. changing the display layout (after lightning the display a series of short pushes)
    1. reseting the board when pushed for more than 5 seconds

The code for detecting the reset condition is working, but the “reset function”, that I copied from the AVR boards, freezes the Zero board:

void(* resetFunc) (void) = 0;//declare reset function at address 0

Anybody has faced this issue (software reset) before?, how can I call a function in Arduino that resets the board?

This is the part of my code that manages the above mentioned functions:

  // Switch management 
  bool Pulsador = !digitalRead(PULSADOR_PIN);    // Leo Estado Pulsador (Lógica Inversa!!)

   // Lightning the  DISPLAY :  
  if ( (Pulsador) || (millis()-ilumTime) < ILUM_INTERVAL ) {
     digitalWrite(BACKLIGHT_PIN, HIGH);  
     digitalWrite(REDLED_PIN, HIGH);  
     if (Pulsador != PulsadorPre) {              // Ha existido cambio estado Pulsador?
        ilumTime = millis();                     // Fijo Tiempo inicio contar Tiempo iluminación
        resetTime = millis();                    // Fijo Tiempo inicio contar Tiempo Reset
        if (Pulsador){                           // Si Flanco Subida?
          LayoutDisplay++;                       // Cambio Tipo Pantalla
          if (LayoutDisplay > 4) {LayoutDisplay = 0;} // Si llego a Pantalla 3, vuelvoa a la primera
        }
     }
   } else {                                      // Pulsador No activado
     digitalWrite(BACKLIGHT_PIN, LOW);  
     digitalWrite(REDLED_PIN, LOW);  
     LayoutDisplay = 0;
  }

  // SOFTWARE RESET: Switch Time  > RESET_INTERVAL
  if (Pulsador && (millis()-resetTime)> RESET_INTERVAL) {
     // Software Reset
     resetFunc();
  }
  PulsadorPre = Pulsador;          // Almaceno Estado pulsador para detectar cambios

Try this code :

Before setup() :

extern "C" {
  extern void resetZero();
}

after loop() :

extern "C" {
#define APP_START_ADDRESS 0x2000

  void resetZero() {
    void (*application_code_entry)(void);
    __set_MSP(*(uint32_t *) APP_START_ADDRESS);
    SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
    application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(APP_START_ADDRESS + 4));
    application_code_entry();
  }
}

Hi Kinematik,

to reset the processor call this CMSIS function

NVIC_SystemReset();      // processor software reset

Ciao
Marco

Hi Marco,

Thanks!, it works!. I did not have idea about the CMSIS (the ARM Cortex Microcontroller Software Interface Standar) was available in the Arduino environment.

A brief explantation about CMSISI (ARM standard), for the not so knowledgable people like me: http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php

Can you please elaborate, what else is available and where are these functions defined in the Arduino environment?

AloyseTech: Try this code :

Before setup() :

extern "C" {
  extern void resetZero();
}

after loop() :

extern "C" {
#define APP_START_ADDRESS 0x2000

  void resetZero() {     void (application_code_entry)(void);     __set_MSP((uint32_t ) APP_START_ADDRESS);     SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);     application_code_entry = (void ()(void))(unsigned )((unsigned *)(APP_START_ADDRESS + 4));     application_code_entry();   } }

thanks Aloise, unfortunately the code freezes my board. Actually I am not using a bootloader but it does not work regardless the value of the star address, I tried both:

#define APP_START_ADDRESS 0x2000
#define APP_START_ADDRESS 0x0000

But this is a very nice opportunity to learn more. Would you please elaborate what does the code use and does?, I really don´t understand it, the "extern" keyboard is for declaring a variable/function that lives outside of the scope of the file, and also why the "C" definition should lie before setup?, and then a new "C" definition after the loop?

try with address 0x000000, but you have to reset all peripheral you’re using in the app : SPI.end() for example. By the way, you may have to use it dissconnected to any USB data cable : power your board from an external suply. I’m not sure about the USB problem, but my code only works when I’m not using the USB cable…

The “C” wrapper is for the compiler. And if you use plain C, you have to put the function prototype at the beginning of the code, and then define the function wherever you want.

extern "C" {
#define APP_START_ADDRESS 0x0000

  void jumpApplication() {
    /* Pointer to the Application Section */
    void (*application_code_entry)(void);
    /* Rebase the Stack Pointer */
    __set_MSP(*(uint32_t *) APP_START_ADDRESS);
    /* Rebase the vector table base address */
    SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
    /* Load the Reset Handler address of the application */
    application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(APP_START_ADDRESS + 4));
    /* Jump to user Reset Handler in the application */
    application_code_entry();
  }
}

Hi Kinematik,

unfortunatly, I am not able to answer to your question. :slightly_frowning_face: :slightly_frowning_face:

I discovered the reset function digging in the internet, but I too would like to know which CMSIS functions are available in the Arduino ide and where is possible to find a clear documentation of this.

It would be very useful to have such informations !!!

So I join to your request and I hope that somebody more expert than you and me could find an answer.

Marco

The NVIC_SystemReset() function is briefly mentioned together with other CMSIS functions for NVIC control on page 4-7 of the "Cortex-M0+ Devices Generic User Guide". It's possible to download it from the ARM Information Center: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0484c/index.html

Hello i want to remove the delay after i press the reset button, there are some solution for this?

The best solution is to skip the bootloader. If you don't need to chanre your application once programmed, compile and program at address 0 instead of 0x2000, and don't put any bootloader.

cometa: Hello i want to remove the delay after i press the reset button, there are some solution for this?

I am not sure I am understand correctly your requirement: do you want to reset (via software) the Zero board just after pushing a button?

If this is the case is quite easy:

bool button = digitalRead(BUTTON_PIN);   

if (button) {
    NVIC_SystemReset();      // processor software reset  
}

You can also go the AloyseTech way, although for me did not work.

Reset in the form of a power-on reboot is easy. Use assembly language to "jmp 0". Try this:

void software_Reset() // Restarts program from beginning { asm volatile (" jmp 0"); }

Hmm. when I try

NVIC_SystemReset(); // processor software reset

I cannot open the serial port any more until I reset by pressing the reset button. I hear it de-enumerate and re-enumerate and it shows up in the device manager (but not the Arduino IDE) and if I try to open it with putty fails.

Am I supposed to do something before the calll to NVIC_SystemReset()?

Hi tozz88,

I cannot open the serial port any more

I assume that you are referring to the USB native port, right?

I checked the NVIC_SystemReset(); with this simple sketch:

int led = 13;

void setup() 
{                
  pinMode(led, OUTPUT);     
}

void loop() 

{
  int i;

  for(i=0; i<3; i++)
  {
    digitalWrite(led, HIGH); 
    delay(1000);              
    digitalWrite(led, LOW);   
    delay(1000);             
  }
  
  delay(1000);
  NVIC_SystemReset();          // processor software reset  
}

and the USB serial port never disappear from the Arduino Ide.

I am using an Arduino Zero connected to the USB native port and SamD core 1.6.20.

Marco