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

sd_softdevice_enable halted (hard fault)

Hi,

I have the problem as described in the title, and I have already searched and looked every thread in this forum about this issue, but none of them seems could help.

The closest case is this one: https://devzone.nordicsemi.com/f/nordic-q-a/45838/sd_softdevice_enable-hardfault/180723#180723 , but in that thread problem was solved by adding 2 preprocessor definitions, not work for me.

My situation is : I'm writing a simplest code doing a single sd_softdevice_enable() call only, and the call never returns, if I tracked it I found the code got stuck at 0x8c8, according to the above thread, that's the hard fault handler address inside MBR.

I created the project from the scratch, but have all the settings set according to the ble_app_blank example in the SDK. Here are the settings I've configured:

Set to use the flash placement file and the xml file is copied from ble_app_blank example.

The segment placement macros are set to:

FLASH_PH_START=0x0

FLASH_PH_SIZE=0x80000

RAM_PH_START=0x20000000

RAM_PH_SIZE=0x10000

FLASH_START=0x26000

FLASH_SIZE=0x5a000

RAM_START=0x20002218

RAM_SIZE=0xdde8

copied Preprocessor definitions from the ble_app_blank:

BOARD_PCA10040

CONFIG_GPIO_AS_PINRESET

FLOAT_ABI_HARD

NO_VTOR_CONFIG

NRF52

NRF52832_XXAA

NRF52_PAN_74

NRF_SD_BLE_API_VERSION=6

S132

SOFTDEVICE_PRESENT

SWI_DISABLE0

INITIALIZE_USER_SECTIONS

set the Additional Load File[0] to s132_nrf52_6.0.0_softdevice.hex

my source code is as this:

// main cpp program

#include <stdio.h>
#include <nrf.h>
#include <nrf_sdm.h> // clock_lf_cfg_t


#define NRF_SDH_CLOCK_LF_SRC 1
#define NRF_SDH_CLOCK_LF_RC_CTIV 0
#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0
#define NRF_SDH_CLOCK_LF_ACCURACY 7

uint32_t result;


void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
{
    printf("nrf sd error");
}

int main(void)
{
    nrf_clock_lf_cfg_t const clock_lf_cfg =
    {
        .source = NRF_SDH_CLOCK_LF_SRC,
        .rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV,
        .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
        .accuracy = NRF_SDH_CLOCK_LF_ACCURACY
    };
    result = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler);
    if (result == NRF_SUCCESS)
    {
        printf("successful");
    }
    else
    {
        printf("error");
    }
    while (1);
}

I modified the ble_add_blank example's main function like this:

/**@brief Function for application main entry.
*/
int main(void)
{
    bool erase_bonds;
    nrf_clock_lf_cfg_t const clock_lf_cfg =
    {
        .source = NRF_SDH_CLOCK_LF_SRC,
        .rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV,
        .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
        .accuracy = NRF_SDH_CLOCK_LF_ACCURACY
    };

    sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler);

...

I let it call the sd_softdevice_enable() right at the beginning of the main() and it returns correctly. But my own code just got stuck in sd_softdevice_enable(). 

As instructed in the above thread, I compared the to .map files, and couldn't find any significant difference. The __reserved_ram_end__ and _app_ram_start__ were both 0x20002218 in two files, and __vectors and __vectors_end__ were both 0x26000 and 0x260dc .

My code goes to the main() when the debugging starts, so the vector tables must work correctly. The sd_softdevice_enable() call in  ble_app_blank example code and my code both jump to address 0x90c , I think which means my code has got the correct SVC call executed.

I believe there must be some compiler or linker settings missing in my code ? But I couldn't figure it out, can anybody help here? Thank you very much!

Jian

