This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Logging assert failures in freeRTOS

I am trying to use the NRF_LOG system with FreeRTOS.     In the case of an ASSERT, I want to be able to:

1) log the location of the assertion

2) flush the logs over RTT

3) reset

The issue I'm seeing is that adding a flush to the ASSERT macro causes the worst case stack usage of all tasks to increase dramatically.  Each stack now requires at lease 1000 bytes because the nrf_log_frontend needs ~300 bytes and nrf_log_backend_rtt_put requires ~700 bytes. 

What method is recommended for avoiding this excessive stack usage?

Is there a way to trigger log flushing from the logger_thread instead of the current thread?

Parents
  • Hello,

    looking in the app_error_weak.c the assert does flush automatically, so there is no reason to add the flush. Also this stack usage is not related to FreeRTOS, it would be the same on baremetal too.
  • The issue in the RTOS is that every task needs to reserve the additional space for the flush, so if you have 5 tasks then the 300 bytes is actually 1500 bytes since every task might have an assert that causes a flush.  Clearly this is not the same as on baremetal.

    One difficult problem with RTOS is selecting an appropriate size for the stack.  Since the worst case conditions may not happen very often it is easy to believe your stack is working only to discover in some rare corner case you exceed the stack.  The stack guards implemented in freeRTOS do NOT guarantee the detection of stack corruption for another thread, its very easy to describe a case where a large allocation on the stack in a rare circumstance (such as an assert) greatly exceeds the end of the tasks stack, since automatic variables are not initialized the stackguard would not detect the overflow but another stack would corrupted.

  • Hi Anthony,

    Seems like the assert function that comes with the SDK is not very stack friendly in terms of memory it uses.

    If you want all the logs to be handled only though one task, logger_task, then you can see the example of SDK\examples\ble_peripheral\ble_app_hrs_freertos\main.c and see how it is done. The idea is simple, create a logger task and make sure that it is only run in the idle time by implementing the vApplicationIdleHook and resuming the logger task in this hook. I believe this is what you are looking for.

Reply
  • Hi Anthony,

    Seems like the assert function that comes with the SDK is not very stack friendly in terms of memory it uses.

    If you want all the logs to be handled only though one task, logger_task, then you can see the example of SDK\examples\ble_peripheral\ble_app_hrs_freertos\main.c and see how it is done. The idea is simple, create a logger task and make sure that it is only run in the idle time by implementing the vApplicationIdleHook and resuming the logger task in this hook. I believe this is what you are looking for.

Children
  • The issue is that the ASSERT is called deep inside of API code instead of passing back error codes.   Also since the ASSERT calls NRF_LOG_FLUSH() it actually requires additional stack space for the logging backend operation which is not reported by the static analysis since it is called from a function pointer.

    The logger thread by itself does not fix this problem.  However I have modified the example assert to eliminate the flush.  My workaround is to set a flag in the assert and then raise the priority and resume the logger thread which will perform the flush.

Related