ARM Technical Support Knowledge Articles

Why does my Cortex-M processor Lock Up with a Hard Fault a few cycles after reset?

Applies to: Cortex-M0, Cortex-M0Plus, Cortex-M1, Cortex-M3, Cortex-M4


My Cortex-M processor halts all activity and asserts its LOCKUP signal on-chip and sets bit S_LOCKUP in the Debug Halting Control and Status Register.


Various ARM architectures support interworking, which is the ability to switch between the ARM and Thumb instruction sets using certain kinds of branch instructions. This allows code routines implemented in alternate instruction sets to inter-operate, by informing the processor of the change of instruction set at the branch.

The mechanism for switching makes use of the fact that all instructions must be (at least) halfword-aligned, which means that bit[0] of the branch target address is redundant. Therefore this bit can be re-used to indicate the target instruction set at that address. Bit[0] cleared to 0 means ARM and bit[0] set to 1 means Thumb.

For example, consider the instruction:

     BX lr

If the value in lr is 0x02000000 then the processor will branch to the instruction at 0x02000000 and interpret it as an ARM 32-bit instruction.

If the value in lr is 0x02000001 then the processor will branch to address 0x02000000 but interpret the instruction found there as a Thumb opcode.

The ARM Compiler (armcc) ensures that all branch target label addresses have bit[0] set correctly to represent the type of opcode found at that address. However, if the programmer creates an address manually, they must take care of ensuring that bit[0] is correctly set to represent the opcode type of that branch target.

ARMv6-M and ARMv7-M processors (Cortex-M processors) support only the Thumb instruction set. Therefore all branch targets should be indicated as odd numbers, having bit[0] set for interworking, indicating that the target contains a Thumb opcode.

The vector table in Cortex-M processors (unlike other ARM processors) is a list of addresses (vectors). These vectors are defined as interworking-capable, therefore all populated entries in the vector table must similarly have bit[0] set.

For ARMv7-M processors, if the Reset vector is an even number, the processor will immediately call a UsageFault of type INVSTATE due to the attempt to invoke the ARM instruction set for the Reset handler. Because the UsageFault is not enabled at Reset, the fault will escalate to HardFault. The HardFault vector itself will cause another UsageFault due to its bit[0] being clear. The occurrence of a fault inside the HardFault handler will result in the processor discontinuing execution, and asserting its LOCKUP output signal. For ARMv6-M processors, all faults are taken as HardFault, but the behavior is similar.

Vector table entries which are code entry point labels will be taken care of by the compilation toolset. For vector table entries which are written as literal constants in the code, the programmer must ensure that bit[0] is set to 1.

Rate this article

Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential