1. Where does the MCU read code when it first starts up?After the CPU is powered on, it is designed to read code from address 0x00000000; it first reads two words in succession, which are the initial value of the stack pointer and the address of the reset exception handler; then it jumps to execute the reset exception handler.
In some early ARM processor designs, such as the Arm7TDMI, the reset will directly read the code at address 0 for execution, with the stack pointer initialized by software, and the interrupt handler function stored directly at address 0 instead of its address. Therefore, we can reasonably speculate that the first word is the stack address because the subsequent reset interrupt handler involves function jumps, which may already require content to be stored in the stack.
2. Is the code at address 0x0 bootROM code or user bootloader code?
The answer is both. It actually depends on where the user’s code is stored.For some high-performance MCUs (like the Cortex-A series), the code itself is relatively large and may be stored in an SD card or QSPI/SPI Flash. These MCUs must first execute code from the bootROM because the storage of SD cards and SPI Flash is not in the MCU’s unified address space, and cannot be accessed without initializing these peripherals. The bootROM, which is NOR Flash, can definitely be accessed directly by the MCU through the bus address, and the code at address 0 is located in the bootROM. After the code is retrieved from the bootROM, the startup pins determine from which peripheral to load the user program and initialize the corresponding peripheral, moving the user code stored in the peripheral to internal SRAM for execution. The subsequent startup process will not be elaborated.
For some small-capacity MCUs, such as Cortex-M3/M4, they have built-in Flash, which is similar to the bootROM mentioned above, and can be accessed directly by the MCU through the address bus without needing to initialize external peripherals. Of course, these MCUs also have bootROM, so they can choose to boot from the bootROM or from the built-in Flash upon power-up, selected via external pins. Whichever is selected will have its starting address mapped to address 0.
3. How do MCUs like Cortex-M3/M4 ensure that the Flash starting address is the stack pointer and the reset exception handler pointer?
This is actually specified through the compiled linker file. For example, here is an excerpt from my IAR linker file (.icf).
4. Is it possible for an MCU to not read code starting from address 0?
Chips with the M7 core are more flexible and have changed the fixed reading of the interrupt vector table from address 0x0000 0000. Taking the STM32H7 as an example, it can boot from any address between 0x0000 0000 and 0x3FFF 0000. A special option byte is arranged for configuration.