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,

  • 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 chip is nRF51822 QFACA1 (1810DH). The SDK-12.3.0 (d7731ad) release notes says that SoftDevice-2.0.1 is compatible with nRF51 revision 3 only. I'm not completely sure that my nRF51 chip is rev3... could anyone confirm 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

Related