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

How to find what is causing APP_ERROR:ERROR:FATAL

After I write bonding data to flash memory  (SoftDevice has been disabled before the write) I get an APP_ERROR:ERROR:FATAL. But I do not know what is causing it. I do an NRF_LOG_DEBUG("Flash written\r\n"); after the flash write is done, and it is displayed.

The next log statement is NRF_LOG_DEBUG("Security key data freed\r\n");

but it is never displayed. The only thing that happens before that statement is a bunch of memory is freed. Naturally I thought there might be an error there but commenting out all that code does not change the behavior.  The write to flash is in some sense successful, because on a reconnect, all the bonding information is stored and correctly reloaded and the connection goes fine. So if I never looked at a log I would never know there was an error. There is no error after the disconnect on the reconnect because there is no write to flash (I assume that is the reason).

So it has something to do writing to flash but I have no idea how to find the cause. The error will display even if I comment out all the NRF_LOG statements after the flash write.

How can I debug this?

This is my main process loop - note I am handling the sd_app_evt_wait() and the events via sd_ble_evt_get().

static void main_loop(void)
{
    uint8_t enabled;
    uint16_t len;
    uint32_t result;
    for (;;)
    {
        indicate_data();        // when flag is set, a set of data is indicated. Flag reset in method
        main_wait();            // Contains the sd_app_evt_wait()
        while(true)
        {
            sd_softdevice_is_enabled(&enabled); // Don't do this if disabled, for example when writing flash at the end
            if (enabled != 1)
            {
                while(NRF_LOG_PROCESS());
                break;
            }
            result = sd_ble_evt_get(NULL, &len);    // Get sixe of event
            if (result == NRF_ERROR_NOT_FOUND)      // If there aren't any, go back to wait
            {
                break;
            }
            evt_buf = (uint8_t *)calloc(1, len);                // Make space for event
            result = sd_ble_evt_get((uint8_t *)evt_buf, &len);  // get the event
            if (result == NRF_SUCCESS)
            {
                ble_evt_t *evt = (ble_evt_t *)evt_buf;
                ble_evt_dispatch(evt);                          // dispatch event to handler
                //NRF_LOG_PROCESS();                              // SHould I do this here to get a tighter display of log?
            }
            else                                                // Hopefully no error but just in case log it.
            {        
                #if (USE_DK == 1)
                NRF_LOG_DEBUG("PENDING BLE Event return error: %u\r\n", result);
                #endif
                free(evt_buf);  // Clean up
                break;          // back to wait
            }
            free(evt_buf);      // clean up and get the next event
        }
    }
}

  • Enable the DEBUG preprecessor flagIf you can start your program in debugger, you should be able to see the call trace when the hit the breakpoint of the error like this

  • My file does not have that. s130 for soft device and SDK 12.3.0.

    My file looks like this:

    #include "app_error.h"
    
    #define NRF_LOG_MODULE_NAME "APP_ERROR"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    /*lint -save -e14 */
    
    /**
     * Function is implemented as weak so that it can be overwritten by custom application error handler
     * when needed.
     */
    __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
        NRF_LOG_ERROR("Fatal\r\n");
        NRF_LOG_FINAL_FLUSH();
        // On assert, the system can only recover with a reset.
    #ifndef DEBUG
        NVIC_SystemReset();
    #else
        app_error_save_and_stop(id, pc, info);
    #endif // DEBUG
    }

    It looks like I have to set a DEBUG preprocessor somewhere. The preprocessor list in Keil is one of the most user-unfriendly interfaces I have seen. One line of limited size where one has to enter one after the other. Horrible. Perhaps there is another way?

  • I just added the preprocessor in that ugly line. What I found was that the method sd_app_evt_wait() returns error code 2 which is NRF_ERROR_SVC_HANDLER_MISSING. I did not check for any error codes on this method because the documentation states it only returns NRF_SUCCESS. 

    Opps, error 2 is NRF_ERROR_SOFTDEVICE_NOT_ENABLED. Of course it is disabled. I disabled it. So how do I handle that final for(;;) loop? Should I just return and exit main?

Related