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.