Asserts and Faults
Asserts
We make liberal use of the ASSERT macro in the sample applications. Asserts are intended to catch unexpected OS and stack failures that we can't recover from.
The syntax is:
ASSERT(truth test);
if the truth test is false, an assert_handler will be called.
E.g. After attempting to create a semaphore, we expect OSSemCreate() to return a pointer to an OS_EVENT, and we test this with an ASSERT.
OS_EVENT* mySemaphore; mySemaphore = OSSemCreate(0); ASSERT(mySemaphore != NULL);
For OS and stack functions that return an error code, during debugging it may be useful to print the error before testing with an ASSERT.
The assert_handler:
- prints the stack usage for all tasks
- disables the radio
- saves the assert to the log (which can be retrieved by the manager using the getLog API command)
- prints out the file and line of the assert
- resets the part
A sample:
Task 1 ? used 33 of 256 (12%) Task 10 drvMon used 89 of 128 (69%) Task 14 macCtrl used 116 of 256 (45%) Task 15 macMon used 51 of 256 (19%) Task 32 net used 35 of 384 (9%) Task 34 loc used 157 of 384 (40%) Task 36 moteMon used 117 of 320 (36%) Task 50 locNotif used 42 of 256 (16%) Task 51 locCtrl used 110 of 256 (42%) Task 53 spi used 114 of 256 (44%) Task 54 myTask used 63 of 512 (12%) Task 63 uC/OS-II Idle used 18 of 64 (28%) assert: my_app.c: 123
Note that for some versions of the networking stack, an assert will also print a fault to show the contents of various registers.
Faults
The stack installs several fault handlers. The default handler prints all registers, while the special handlers listed below may only print a subset.
- BUS Fault - Memory access error, such as an invalid pointer.
- MPU Fault - Accessing a null pointer or exiting a task will result in an MPU fault.
- Bad power - The part can fault if your supply dips to the brownout voltage. It is not uncommon to see this on a DC9003 that has the power switch off, but the mote is being powered through IOs via the DC9006.
- The other faults relate to hardware conditions that are rare. If you have eliminated the first two causes, and still see the same fault on different boards, contact factory apps (dustsupport@linear.com).
The part will also reset in the case of a fault.
It can take 5-10 s for the part to reset after an assert or fault.
Faults print the current time (OS time), and the contents of various registers. The following code stores a value at an invalid memory location:
int *pointer; pointer = (int *) 0x20302030; // this is outside of SRAM *pointer = 42;
Which results in the following fault:
Time = 59a04 Fault R0 = 2a R1 = 20302030 R2 = 200008d4 R3 = 4 R12 = 0 LR = 489c5 PC = 4ccce (Program counter - this may be able to tell you which part of the code is causing the fault) PSR = 21000000 BFAR = 20302030 (Bus Fault Address Register - may contain the bad address or the BFAR address of e000ed38) CFSR = 8200 (Configurable Fault Status Registers - indicates precise data bus error and BFAR holds address) HFSR = 0 (HardFault Status register) DFSR = 0 (Debug Fault Status Register) AFSR = 0 (Auxiliary Fault Status Register) MFAR = 20302030 (MemManage Address Register - may contain the bad address or the MFAR address of e000ed34) IPSR = 400805 NVIC_ACTIVE0_R = 0 NVIC_ACTIVE1_R = 0 NVIC_SYS_HND_CTRL_R = 70002 (System Handler Control and State Register) SP = 200008c8
Changing pointer
to a null pointer results in an MPU fault:
MPU Fault Time = 3eb2 LR = 489c5 PC = 4ccce BFAR = 0
See the Cortex-M3 Technical Reference Manual for more details.