APPENDIX E Cortex-M3 Troubleshooting Guide
One of the challenges of using the Cortex-M3 is to locate problems when the program goes wrong. The Cortex-M3 processor provides a number of fault status registers to assist in troubleshooting (see Table E.1).
The MMSR, BFSR, and UFSR registers can be accessed in one go using a word transfer instruction. In this situation the combined fault status register is called the Configurable Fault Status Register (CFSR).
Another important piece of information is the stacked Program Counter (PC). This is located in memory address [SP + 0x24]. Since there are two stack pointers in the Cortex-M3, the fault handler might need to determine which stack pointer was used before obtaining the stacked PC.
In addition, for bus faults and memory management faults, you might also able to determine the address that caused the fault. This is done by accessing the MemManage (Memory Management) Fault Address Register (MMAR) and the Bus Fault Address Register (BFAR). The contents of these two registers are only valid when the MMAVALID bit (in MMSR) or BFARVALID bit (in BFSR) is set. The MMAR and BFAR are physically the same register, so only one of them can be valid at a time (see Table E.2).
Finally, the Link Register (LR) value when entering the fault handler might also provide hints about the cause of the fault. In the case of faults caused by invalid EXC_RETURN value, the value of LR when the fault handler is entered shows the previous LR value when the fault occured. Fault handler can report the faulty LR value, and software programmers can then use this information to check why the LR ends up with an illegal return value.
In most cases, fault handlers for development and for real running systems differ from one another. For software development, the fault handler should focus on reporting the type of error, whereas the fault handler for running systems will likely focus on system recovery actions. Here we cover only the fault reporting because system recovery actions highly depend on design type and requirements.
In complex software, instead of outputting the results inside the fault handler, the contents of these registers can be copied to a memory block and then you can use PendSV to report the fault details later. This avoids potential faults in display or outputting routines causing lockup. For simple applications this might not matter, and the fault details can be output directly within the fault handler routine.
The most basic step of a fault handler is to report the fault status register values. These include:
The step for getting the stacked PC is similar to the SVC example in this book.
This process can be carried out in assembly language as:
To help with debugging, we should also create a disassembled code list file so that we can locate the problem easily.
The fault address register can be erased after the MMARVALID or BFARVALID is cleared. To correctly access the fault address register, the following procedure should be used:
The reason for this procedure instead of reading valid bits first is to prevent a fault handler being preempted by another higher-priority fault handler after the valid bit is read, which could lead to the following erroneous fault-reporting sequence:
Therefore it is important to read the BFARVALID/MMARVALID after reading the Fault Address register to ensure that the address register content is valid.
After the fault reporting is done, the fault status bit in the FSR should be cleared so that next time the fault handler is executed, the previous faults will not confuse the fault handler. In addition, if the fault address valid bit is not clear, the fault address register will not get an update for the next fault.
It is often necessary to save the contents of LR in the beginning of a fault handler. However, if the fault is caused by a stack error, pushing the LR to stack might just make things worst. As we know, R0–R3 and R12 should already been saved, so we could copy LR to one of these registers before doing any function calls.
After obtaining the information we need, we can establish the cause of the problem. Tables E.3–E.7 list some of the common reasons that faults occur.
A number of other common problems are in Table E.8.
13.59.80.187