This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nrf_fstorage_write() triggers HARD FAULT only when called from usage fault handler

We are implementing a system where diagnostics info is saved to FLASH when one of the error handlers is called. Our code collects diagnostic registers and stack info, and saves them to a predetermined block in FLASH,

We use our own library which is a wrapper on nrf_storage_write():


volatile bool flash_waiting = false;
void flash_raw_wait_until_done(void);
void flash_raw_callback(nrf_fstorage_evt_t * p_evt);

NRF_FSTORAGE_DEF(nrf_fstorage_t flash_blocks) =
    {
        .evt_handler = flash_raw_callback,
        .start_addr = FLASH_START,
        .end_addr = FLASH_END
    };

void flash_raw_init(void)
{
    PROJECT_ERROR_CHECK(nrf_fstorage_init( &flash_blocks, &nrf_fstorage_sd, NULL));
};

void flash_raw_write_block(const uint32_t * block_start,  const uint32_t * src, const uint8_t n_words)
{
    PROJECT_CHECK_NOT_NULL(block_start);
    PROJECT_CHECK_NOT_NULL(src);
    PROJECT_LOG_DEBUG("WR %d wds to 0x%08x fr 0x%04x", n_words, block_start, src);
    flash_waiting = true;
    ret_code_t rc = nrf_fstorage_write(&flash_blocks, (uint32_t)block_start, src, n_words * (sizeof(uint32_t)), NULL);
    //ret_code_t rc = 0;
    PROJECT_LOG_DEBUG("nrf_fstorage_write returned 0x%04x", rc);

    flash_raw_wait_until_done();
}


void flash_raw_wait_until_done(void)
{
    uint32_t t;
    for (t = 0; t < FLASH_BLK_WRITE_TIMEOUT_MS && flash_waiting; t++) nrf_delay_ms(1);
    if (flash_waiting)
    {
        PROJECT_LOG_ERROR("FLASH operation timed out.");
    }
    else
    {
        PROJECT_LOG_DEBUG("FLASH OK %dms", t);
    }
   
}

void flash_raw_callback(nrf_fstorage_evt_t * p_evt)
{
    if (p_evt->result != NRF_SUCCESS)
    {
        PROJECT_LOG_ERROR("FLASH failure 0x%04x", p_evt->result);
    }
    flash_waiting = false;
}

Everything works fine when we do this from an application error (i.e. we call the error handler ourselves).

However when we call this code from the Usage Fault Handler (after first saving the diag info), the call to nrf_storage_wr() seems to immediately cause another fault which is escalted to a Hard Fault. (We are testing this by deliberately triggering a divide by zero). Log output:

