ARM Cortex-M33 Hard Fault During VLDR Execution
The issue at hand involves a HardFault triggered by the execution of the vldr d16, [r7, #200]
instruction on an ARM Cortex-M33 processor, specifically the LPC55S69 (CM33_Core0) with DSP extensions. The fault occurs during the execution of a floating-point unit (FPU) instruction, suggesting potential misconfigurations or memory access issues. The system is built using GNU Tools ARM Embedded/8 2019-q3-update and debugged in MCUXpresso IDE v11.0.1. The SystemInit()
function, which is responsible for initializing the system, including the FPU, appears to execute correctly, but the fault persists even after adding data synchronization barriers (DSB
) and instruction synchronization barriers (ISB
).
The primary concern revolves around understanding the current processor context (secure/non-secure, privileged/unprivileged, thread/handler), verifying the FPU’s enabled state, and ensuring proper memory alignment for the VLDR
instruction. Additionally, the absence of DSB
and ISB
instructions after enabling the FPU in SystemInit()
raises questions about their necessity in this context.
FPU Configuration, Memory Alignment, and Processor Context
The HardFault could stem from several root causes, including incorrect FPU configuration, improper memory alignment, or an invalid processor context during the execution of the VLDR
instruction. The Cortex-M33 processor’s FPU must be explicitly enabled by setting the appropriate bits in the Coprocessor Access Control Register (CPACR). The SystemInit()
function correctly sets the CPACR bits to enable full access to the FPU, but the absence of DSB
and ISB
instructions immediately after this configuration could lead to pipeline inconsistencies, causing the processor to execute FPU instructions before the FPU is fully enabled.
Memory alignment is another critical factor. The VLDR
instruction requires the memory address to be word-aligned. If the address in register r7
(0x2003FEA0) plus the offset (200 or 0xC8) results in a non-word-aligned address, the processor will generate a HardFault. The value of r7
and the structure of gMyInout
must be examined to ensure proper alignment.
The processor context (secure/non-secure, privileged/unprivileged, thread/handler) also plays a significant role. The Cortex-M33 implements the ARMv8-M architecture, which introduces a security extension. The Non-Secure Access Control Register (NSACR) must be configured to allow non-secure access to the FPU. The SystemInit()
function sets the NSACR bits correctly, but the current context during the VLDR
execution must be verified to ensure it has the necessary privileges and security permissions.
Verifying FPU Status, Aligning Memory, and Ensuring Proper Context
To resolve the HardFault issue, a systematic approach is required to verify the FPU status, ensure memory alignment, and confirm the processor context. Below are detailed troubleshooting steps and solutions:
Verifying FPU Configuration and Status
The FPU status can be verified by inspecting the CPACR and NSACR registers. The CPACR should have bits 20-23 set to enable full access to the FPU. The NSACR should have bits 0, 1, 10, and 11 set to allow non-secure access to the FPU. Additionally, the FPU enable status can be checked using the Floating-Point Status and Control Register (FPSCR). If the FPU is enabled, the FPSCR will reflect the current state of the FPU.
To ensure the FPU is fully enabled before executing FPU instructions, add DSB
and ISB
instructions immediately after setting the CPACR and NSACR bits in SystemInit()
. These instructions ensure that the pipeline is flushed and the FPU is ready for use.
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); // Enable CP10 and CP11 (FPU)
SCB->NSACR |= ((3UL << 0) | (3UL << 10)); // Enable non-secure access to FPU
__DSB(); // Ensure the configuration is complete
__ISB(); // Flush the pipeline
Ensuring Proper Memory Alignment
The VLDR
instruction requires the memory address to be word-aligned. Verify that the address in r7
(0x2003FEA0) plus the offset (200 or 0xC8) results in a word-aligned address. If gMyInout
is a structure or array, ensure that its elements are properly aligned in memory. Use the __attribute__((aligned(4)))
attribute in C to enforce alignment.
typedef struct {
int32_t data[50]; // Example array
} __attribute__((aligned(4))) MyStruct;
MyStruct gMyInout; // Ensure alignment
Confirming Processor Context
The processor context can be verified using the Control Register (CONTROL) and the Security Attribution Unit (SAU). The CONTROL register indicates whether the processor is in privileged or unprivileged mode, while the SAU configuration determines the security state. Use the following code to check the current context:
uint32_t control_reg = __get_CONTROL();
uint32_t is_privileged = !(control_reg & 0x1); // Bit 0 indicates privilege
uint32_t is_secure = __TZ_get_PSPLIM_NS() == 0; // Check secure state
If the processor is in an unprivileged or non-secure state during the VLDR
execution, it may lack the necessary permissions to access the FPU or memory. Ensure that the code is executed in a privileged and secure context.
Debugging the HardFault
The Configuration Fault Status Register (CFSR) provides detailed information about the cause of the HardFault. Inspect the CFSR to determine whether the fault is due to an alignment issue, an access violation, or an FPU configuration error. The CFSR can be accessed using the following code:
uint32_t cfsr = SCB->CFSR;
if (cfsr & SCB_CFSR_IMPRECISERR_Msk) {
// Imprecise data access error
} else if (cfsr & SCB_CFSR_UNALIGNED_Msk) {
// Unaligned memory access error
} else if (cfsr & SCB_CFSR_NOCP_Msk) {
// Coprocessor access error (FPU not enabled)
}
Final Recommendations
- Add
DSB
andISB
instructions after enabling the FPU inSystemInit()
. - Verify the alignment of the memory address used in the
VLDR
instruction. - Ensure the processor is in a privileged and secure context during FPU operations.
- Inspect the CFSR to identify the specific cause of the HardFault.
- Use debugging tools to step through the code and verify the values of critical registers (CPACR, NSACR, CONTROL, CFSR).
By following these steps, the HardFault issue can be systematically diagnosed and resolved, ensuring proper FPU configuration, memory alignment, and processor context.