The exact configuration options available are specific to the Cortex-M implementation being used. This register only exists for Cortex-M7 devices. A full discussion of memory interfaces is outside the scope of this article but more details can be found in the reference manual 4. However, there are a few memory access errors that will always result in a MemManage fault — such as trying to execute code from the system address range 0xExxx.
To fix a fault, we will want to determine what code was running when the fault occurred. To accomplish this, we need to recover the register state at the time of exception entry. If the fault is readily reproducible and we have a debugger attached to the board, we can manually add a breakpoint for the function which handles the exception. In GDB this will look something like. Upon exception entry some registers will always be automatically saved on the stack.
Depending on whether or not an FPU is in use, either a basic or extended stack frame will be pushed by hardware. Regardless, the hardware will always push the same core set of registers to the very top of the stack which was active prior to entering the exception. If the bit is set, the psp was active prior to exception entry, else the msp was active.
The astute observer might wonder what happens when a new fault occurs in the code dealing with a fault. If you have enabled configurable fault handlers i.
At this level or above, a fault will put the processor in an unrecoverable state where a reset is expected. This state is known as Lockup. Typically, the processor will automatically reset upon entering lockup but this is not a requirement per the specification. For example, you may have to enable a hardware watchdog for a reset to take place. When a debugger is attached, lockup often has a different behavior.
When a lockup happens, the processor will repeatedly fetch the same fixed instruction, 0xFFFFFFFE or the instruction which triggered the lockup, in a loop until a reset occurs. At this point we have gone over all the pieces of information which can be manually examined to determine what caused a fault. While this might be fun the first couple times, it can become a tiresome and error prone process if you wind up doing it often.
What if we are trying to debug an issue that is not easy to reproduce? Even if we have a debugger attached, useful state may be overwritten before we have a chance to halt the debugger and take a look. Above , we discussed how to hand unroll the register state prior to the exception taking place. Now when a fault occurs and a debugger is attached, we will automatically hit a breakpoint and be able to look at the register state!
Furthermore, we now have a variable we can read stack info from and a C function we can easily extend for postportem analysis! Many embedded IDEs expose a system view that can be used to look at registers. The registers will often be decoded into human readable descriptions. To use the utility, all you need to do is update your. The previous two approaches are only helpful if we have a debug or physical connection to the device.
Once the product has shipped and is out in the field these strategies will not help to triage what went wrong on devices. One approach is to simply try and reproduce the issue on site. I did find the diagnostic lof on the disk.
It was from back in August when I bought the system. This log also showed the Memory Faults. So have hey always been there. Really no reason to believe the memory is bad as everything does work. Was this reply helpful? Yes No. Sorry this didn't help. Thanks for your feedback. This thread is locked. You can follow the question or vote as helpful, but you cannot reply to this thread. I have the same question The fault handler is shown below using GCC syntax.
Note that the function is declared as being naked, so it does not contain any compiler generated code for example, there is no function entry prologue code. The variables are named to indicate the register value that they hold. Other registers will not have changed since the fault occurred, and can be viewed directly in the debugger's CPU register window. If the debugger won't show the values of the variables, make them global my moving their declaration outside of this function.
In the code above, the variable pc contains the program counter value. When the fault is a precise fault, the pc holds the address of the instruction that was executing when the hard fault or other fault occurred.
When the fault is an imprecise fault, then additional steps are required to find the address of the instruction that caused the fault. To find the instruction at the address held in the pc variable, either Open an assembly code window in the debugger, and manually enter the address to view the assembly instructions at that address, or Open the break point window in the debugger, and manually define an execution or access break point at that address. With the break point set, restart the application to see which line of code the instruction relates to.
Knowing the instruction that was being executed when the fault occurred allows you to know which other register values are also of interest. For example, if the instruction was using the value of R7 as an address, then the value of R7 needs to be know. Further, examining the assembly code, and the C code that generated the assembly code, will show what R7 actually holds it might be the value of a variable, for example.
It is harder to determine the cause of an imprecise fault because the fault will not necessarily occur concurrently with the instruction that caused the fault. For example, if writes to memory are cached then there might be a delay between an assembly instruction initiating a write to memory and the write to memory actually occurring. If such a delayed write operation is invalid for example, a write is being attempted to an invalid memory location then an imprecise fault will occur, and the program counter value obtained using the code above will not be the address of the assembly instruction that initiated the write operation.
0コメント