INF main.c 112: kamikaze by DIVZERO!                                            
ERR arm_fault_handling.c 82: CFSR: 02000000 HFSR: 00000000                      
ERR arm_fault_handling.c 83: DFSR: 00000000 AFSR: 00000000                      
ERR arm_fault_handling.c 84: LR: fffffff9 MMFAR: e000ed34                       
ERR arm_fault_handling.c 85: BFAR: e000ed38 PC: 0002eeca                        
ERR arm_fault_handling.c 86: SP: 2000ff98 TOS: 20010000                         
ERR arm_fault_handling.c 87: Stack depth: 26                                    
ERR arm_fault_handling.c 90: stack[00] 2000ff98                                 
ERR arm_fault_handling.c 90: stack[01] 00000001                                 
ERR arm_fault_handling.c 90: stack[02] 00030e97                                 
ERR arm_fault_handling.c 90: stack[03] 00000000                                 
ERR arm_fault_handling.c 90: stack[04] 2000ffd4                                 
ERR arm_fault_handling.c 90: stack[05] fffffff9                                 
ERR arm_fault_handling.c 90: stack[06] 00000000                                 
ERR arm_fault_handling.c 90: stack[07] 00030ff0                                 
ERR arm_fault_handling.c 90: stack[08] 00000001                                 
ERR arm_fault_handling.c 90: stack[09] 00000000                                 
ERR arm_fault_handling.c 90: stack[10] 0000000a                                 
ERR arm_fault_handling.c 90: stack[11] 000264c3                                 
ERR arm_fault_handling.c 90: stack[12] 00026856                                 
ERR arm_fault_handling.c 90: stack[13] 01000200                                 
ERR arm_fault_handling.c 90: stack[14] 000264af                                 
ERR arm_fault_handling.c 90: stack[15] 2000ffe0                                 
ERR arm_fault_handling.c 90: stack[16] 00030e24                                 
ERR arm_fault_handling.c 90: stack[17] 01000000                                 
ERR arm_fault_handling.c 90: stack[18] 2000ffe8                                 
ERR arm_fault_handling.c 90: stack[19] 01046709                                 
ERR arm_fault_handling.c 90: stack[20] 2000fff8                                 
ERR arm_fault_handling.c 90: stack[21] 000267a9                                 
ERR arm_fault_handling.c 90: stack[22] 00030fe0                                 
ERR arm_fault_handling.c 90: stack[23] 00000000                                 
ERR arm_fault_handling.c 90: stack[24] 00000000                                 
ERR arm_fault_handling.c 90: stack[25] 00026297                                 
DBG project_err_debug.c 108: Priv mode? 1                                       
DBG _flash_storage.c 76: writing forensics to 0x00076000                        
DBG _flash_storage_raw.c 36: WR 62 wds to 0x00076000 fr 0x20004                 
ERR arm_fault_handling.c 82: CFSR: 02000000 HFSR: 40000000                      
ERR arm_fault_handling.c 83: DFSR: 00000000 AFSR: 00000000                      
ERR arm_fault_handling.c 84: LR: fffffff1 MMFAR: e000ed34                       
ERR arm_fault_handling.c 85: BFAR: e000ed38 PC: 0002ed22                        
ERR arm_fault_handling.c 86: SP: 2000fe38 TOS: 20010000                         
ERR arm_fault_handling.c 87: Stack depth: 32                                    
ERR arm_fault_handling.c 90: stack[00] 2000fe38                                 
ERR arm_fault_handling.c 90: stack[01] 00000001                                 
ERR arm_fault_handling.c 90: stack[02] 2000fe3c                                 
ERR arm_fault_handling.c 90: stack[03] 0002a195                                 
ERR arm_fault_handling.c 90: stack[04] 2000fe70                                 
ERR arm_fault_handling.c 90: stack[05] fffffff1                                 
ERR arm_fault_handling.c 90: stack[06] 00076000                                 
ERR arm_fault_handling.c 90: stack[07] 20004000                                 
ERR arm_fault_handling.c 90: stack[08] 0000003e                                 
ERR arm_fault_handling.c 90: stack[09] 20004000                                 
ERR arm_fault_handling.c 90: stack[10] 0000000a                                 
ERR arm_fault_handling.c 90: stack[11] 00029ef9                                 
ERR arm_fault_handling.c 90: stack[12] 00029e10                                 
ERR arm_fault_handling.c 90: stack[13] 21000006                                 
ERR arm_fault_handling.c 90: stack[14] 20003aa0                                 
ERR arm_fault_handling.c 90: stack[15] 200039ec                                 
ERR arm_fault_handling.c 90: stack[16] 00000000                                 
ERR arm_fault_handling.c 90: stack[17] 20004000                                 
ERR arm_fault_handling.c 90: stack[18] 00076000                                 
ERR arm_fault_handling.c 90: stack[19] 0000003e                                 
ERR arm_fault_handling.c 90: stack[20] 2000fe90                                 
ERR arm_fault_handling.c 90: stack[21] 00029fbb                                 
ERR arm_fault_handling.c 90: stack[22] 2000feb8                                 
ERR arm_fault_handling.c 90: stack[23] 20003a8c                                 
ERR arm_fault_handling.c 90: stack[24] 2000fea0                                 
ERR arm_fault_handling.c 90: stack[25] 0002a053                                 
ERR arm_fault_handling.c 90: stack[26] 2000fea8                                 
ERR arm_fault_handling.c 90: stack[27] 0002a1fd                                 
ERR arm_fault_handling.c 90: stack[28] 000000f8                                 
ERR arm_fault_handling.c 90: stack[29] 20004000                                 
ERR arm_fault_handling.c 90: stack[30] 00076000                                 
ERR arm_fault_handling.c 90: stack[31] 20002b10                                 
DBG project_err_debug.c 108: Priv mode? 1                                       
DBG _flash_storage.c 76: writing forensics to 0x00076000                        
DBG _flash_storage_raw.c 36: WR 62 wds to 0x00076000 fr 0x20004                 
DBG _flash_storage_raw.c 40: nrf_fstorage_write returned 0x0000                 
ERR _flash_storage_raw.c 60: FLASH operation timed out.      

Why would this be? Do the ARM (Hard Fault, Usage Fault etc) handlers set some flag or place the system in some mode that causes a FLASH write to fail?

Parents
  • I could trace the hard fault to here:

    00029e0e <sd_flash_write>:
       29e0e:    df29          svc    41    ; 0x29
       29e10:    4770          bx    lr
       29e12:    bf00          nop
       29e14:    4618          mov    r0, r3

    So the SVC call seems to trigger the fault.

    I guess somewhere in the handler I need to do something (enable ints?). Our handler is rather simple. SAVE_DIAGNOSTIC_REGISTERS is just a macro that saves all diag info for later saving/printing.

    void UsageFault_Handler(void)
    {
      SAVE_DIAGNOSTIC_REGISTERS;
      project_fatal_error("USAGE FAULT");
    }
Reply
  • I could trace the hard fault to here:

    00029e0e <sd_flash_write>:
       29e0e:    df29          svc    41    ; 0x29
       29e10:    4770          bx    lr
       29e12:    bf00          nop
       29e14:    4618          mov    r0, r3

    So the SVC call seems to trigger the fault.

    I guess somewhere in the handler I need to do something (enable ints?). Our handler is rather simple. SAVE_DIAGNOSTIC_REGISTERS is just a macro that saves all diag info for later saving/printing.

    void UsageFault_Handler(void)
    {
      SAVE_DIAGNOSTIC_REGISTERS;
      project_fatal_error("USAGE FAULT");
    }
Children
No Data
Related