ARM Cortex M7 processor boot reset sequence

This blog post explains the reset sequence of ARM Cortex M Microcontrollers. Also, we will see what happens if someone press reset buttons. Generally, people ask the question in the interview that what happens when you reset the processor.

But before explaining the reset sequence, I want to explain the requirement of reset in MCU. I will also mention some important factors that influence how the Cortex-M7 system boots.

So let’s first discuss the requirement of reset. A reset is an important operation and is used to bring the device into a known state. It also allows users to debug their code from the very beginning. For example, when the user initiates a debug session with the debugger (E1/E2 emulator, JTAG, or ST-Link) by connecting to the device, it resets the processor to ensure it’s a fresh start and then stops the CPU before the user application is started.

Now let’s see the factors that influence how the Cortex-M7 system boots.

  • What operating system, if any, is being used.
  • Whether TCMs are implemented.
  • How the vector table is configured at reset.
  • Memory and clock setup/configuration.

Besides these factors, CMSIS (Cortex Microcontroller Software Interface Standard) also influences the booting sequence of the ARM Cortex-M7 processor. CMSIS is the standard that makes it easier for silicon vendors, tool vendors, and software developers to work with Cortex-M devices. It defines two startup files:

startup_<device>.s

system_<device>.c

<device> is replaced with the name of the device, for example:

startup_stm32f401xc.s

system_stm32f4xx.c

 

Cortex-M silicon vendors provide these two files, which helps developers immediately get started with the Cortex-M device they are working with. The assembly language file contains the vector table, code for stack and heap initialization, and a reset handler. The C file is very device-specific and is where the clocks in the system are configured.

The Reset_Handler, generally calls two functions:

1. SystemInit()  – System and clock configuration, for example, configure XTAL frequency or PLL prescaler settings.

2. __main – The __main function is responsible for setting up the C library appropriately and eventually ends up calling the main() function.

Here I am not going into much detail if you want you can follow the “Arm developer portal”, they have described it very well.

 

If you want to learn STM32 from scratch, you should follow this course “Mastering Microcontroller with Embedded Driver Development”. The course contains video lectures of 18.5-hours length covering all topics like, Microcontroller & Peripheral Driver Development for STM32 GPIO, I2C, SPI, USART using Embedded C.

Enroll In Course

 

Below I am taking an example that will describe the reset sequence of the ARM Cortex M processor. In other words, I will describe the steps that might be taken between resetting a Cortex-M7 system and the application reaching the main() function.

Assumption:

ROM at address 0x00000000

RAM at address 0x20000000

Single binary image stored in ROM

 

I am explaining the below steps on the basis of mentioned assumption. These steps only for the basic understanding. You can follow the ARM developer portal for the more clear explanation.

1. After reset, processors boots from address 0x00000000 in Thread mode using the main stack by default. Thread mode execution can be unprivileged or privileged.

2. The processor loads the main stack vector value at address 0x00000000 into the stack pointer (sp). It is the programmer’s responsibility to put the valid value at the location 0x00000000.

3. Now processor loads  Reset vector value at address 0x00000004 into the program counter (PC).

4. Next, the control jumps to the  Reset_Handler function. In the beginning, I have already described the Reset_Handler function.

; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

 

5. You can see the above-mentioned assembly code,  where subroutine (Reset_Handler ) calls to SystemInit() to configure the clock, FPU setting, vector table location, and memory.

6. Now direct branch to __main. I have already discussed it.

7. Now finally control comes to the main() function.

 

Recommended Post: