The Cortex-M0+ core can hang up or freeze at the address FFFF FFFEh when executing the DSB (Data Synchronization Barrier) instruction. This is often an indication of a bug or issue in the way the DSB instruction is being used in the code running on the Cortex-M0+ core.
What is the DSB instruction?
The DSB instruction, also known as the Data Synchronization Barrier instruction, is used to synchronize memory accesses between the processor and memory system of an ARM processor like the Cortex-M0+. It ensures that all memory accesses initiated before the DSB instruction are completed before any subsequent instructions begin execution.
The DSB acts as a barrier by stalling the pipeline until all outstanding memory transfers are completed. This is important for situations where order and timing of memory operations matter, like when interacting with memory-mapped peripherals or ensuring data coherency in multicore systems.
Why does the Cortex-M0+ hang at FFFF FFFEh with DSB?
The address FFFF FFFEh corresponds to the Debug Monitor Exception vector on ARM Cortex-M cores. When a fault or exception occurs, the core will jump to this address to handle the debug exception.
In the case of a DSB hang up, the most likely causes are:
- Invalid memory access – The DSB tried to synchronize an invalid or restricted memory access, causing a fault.
- Unaligned access – The memory address in the load/store instruction preceding the DSB was unaligned, causing an alignment fault.
- MPU configuration error – The Memory Protection Unit (MPU) was set up incorrectly, denying access to a region of memory.
- Undefined instruction – The code preceding the DSB contained an undefined or unimplemented instruction.
The DSB ends up triggering the debug monitor exception handler because of one of these illegal conditions. But the handler itself is unable to recover or return properly, so the core remains stuck at FFFF FFFEh.
Fixing a DSB hang up on Cortex-M0+
Fixing the DSB hang up requires identifying and resolving the root cause that is triggering the exception. Some troubleshooting tips include:
- Check alignment of memory addresses used before the DSB. Align to 4-byte boundaries.
- Verify no unaligned memory writes happen before the DSB.
- Confirm that memory regions accessed have valid permissions configured in MPU.
- Rule out any undefined instructions like invalid Thumb encodings.
- Examine exception handler code to ensure graceful exception return.
- Use debugger or trap handlers to identify offending instruction.
Modifying the linker scripts or scatter files to align the Debug Monitor exception handler to a 4-byte boundary can also help avoid alignment issues.
It is also good practice to place DSB instructions after memory transfers rather than before. Check that no unexpected exceptions occur in code preceding the DSB.
Example code causing DSB hang
A common coding mistake is placing a DSB immediately after configuring memory regions. This often results in a hang or freeze: // Set up MPU regions MPU->RBAR = 0x00000000; MPU->RASR = // region 0 config // DSB hangs here __DSB();
The MPU configuration expects valid memory transfers to occur before synchronizing via DSB. But an immediate DSB causes an invalid access fault, hanging the core.
Instead, place the DSB after actual memory accesses: // Set up MPU regions MPU->RBAR = 0x00000000; MPU->RASR = // region 0 config // Memory transfers using new MPU settings buffer = value; // DSB works correctly here __DSB();
Using DSB safely in Cortex-M0+ code
Some tips for using DSB instructions safely in Cortex-M0+ code:
- Place DSBs after memory access instructions, not before.
- Avoid using DSBs immediately after MPU configurations.
- Use DSBs after mutex acquire or release operations.
- Insert DSBs to enforce order between memory mapped writes.
- Utilize DSBs to synchronize writes to peripherals or shared memory.
- Validate memory regions accessed before using DSB.
- Align exception vectors like Debug Monitor to avoid hangs.
- Reference ARM documentation on proper DSB usage.
With careful placement and validation of memory accesses around DSBs, hangs and Freeze ups can be avoided in Cortex-M0+ applications.
Debugging a DSB hang
To debug a DSB hang:
- Connect a debugger and halt execution at the DSB instruction.
- Step backwards through code and examine memory accesses.
- Set watchpoints on exception handler entry.
- Analyze call stack and exception context.
- Inspect memory locations accessed prior to DSB for alignment issues.
- Check for MPU violations using MPU debug registers.
- Verify no uninitialized stack variables are accessed.
Debugging works best with symbols and source code available. The faulting instruction can be identified through the program counter value in the debug exception context.
For embedded Cortex-M0+ devices, debug logs and breakpoint traps can help pinpoint root cause without a debugger.
To summarize, the Cortex-M0+ core hangs at FFFF FFFEh when a DSB instruction generates an exception that the handler cannot recover from properly. This is typically caused by invalid memory access, unaligned addresses, MPU configuration errors, or undefined instructions preceding the DSB.
Following best practices of validating memory operations, proper alignment, and careful DSB placement helps avoid hangs. Debuggers and debug code can identify root cause and faulty instructions. With robust exception handling and protected memory access, DSBs can be used safely even on Cortex-M0+ devices.