|ARM Technical Support Knowledge Articles|
At Reset, Cortex-M3 and Cortex-M4 processors always boot from a vector table at address zero.
With uninitialized memory at address zero (for example, unprogrammed Flash or uninitialized RAM), the processor will read a spurious initial Main Stack Pointer value from address zero and a spurious code entry point (Reset vector) from address 0x4, possibly containing an illegal instruction set state specifier (ESPR.T bit) in bit.
The processor may lock up immediately, or may execute some spurious opcodes, though in the latter case, lock-up remains a possible outcome.
A clean boot-up can be achieved through the actions of a debugger connected to the processor's debug port (assuming that the SoC has implemented Debug features for the processor).
For systems where there is no possibility of damage to the SoC or to the connected systems, the processor could be allowed to exit from Reset, and potentially execute some spurious opcodes, before the debugger takes control; however, where the possibility of damage or undesirable consequences of executing spurious opcodes exists, the SoC should be carefully designed to provide a suitable method of preventing initial execution, such as holding the processor's functional reset, SYSRESETn, asserted after the release of the power-on reset, PORESETn.
While the processor is executing or held in functional reset, the debugger can write to the NVIC to enable Halting Debug (DHCSR.C_DEBUGEN) and set up a vector catch at reset (DEMCR.VC_CORERESET). The processor can then be halted via the vector catch. If the processor is still held in functional reset, this is achieved simply by releasing the reset. If the processor is not currently held in reset, this can be achieved by halting the processor via the DHCSR.C_HALT bit and then writing the AIRCR.VECTRESET bit.
The processor is now in a Debug Halt state, having fetched the initial Main Stack Pointer, the Reset Vector, and the EPSR.T bit from uninitialized memory.
Note that the method of holding the processor in reset until the debugger has set up the vector catch carries an implication that the debugger then has the ability to subsequently release the SYSRESETn input to the processor. This requires some implementation-defined logic on the SoC to hold SYSRESETn asserted after PORESETn is released, most likely in the reset control logic on the SoC. The debugger must then be able to clear that SYSRESETn assertion, most likely by writing to a memory-mapped register in the system.
The ARMv7-M Architecture specifies that the debugger can access the processor's internal debug registers while the functional reset is asserted. It does not specify whether the external memory system can be accessed in this reset state. In the case of Cortex-M3 and Cortex-M4, debugger access to the memory system during functional reset is slightly irregular. Cortex-M3 r2p1 and Cortex-M4 r0p1 exhibit the following behavior: the debugger can successfully read from any external address, and can successfully write to any address on the System bus. However, the write data value on the D-Code bus is tied to zero in this state, so the debugger can write to any address in the Code space but only with a write data value of zero.
Once the processor is halted at the vector catch on reset, with invalid values in the main Stack Pointer and Program Counter, the correct and robust procedure from this point is to initialize at least a minimal vector table at address zero. The minimal vector table requires at least the first four entries to be valid, which are the initial Main Stack Pointer, and vectors (all with bit = 1) for the Reset, NMI and Hard Fault handler entry points, as these exceptions cannot be inhibited, and a Reset will always cause the vector table offset to revert to address 0x0. Also remember to download an executable code image to a suitable address in a writable and executable memory region before restarting operation by issuing a further self-reset (VECTRESET) so that the boot procedure starts over, but this time from the now populated vector table at address 0x0.
For use cases such as a simple test case, where there is no desire to fully support continuation of normal execution after the test, and where writing to memory at address zero is cumbersome (for example, requiring Flash erase and reprogramming), a "quick and dirty" alternative exists; the already-fetched values from addresses 0x0 and 0x4 can be fully modified by the debugger through the DCRSR and DCRDR functions while the processor is halted in debug state. This requires the Main Stack Pointer to be written with a suitable "top of stack" address in RAM, the DebugReturnAddress (essentially the PC) to be written with the true address of the code entry point, the xPSR to be written with 0x01000000 (setting the ESPR.T bit), and, of course, downloading the executable test code into a suitable (writable and executable) memory region as pointed to by that DebugReturnAddress.
Note that for the "quick and dirty" method, there remains no valid vector table at address zero. The debugger or the code image can program the VTOR to point to a valid vector table, for example located in the downloaded code image itself, but if a further reset should occur, the reboot will revert to the (non-existent) vector table at address 0x0.
Did you find this article helpful? Yes No
How can we improve this article?