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

linker script and HardFault

Hi all!

I want to use the BLE stack by Nordic. I figured out that S132 is the appropriate HEX image for nRF52832. I can burn the softdevice into flash with nrjftool.

An application should also run and provide BLE features later. There are multiple linker scripts in the SDK:

  1. if SDK_DIR/components/softdevice/s132/toolchain/armgcc/armgcc_s132_nrf52832_xxaa.ld is selected for linking, my application begins running after burn, as expected;
  2. if SDK_DIR/config/nrf52832/armgcc/generic_gcc_nrf52.ld is selected, my application doesn't run, it's in an endless HardFault loop;

I'd be quite satisfied with 1), but BLE functions demand the compilation of many C files from the SDK, and some of them require section variables. Linker script #1 doesn't support section variables, so linker script #2 must be used instead. But the final application doesn't run. I've tried with other linker files from the examples directory, without any success.

SDK version is nRF5_SDK_15.2.0_9412b96. I'm using a custom build system.

What could go wrong?

  • No success. I've created a hybrid linker file with the correct flash and RAM addresses/sizes, but my app still doesn't work. If the very same app is linked with the linker file without extra sections, it's okay.

    Here's the correct linker file:

    /* Linker script to configure memory regions. */
    
    SEARCH_DIR(.)
    GROUP(-lgcc -lc -lnosys)
    
    MEMORY
    {
      FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000
      RAM (rwx) :  ORIGIN = 0x20001628, LENGTH = 0xe9d8
    }
    
    SECTIONS
    {
    }
    
    SECTIONS
    {
      . = ALIGN(4);
      .mem_section_dummy_ram :
      {
      }
    
    } INSERT AFTER .data;
    
    SECTIONS
    {
      .mem_section_dummy_rom :
      {
      }
    
    } INSERT AFTER .text
    
    INCLUDE "nrf_common.ld"

    And here's the wrong. As you can see, I've just added the extra sections, but it caused some troubles.

    /* Linker script to configure memory regions. */
    
    SEARCH_DIR(.)
    GROUP(-lgcc -lc -lnosys)
    
    MEMORY
    {
      FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000
      RAM (rwx) :  ORIGIN = 0x20001628, LENGTH = 0xe9d8
    }
    
    SECTIONS
    {
    }
    
    SECTIONS
    {
      . = ALIGN(4);
      .mem_section_dummy_ram :
      {
      }
      .cli_sorted_cmd_ptrs :
      {
        PROVIDE(__start_cli_sorted_cmd_ptrs = .);
        KEEP(*(.cli_sorted_cmd_ptrs))
        PROVIDE(__stop_cli_sorted_cmd_ptrs = .);
      } > RAM
      .fs_data :
      {
        PROVIDE(__start_fs_data = .);
        KEEP(*(.fs_data))
        PROVIDE(__stop_fs_data = .);
      } > RAM
      .log_dynamic_data :
      {
        PROVIDE(__start_log_dynamic_data = .);
        KEEP(*(SORT(.log_dynamic_data*)))
        PROVIDE(__stop_log_dynamic_data = .);
      } > RAM
      .log_filter_data :
      {
        PROVIDE(__start_log_filter_data = .);
        KEEP(*(SORT(.log_filter_data*)))
        PROVIDE(__stop_log_filter_data = .);
      } > RAM
    
    } INSERT AFTER .data;
    
    SECTIONS
    {
      .mem_section_dummy_rom :
      {
      }
      .sdh_ant_observers :
      {
        PROVIDE(__start_sdh_ant_observers = .);
        KEEP(*(SORT(.sdh_ant_observers*)))
        PROVIDE(__stop_sdh_ant_observers = .);
      } > FLASH
      .sdh_ble_observers :
      {
        PROVIDE(__start_sdh_ble_observers = .);
        KEEP(*(SORT(.sdh_ble_observers*)))
        PROVIDE(__stop_sdh_ble_observers = .);
      } > FLASH
      .sdh_soc_observers :
      {
        PROVIDE(__start_sdh_soc_observers = .);
        KEEP(*(SORT(.sdh_soc_observers*)))
        PROVIDE(__stop_sdh_soc_observers = .);
      } > FLASH
      .sdh_stack_observers :
      {
        PROVIDE(__start_sdh_stack_observers = .);
        KEEP(*(SORT(.sdh_stack_observers*)))
        PROVIDE(__stop_sdh_stack_observers = .);
      } > FLASH
      .sdh_req_observers :
      {
        PROVIDE(__start_sdh_req_observers = .);
        KEEP(*(SORT(.sdh_req_observers*)))
        PROVIDE(__stop_sdh_req_observers = .);
      } > FLASH
      .sdh_state_observers :
      {
        PROVIDE(__start_sdh_state_observers = .);
        KEEP(*(SORT(.sdh_state_observers*)))
        PROVIDE(__stop_sdh_state_observers = .);
      } > FLASH
        .nrf_queue :
      {
        PROVIDE(__start_nrf_queue = .);
        KEEP(*(.nrf_queue))
        PROVIDE(__stop_nrf_queue = .);
      } > FLASH
        .nrf_balloc :
      {
        PROVIDE(__start_nrf_balloc = .);
        KEEP(*(.nrf_balloc))
        PROVIDE(__stop_nrf_balloc = .);
      } > FLASH
        .cli_command :
      {
        PROVIDE(__start_cli_command = .);
        KEEP(*(.cli_command))
        PROVIDE(__stop_cli_command = .);
      } > FLASH
      .crypto_data :
      {
        PROVIDE(__start_crypto_data = .);
        KEEP(*(SORT(.crypto_data*)))
        PROVIDE(__stop_crypto_data = .);
      } > FLASH
      .pwr_mgmt_data :
      {
        PROVIDE(__start_pwr_mgmt_data = .);
        KEEP(*(SORT(.pwr_mgmt_data*)))
        PROVIDE(__stop_pwr_mgmt_data = .);
      } > FLASH
      .log_const_data :
      {
        PROVIDE(__start_log_const_data = .);
        KEEP(*(SORT(.log_const_data*)))
        PROVIDE(__stop_log_const_data = .);
      } > FLASH
      .log_backends :
      {
        PROVIDE(__start_log_backends = .);
        KEEP(*(SORT(.log_backends*)))
        PROVIDE(__stop_log_backends = .);
      } > FLASH
    
    } INSERT AFTER .text
    
    INCLUDE "nrf_common.ld"

    I'll check whether my compile flags are correct. Perhaps another SDK version would also suit...

  • I've got it. My compile flags are bit different than the flags in the SDK, but in general this doesn't cause any issue, except for a linker flag:

    -Wl,--start-group

    After uncommenting this (and using the proper linker file above) the app began working.

  • Hi.

    The flash address is correct for S132 V6.1.0. The ram address should not have any impact on the starting of the application. If it is wrong, then you might experience a memory corruption very quickly. Are you sure that the value you have set for the RAM start address is correct? It seems quite low (i.e. the lowest possible value), and it could be that you application is starting but gets a corrupted memory very quickly. If you are using a number of features in the SoftDevice, then the RAM start address should be higher.

    For example, take a look at the linker script for the ble_app_blinky example:

    MEMORY
    {
      FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x5a000
      RAM (rwx) :  ORIGIN = 0x200022b8, LENGTH = 0xdd48
    }
    

    The blinky example uses for example RTC0, TIMER0, Radio, ECB, and LF clock, which all requires the SoftDevice.

    Therefore the RAM start address is set much higher than the lowest value.

    Best regards,

    Andreas

  • Hi.

    Glad you found it, I didn't get your reply before making a comment.

    Good luck with further development.

    Best regards,

    Andreas

  • Thanks for this, I've increased the RAM origin address by 0x1000. I hope this'll be enough for the SoftDevice.

Related