Reset reason to safely delete bonds of nRF52832

Hello,

We have a product which is a custom nRF52832 board, nRF5 SDK (didn't have time to upgrade to nRF Connect SDK), s132, BLE. 

We used to call delete_bonds() function in security failure event. This fault on our behalf of course, caused many problems, since security fail can happen for many reasons, the device erased bonding information often. Then clients had to delete bonds from the mobile device to be able to reconnect to nRF52832, and this behaviour is not user friendly.

On another ticket, I got the reply that we shouldn't call delete bonds anywhere, and to allow repairing. 

But, since we couldn't reproduce the error of the clients, and we want to be safe, we want to use the Reset button, as a "factory reset", which will reset the device and delete the bonds. 

I used this code:

int32_t reset_reason = NRF_POWER->RESETREAS;
NRF_LOG_INFO("Reset reason = 0x%x.\n", reset_reason);
NRF_POWER->RESETREAS = NRF_POWER->RESETREAS;

to retrieve the reason of the reset (after reset), and then if reset = 0x1 (pin reset) I called delete_bonds function.

as I found here: 

RESETREAS and here https://devzone.nordicsemi.com/f/nordic-q-a/48446/how-to-detect-cause-of-reset

The problem is that I tested all of the above and it worked fine, using debugger (connected the board on a DK) and having enabled NRF_LOG_ENABLED and NRF_LOG_BACKEND_RTT_ENABLED. 

When i disabled them and tried to test the board not connected to the debugger, the reset reason I get for soft-reset (error from the code) is 0x4 and sometimes it is 0x0. Also from pin-reset I get 0x0, which is supposed to be 0x1

The register doesn't work without the debugger? What could be wrong in this situation? 

Thank you in advance, and I would really appreciate if you can help me on how to achieve to safely rcognise pin-rest, to perform delete bonds only in this case of device reset. 

Best regards, 

Dimitra

  • Hi Dimitra

    Disabling the debugger shouldn't change the reset reasons if the application is running as it should, so I'm guessing that when you disable the logging, something is failing in your application causing this soft-reset you're seeing. Maybe something in your application is trying to use logging, and that the application crashes when you disable it. Have you also commented out the calls to the logging after disabling the logs on your end.

    Best regards,

    Simon

  • Okay, I will describe what I do for logging:

    First, main function starts with these lines:

    //Initialization
      log_init();                             //Initialize logs.
      int32_t reset_reason = NRF_POWER->RESETREAS;
      NRF_LOG_INFO("Reset reason = 0x%x.\n", reset_reason);
      NRF_POWER->RESETREAS = NRF_POWER->RESETREAS;
    
      fds_module_init();                      //Initialize Flash Storage Module.
    
      gpio_init();                            //Initialize general purpose input/output.
    
      gpiote_init();                          //Initialize general purpose input/output task and events.
    
      dfu_async_svci_init();                  //Initialize async svci for device firmware update bootloader.
      
      .... // more initializations 
    }


    Then, in the main file, I use a custom function that works like APP_ERROR_CHECK, and what it does is that it takes the error code that is the return value from almost all of the functions from libraries softdevice etc, and save it in flash along with timestamp and some other information. 

    I have also redefined the weak  function app_error_fault_handler , which does the same, takes error code, line and file info saves them in flash and then performs soft-reset, which is done by calling this function:

    void hardfault_handler(void)
    {
      __disable_irq();
    
      NRF_LOG_FINAL_FLUSH();
      
      NVIC_SystemReset();
    }


    I have also changed something in app_error.h file. 
    /**@brief Macro for calling error handler function.
     *
     * @param[in] ERR_CODE Error code supplied to the error handler.
     */
    #ifndef DEBUG   //NOTE changed here ifdef to ifndef 
    #define APP_ERROR_HANDLER(ERR_CODE)                                    \
        do                                                                 \
        {                                                                  \
            app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__);  \
        } while (0)
    #else
    #define APP_ERROR_HANDLER(ERR_CODE)                                    \
        do                                                                 \
        {                                                                  \
            app_error_handler_bare((ERR_CODE));                            \
        } while (0)
    #endif

    see the NOTE. I changed it so that when in Release mode, I can still get line and file information of the error to save them in flash. 

    Finally, I call NRF_LOG_INFO in many lines in my code, which I don't comment them out when I create the hex file and operate the device without debugger. 

    1) Could the functionality I made with app_error.h, and fault handlers cause the fault ? 
    2) Should I not use NRF_LOG_INFO (should I comment these lines) when I make release code to work without debugger, and not even initiliaze logging with log_init() function in main function?
    3) Should I don't call NRF_LOG_FINAL_FLUSH(); in handler that starts the reset ? 


    Thank you very much for your help in advance,
    Best regards,
    Dimitra

  • Hi

    1. I don't think it's a good idea to change app_error.h with custom features.

    2. When you don't initialize logging you should indeed not call logging functions like NRF_LOG_INFO() in your application.

    3. If logs aren't deferred, then this call has no use and will be empty, but I don't think it will be a problem calling it before a reset, since that is what it's used for (macro for flushing log data before a reset).

    Best regards,

    Simon

  • 1. I don't think it's a good idea to change app_error.h with custom features.

    But, all we do is calling the function app_error_handler() and not app_error_handler_bare() when in release mode, so that we have access to information such as line and file of an error that might occur. 
    So far, we haven't noticed any strange behaviour regarding this, do you think we should undo it?

    2. When you don't initialize logging you should indeed not call logging functions like NRF_LOG_INFO() in your application.

    We do initialize it and call NRF_LOG_INFO. We just don't have NRF_LOG_ENABLED enable (it is 0) in the production version. This I believe works fine, and the these calls are just empty when the NRF_LOG_ENABLED define is zero. Please confirm that this is true, otherwise we must comment any print we have in the code (print such as NRF_LOG_INFO) for debugging purposes.. 

    #define NRF_LOG_INTERNAL_MODULE(level, level_id, ...)                                    \
        if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) &&                                   \
            (level <= NRF_LOG_DEFAULT_LEVEL))                                                \
        {                                                                                    \
            if (NRF_LOG_FILTER >= level)                                                     \
            {                                                                                \
                LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__);                    \
            }                                                                                \
        }

    as i see in the file nrf_log_internal.h , if the NRF_LOG_ENABLED is zero, then the call of the function does nothing.

    So, to turn back to our problem, we still cannot find out why the register RESETREAS doesn't have the expected values when the external debugger (from DK) is not connected. 

    I will explain again, that, after a button reset on our custom board, we expect that this register will have the value 0x01. 
    When we check this with our board connected to the DK to use the external debugger, it does have this value. The button is connected to p0.21 (pin reset) and this "CONFIG_GPIO_AS_PINRESET" is included in the preprocessor's definitions. 

    When a soft-reset happens, for example from a function that returns an error code other than NRF_SUCCESS, the reset reason from the register is 0x4 as expected. When the button is pressed, however, 0x1 is the value with the debugger, and 0x0 is the value without the debugger. 
    Also, after some more tests, I see that the reason might be 0x1 after double press or more of the button. We cannot understand why this strange behaviour happens. 

    Finally, this is very important to us, because we want to use the reset reason in order to delete bonds. (when reset reason is 0x1 we will call delete_bonds function) . But we do not want this to happen any other time in case that the register does not work without the debugger. 

    Hope my description helps, and I really look forward for your assistance. 

    Best regards, 
    Dimitra

    Edit

    I tested many times trying to find what is going on and I want to make something clear, that maybe will help you understand what I am doing wrong or what is going on...

    1. When I connect my custom board with the devkit to use it as an external debugger, I also enable NRF_LOG_ENABLED and NRF_LOG_BACKEND_RTT_ENABLED and also I comment the call of the function dfu_async_svci_init() in main in order to see the debugging messages in Segger Embedded Studio. 
    In this case, the reset reasons I read from the register are correct, and the RED led I have on the board blinks when reason is 0x1, which is when I press the pin-reset button. 

    2. When I disable NRF_LOG_ENABLED and NRF_LOG_BACKEND_RTT_ENABLED and uncomment the dfu_async_svci_init(), and download the application through segger, it also works when the board is connected to the debugger (devkit) and when it is not ! (red led blilnks which indicates to me that the reason is 0x1). 

    3. When I keep the logs disabled and create the hex file, which includes softdevice and bootloader, and download this on the board through the nRF Connect App, then the reset reason doesnot work as expected and when I press the button when the board is not connected to the devkit debugger!  the RED led doesnot turn on to indicate to me that the reason is 0x01 and the another led blinks which means that the reason is 0x00. 

    So is it the bootloader's fault that the behaviour has been changed? 

    Or is the debugger? In all cases, it works as expected when the board is connected to the debugger of the devkit.... But it doesn't when I have bootloader+application and no debugger, which is the real case.. 

    EDIT 2

    After more tests, I find out that when my board is powered by a battery, it works as expected!! (reset register gives 1 for pin reset)
    When it is powered by the Power Profiler Kit II (in ampere mode, power output enabled), the reset register gives 0 for pin reset! 
    All the previous tests were executed with the PPK2, so probably this was the problem from the beginning. But why? How can this be the cause ? 

  • Hi Dimitra, 

    DimitraN said:
    So is it the bootloader's fault that the behaviour has been changed? 

    Yes, the bootloader clears the resetreason at nRF5_SDK_17.1.0_ddde560\components\libraries\bootloader\nrf_bootloader.c:crc_on_valid_app_required:nrf_power_resetreas_clear

    Put a breakpoint here and see if your execution hits here. If it does, comment this clear function so that your application can read the RESETREAS and then the application should clear this register.

Related