Debugging a Program Exit¶
The program must never exit the main()
function. The usual cause for this is
that some software module has called abort()
.
Both IAR and CCS will halt execution when this happens, and the disassembly and call stack will show some type of __exit symbol.
The BLE Stack will call ICall_abort()
when one of the below happens:
- Calling an ICall function from a stack callback
- Misconfiguring of additional ICall tasks or entities
- Incorrect ICall task registering
Should the call stack not give enough information to deduce the cause of the
abort, a breakpoint can be set in the ICall_abort
function to trace from
where this error is coming.
HAL Assert Handling¶
Asserts can be useful when debugging, to trap undesirable states in
the code. The BLE Stack projects are by default set up to have the global
preprocessor symbol EXT_HAL_ASSERT
enabled, which will try to call an assert
handler that the user application can define.
Catching Stack Asserts in the Application¶
The application has an assert callback to catch asserts in the stack project. The assert callback is registered in main() function of each project:
/* Register Application callback to trap asserts raised in the Stack */
RegisterAssertCback(AssertHandler);
The main.c
file also contains an example AssertHandler
function.
Some generic assert causes that can be returned in the callback
include HAL_ASSERT_CAUSE_TRUE
,
HAL_ASSERT_CAUSE_OUT_OF_MEMORY
, and
HAL_ASSERT_CAUSE_ICALL_ABORT
.
When using a split-image build configuration, it may be possible to get a
HAL_ASSERT_CAUSE_INTERNAL_ERROR
assertion. This typically indicates that
the ICall bleAPITable
dispatch table is missing some functions so it calls
a generic icall_liteErrorFunction
error handler. Typically, a fix for this
is error is to enable a missing predefined compiler option to get correct APIs
into bleAPITable
.
The user can decide how to handle these asserts in the callback. By default, it goes into spinlock for most of the asserts.
The assert can also define a subcause that gives a more specific
reason for the assert. An example of a subcause is
HAL_ASSERT_OUT_OF_HEAP
, which describes the type of memory
causing the assert for HAL_ASSERT_CAUSE_OUT_OF_MEMORY
.
If no application callback is registered, the default assert
callback is called and returns without further action unless
HAL_ASSERT_SPIN
is defined in the application project, which traps
the application in an infinite while loop. In addition, one of the
following can also be defined in the stack project if it is not
caught in the application callback:
HAL_ASSERT_RESET
: Resets the deviceHAL_ASSERT_LIGHTS
: Turn on the hazard lights (to be configured by user)HAL_ASSERT_SPIN
: Spinlock in a while loop indefinitely
Enable these by ensuring that one of the above corresponding symbols are defined in the preprocessor symbols.
See hal_assert.h and hal_assert.c in the stack project for implementation details.