Flash operations do not work in the hard fault handler (HardFault_c_handler function).

Hi,

I want to log the error type and program counter when a hard fault occurred. I implemented some algorithm for that, I am using fds library for saving this information to flash. I do not get an error when saving hard fault information on the flash. 

How can i save hard fault information to the flash?

  • Hello,

    I guess there are different ways, but considering you are in the hardfault handler and you can't really depend on any software modules to work, and the interrupts are disabled (or lower priority), so you would need to use flash api that are bare metal and don't rely on interrupts or other software modules. In that case I suggest to use the api in \modules\nrfx\hal\nrf_nvmc.c directly, for instance call nrf_nvmc_page_erase() to erase the flash page you want to store the information, and then follow by one or several calls to nrf_nvmc_write_words(), before you do a system reset to start the chip again. It may be that you need to rename the api in \modules\nrfx\hal\nrf_nvmc.c, because you may using a similar api in your project already that rely on other software modules.

    Kenneth

  • Also have a look at this post if you are using the Softdevice in your application:  RE: Disable Softdevice sandboxing in fault handler  

  • Hi Thank your for the reply,

    I just want to see if I can write to flash.

    FDS_BACKEND 1 in sdk_config.

    int main(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
        
        APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
        
        power_management_init();
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        nrf_delay_ms(10000);
    
        hardfault_genhf_invalid_fp();
    }
    
    #define ADDRESS_OFF_TEST                    0x76000
    
    void flash_set_data(const uint8_t * src){
        nrf_nvmc_write_bytes(ADDRESS_OFF_TEST, src, sizeof(uint8_t));
    }
    
    void flash_get_data(uint8_t * dst){
        memcpy(dst, (uint8_t*)ADDRESS_OFF_TEST, sizeof(uint8_t));
    }
    
    /** @breif Errors caused by Bus Fault, Memory Management Fault, or Usage Fault
     *
     * @note If you want to use custom HardFault_c_handler(), Don't include hardfault_handler_gcc.c file on makefile.
     *       Don't include hardfault_implementation.c file on makefile.
     *
     * @note In order to use this function, the @ref init_hardfault_storage() function must be used.
     */
    void HardFault_c_handler(uint32_t * p_stack_address){
        uint8_t  buffer[1];
        flash_get_data(buffer);
        BB_printf(LOG_FATAL, "Counter : %u", buffer[0]);
        
        buffer[0] = buffer[0] + 1;
        flash_set_data(buffer);
        
        nrf_delay_ms(1000);
    
        // Restart the device.
        NVIC_SystemReset();
    }

    I can not write to flash. Wham Am i doing wrong?

  • NRF_MWU->PREGION[0].SUBS &= ~(MWU_PREGION_SUBS_SR30_Include << MWU_PREGION_SUBS_SR30_Pos);
    __DSB(); // barrier to ensure register is set before accessing NVMC.  

    I used it at starting of HardFault_c_handler() function. 

  • Have you confirmed through debugging that flash_set_data() ends up being called in HardFault_c_handler()?

Related