SPRAD28 October 2022 AM2431 , AM2432 , AM2434 , AM2631 , AM2631-Q1 , AM2632 , AM2632-Q1 , AM2634 , AM2634-Q1 , AM263P4 , AM263P4-Q1 , AM26C31 , AM26C31-EP , AM26C31M , AM26C32 , AM26C32-EP , AM26C32C , AM26C32M , AM26LS31 , AM26LS31M , AM26LS32A , AM26LS32AC , AM26LS32AM , AM26LS33A , AM26LS33A-SP , AM26LS33AM , AM26LV31 , AM26LV31E , AM26LV31E-EP , AM26LV32 , AM26LV32E , AM26LV32E-EP , AM26S10 , AM2732 , AM2732-Q1
In order to detect what caused an exception, you can use the registers above inside the exception handlers themselves. Here is an example of simulating a usage fault exception inside the empty example of the MCU+ SDK and handling it with the registers above:
void empty_main(void *args)
{
/* Open drivers to open the UART driver for console */
Drivers_open();
Board_driversOpen();
//Enable all configurable exceptions:
uint32_t *pSHCSR = (uint32_t*)0xE000ED24;
*pSHCSR |= ( 1<< 16); //Memory Manage Fault
*pSHCSR |= ( 1<< 17); //Bus Fault
*pSHCSR |= ( 1<< 18); //Usage Fault
//Force the processor to execute an undefined instruction from DRAM
uint32_t* pADDR = (uint32_t*)0x00030001;
*pADDR = 0xFFFFFFFF;
void (*temp_address) (void);
temp_address = pADDR;
temp_address();
while(1);
Board_driversClose();
Drivers_close();
}
Running this code causes the processor to execute an undefined instruction and end in the UsageFault handler.
Inside the UsageFault handler (HwiP_armv7m_handlers_nortos.c), you can use the Usage Fault Status Register (UFSR) by reading and printing its value & 0XFFFF.
void HWI_SECTION HwiP_usageFault_handler()
{
uint32_t *pUFSR = (uint32_t*)0xE000ED2A;
volatile uint32_t loop = 1;
printf("UsageFault Exception\n");
printf("UFSR = %x\n", (*pUFSR) & 0xFFFF);
while(loop)
;
}
Since an undefined instruction is executed, you can expect this register to be equal to '1':