How to determine the App RAM base address in the linker script?

I understand part of ram is used by the softdevice, but I see different addresses are used in different examples that use the same softdevice, namely S132. For example,

in ble_app_hrs/pca10040/s132/armgcc/ble_app_hrs_gcc_nrf52.ld, RAM (rwx) : ORIGIN = 0x20002c38, LENGTH = 0xd3c8

In ble_app_uart/pca10040/s132/armgcc/ble_app_uart_gcc_nrf52.ld, RAM (rwx) : ORIGIN = 0x20002128, LENGTH = 0xded8

How is the exactly value being determined?

  • This is documented in the sd_ble_enable() call, although you'll find in all the recent SDKs this has been abstracted away inside the standard softdevice_handler which also now contains a macro to work out what the memory usage ought to be.

    You basically give the sd_ble_enable() call a pointer to uint32_t which contains the address of the start of user memory, it either returns an error telling you you've not given it enough RAM or it returns ok and puts the minimum value of the app RAM base back in the pointer.

    So the best way is to use softdevice_handler, or just give it lots of RAM, break after the sd_ble_enable() call and note down the value, then set the linker script to that.

  • As RK suggested there is (according to Nordic) no clear formula about Soft Device RAM allocation depending on the configuration during enable/init so you need to run it once on actual chip and get the correct value from the Soft Device. If you cannot or don't want to use debugger you can use UART (or debug Trace) and print it out (here are some hints and code samples if needed).

  • RK

    app_ram_base will only be what I set it to in the IAR IDE wright?

    If I set it to 0x20001FF0 then that is what app_ram_base displays. If I set it to 0x20002FF0 then that is what app_ram_base displays.

    So in IAR one only adjusts the RAM start and end address, not the size

    So where does SD get the RAM info, if all I do is tell the linker in advance where RAM starts?

    Any help appreciated

  • @renix: No, the SoftDevice will calculate its RAM requirements based on the configuration( e.g. number of central/peripheral links, number of services/characteristics/descriptors etc) when you enable it, i.e. call sd_ble_enable(). So in IAR the start address will be 0x20000000 and then app_ram_base should return the the end address of the SoftDevice RAM region. What happens if you set the end address to 0x20001000? 0x1000 should be to little and app_ram_base should contain a larger value. A quick way to tell if you have allocated enough RAM to the SoftDevice is to check if your device is advertising, if not, then increase the end_address until it starts advertising.

  • Bjørn

    When I set IAR RAM Start to 0x20001000, execution runs to ble_stack_init(void) and goes into the weeds at sd_ble_enable(0);

    I break before sd_ble_enable(0); then ram_start = 0x20001000

    No debug output on UART or RTT Viewer.

    When I set IAR RAM Start to 0x20001FE0, execution runs to app_error.c and sits at while (loop); Note: loop is '1'

    I break at if (app_ram_base != *ram_start) inside softdevice_enable(uint32_t * ram_start) Then ram_start = 0x20002950 app_ram_base = 0x20001FF0

    (So uint32_t app_ram_base = *ram_start; is why it looks like app_ram_base is always what I set it to in IAR)

    Debug output on UART SDH:WARNING:RAM start should be adjusted to 0x20001ff0. SDH:WARNING:RAM size should be adjusted to 0xe010. :ERROR:Fatal

    When I set IAR RAM Start to 0x20001FF0, (as the UART printout suggests), BLE runs fine.

    Thanks for the explanation.