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

no HardFault on nRF51

My problem is a little bit weird: I don't get a HardFault, although I'd want so.

SDK-12.3.0 (d7731ad), FreeRTOS (from the SDK) and SoftDevice S130 (2.0.1) also from the SDK.

On all other Cortex M machines I used to work with (Kinetis M0, Kinetis M4, nRF52) the following code always generated a nice HardFault:

    uint8_t *ptr = (uint8_t *)0xABADC0DE;
    *ptr = 16;

On the mentioned machines the default HardFault_Handler is always overridden by my version, they work like a charm. I want to have the same on nRF51822 too, but I keep on failing.

The most surprising is that the HardFault doesn't get generated. Or I don't know what happens. E.g. in 1-2% of all cases I see my HardFault_Handler executing, but in the rest cases the execution stops and the watchdog resets the machine. The current HardFault_Handler looks like this:

void HardFault_Handler(void)
{
    bsp_led_set(RED, 1);
    bsp_led_set(GREEN, 1);
    for (;;);
}

I haven't found any traces that HardFaults can be disabled anyhow. Forums are full with posts on handling the HardFault, investigating the reasons, but I found nothing telling why HardFault doesn't generate when it's expected to do so. Of course, I've tried to write to different memory location, different data size... Compiling with debug options also didn't do the trick. I tried in Ozone debugger putting a breakpoint to HardFault_Handler(void), but it doesn't get called...

The primitive SoftDevice init looks like this:

static void bsp_ble_init(void)
{
    uint32_t ret;
    nrf_clock_lf_cfg_t clockcfg = {NRF_CLOCK_LF_SRC_RC, 16, 0, NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM};
    ble_enable_params_t ble_enable_params;

    SOFTDEVICE_HANDLER_INIT(&clockcfg, NULL);
    ret = softdevice_enable_get_default_config(BOARD_BLE_CENTRAL_LINK_COUNT, BOARD_BLE_PERIPHERAL_LINK_COUNT, &ble_enable_params);
    CHECK;
    ble_enable_params.gatts_enable_params.attr_tab_size = 300;
    ret = softdevice_enable(&ble_enable_params);
    CHECK;
}

Any idea?

Thanks, regards,

Parents
  • I've dug into this a little deeper... it appears that with the above code I can successfully generate a HardFault anywhere until the point where vTaskStartScheduler is called. From there the HardFault_Handler doesn't get called. Or no HardFault is raised, although it doubt it...

  • The vTaskStartScheduler should not be able to mask the HardFault_Handler. 

    If I understand correctly, the exact same code after vTaskStartScheduler  o n nRF52 generates hardfault?

    Not sure if this is even possible. 

    On the second thought, I am assuming that when you say that you put the code that generates hardfault after vTaskStartScheduler , I am assuming that you do that in some task. Because the line after vTaskStartScheduler  is never executed in the main() function. The moment vTaskStartScheduler  is called, the RTOS scheduler takes over and the control never reaches to the next line of of vTaskStartScheduler inside main. Maybe this is what you are seeing?

  • You're right, I obviously was wrong, no execution in the parent context is allowed to occur once vTaskStartScheduler is called.

    #define HARDFAULT do { \
        uint32_t *ptr = (uint32_t *)0xABADC0DE; \
        *ptr = 0x12345678; \
    } while (0)
    

    By the way, anywhere in any FreeRTOS task the call of HARDFAULT causes the machine to hang, reset by watchdog, but the HardFault_Handler doesn't seem to be called, because that handler should light two LEDs. And the same handler works perfectly if issued before vTaskStartScheduler.

    As the address of HardFault_Handler is burnt into the flash, it can't be changed in runtime, so at the moment my best idea is that somehow FreeRTOS disables HardFault_IRQ, but I haven't seen any traces of it... or messes with NVIC...

  • not sure why you did not get a hardfault, but trying what you did I can see that it can break into the hardfault handler

Reply Children
  • Another issue: there's a function like this to generate random numbers:

    static void bsp_rng_read_custom_length_do(uint8_t *output, uint32_t len)
    {
    #ifdef SOFTDEVICE_PRESENT
        uint8_t avail = 0;
    
        while (avail < len) {
            if (sd_rand_application_bytes_available_get(&avail) != NRF_SUCCESS) {
                memset(output, 0, len);
                return;
            }
            if (avail >= len)
                break;
            vTaskDelay(pdMS_TO_TICKS(1));
        }
        if (sd_rand_application_vector_get(output, len) != NRF_SUCCES)
            memset(output, 0, len);
    #else   /* SOFTDEVICE_PRESENT */
        /* IMPLEMENT */
    #endif  /* SOFTDEVICE_PRESENT */
    }
    
    If this is executed many times in loop in a task, HardFault occurs. Sometimes the LEDs switch on (as expected, as HardFault_process(...) does so), but sometimes don't. Watchdog resets. Can you reproduce it?

    Isn't my 51822 QFACA1 incompatible with the SDK/SoftDevice?

  • Hi, 

    Please kindly create a new support case for another issue. This will be easy for users to find a solution to the issue. Thanks. 

    -Amanda H.

Related