Parents
  • Additional Information:

    I found that the assembly code at 0x90c will read a word at address 0x20000000 which is the start of physical RAM and use the content (which is 0x1000 in the ble_app_blank example) to add 0x2c and use the result as the address of next read target , the reading of that address is used as the next jump destination.  The problem with my code is , the content of 0x20000000 is random, so the reading of the 2nd step will be illegal ( most likely go off the range of the memory ). 

    Now I know where the problem is, but still don't know how to fix it.

    I haven't found any code in either the example code or my code to write to 0x20000000 address before it runs to main(), I set break point at 'reset handler' and clear the 0x20000000 content,  then let it runs to main(), the content is not changed, so the content must be written by the J-link debugger while downloading, but I haven't found any instruction for the J-link to do this, where is it?

    Even if I know where and how to instruct the J-link, the question still remains: if there is no code in flash to set the content of 0x20000000, what happens if we disconnect the downloader and re-poweron the board?

    I'm really confused, please help, thanks!

    Jian

  • Hi Jian, 

    My recommendation would be to use the ble_app_template example instead of porting support for the SoftDevice and BLE into a blank example. 

    With regards to your issue you must remember that the SoftDevice and the MBR run before execution is passed on to the application. The MBR will execute first and run its Reset handler, then jump to the SoftDevice Reset Handler, which in turn will jump to the application's reset handler. It is the MBR that writes 0x1000 to the first word in RAM, i.e. at 0x20000000. This address will not be modified afterwards and the application should never write to the SoftDevice RAM region. 

    So it could sound like the application is overwritting the SoftDevice RAM region when it runs its ResetHandler. COuld you attach the project folder so that I could debug the project here on my end. 

  • Hi bjorn-spockeli,
    Thank you very much for the quick response.
    I agree with you that using the template is easier to make it work, actually I did it before and it works, the reason I'm trying to do this is usually I'd prefer to write code in C++ and I found it is a bit tricky to adapt Nordic's template with my code. It would be nice if Nordic could provide a framework for C++ in the future.
    Yes now I realized that the MBR and SD have already run when it reaches the 'reset handler' in the code. What I still don't understand is the content of 0x20000000 was already the 'random' value when the code runs to the reset handler. I was wrong when I said it's random, because I found that value was consistent every time.
    I couldn't find anywhere to attach the file, could you please let me know how to send you the attachment? 
    Best Regards,
    Jian
  • To attach a file, select "Insert" below and then click "Insert Image/video/file"

    So by random value you mean that the value at 0x20000000 is something else than 0x1000, but it is the same value consistently?

    Best regards

    Bjørn

  • Thanks Bjorn,

    The content at 0x20000000 is always 0xA801BE00 (in 32bit format), so it must not be 'random'. The memory from 0x20000000 to 0x20000100 is as below, looks like some sort of code:

    A801BE00 F0009900 E7F9F993 304046EC 230F4685 20041C1A D3000852 1E40404A B404D1FA D5F51E5B 477046E5 9D04B5E0 1E7F2700 8816D41A 072E4075 598E0EB6 4075092D 0EB6072E 092D598E 072E4075 598E0EB6 4075092D 0EB6072E 092D598E 1C924075 D1E41E9B BDE01C28 F897F000 B5F1E7E1 2A102700 1E7FD40D C971D407 191B181B 199B195B D1F43A10 9800E00A F885F000 1E7FE7F3 680ED406 199B1D09 D1F81F12 BDF21C18 F0009800 E7F4F878 680AB5F2 688C684B 27002600 D40D1E7F 599D5991 D10442A9 1EA41D36 2000D1F6 199BBDF2 600B9900 BDF22001 F85FF000 B5F1E7EE 2A102700 1E7FD41C C971D40B D10C4283 D10D42A3 D10E42AB D10F42B3 D1F03A10

    I zipped my entire project folder and uploaded it here, and for your information my working environment is : Segger Embedded Studio 4.16 for Linux, the 'softdevice' subdirectory in 'nRF' is copied from nRF_SDK_15.0.0_a53641a. nRF_cpp_test.zip

    Thank you!

  • You had Debug > Debugger > Start From Entry Point Symbol set to Yes. It should be set to No, otherwise the Debugger will reset the device and jump directly to the application code without executing the MBR and SD first. 

    Best regards

    Bjørn 

Reply Children
Related