2 years, 3 months ago.

How does MBED set aside RAM for the NORDIC softdevice?

Hi, I am trying to connect multiple Peripherals to one Central using the MBED BLE librarys. However, when i try to change the maximum allowed clients, my app wont run anymore (hangs in BLE::Instance();).

I have tried following in sdk_config.h:

NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1 ; NRF_SDH_BLE_CENTRAL_LINK_COUNT 3 ; NRF_SDH_BLE_TOTAL_LINK_COUNT 4 ; this and anything below works! NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1 ; NRF_SDH_BLE_CENTRAL_LINK_COUNT 4 ; NRF_SDH_BLE_TOTAL_LINK_COUNT 5 ; this and anything above does not work! NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1 ; NRF_SDH_BLE_CENTRAL_LINK_COUNT 1 ; NRF_SDH_BLE_TOTAL_LINK_COUNT 5 ; this does also not work!

I assume this has something to do with RAM reservation for the softdevice, because it needs a reserved area in RAM. I looked at the linker script (NRF52832.ld) and noticed following:

Linker script snippet

/* If app_start is 0, do not set aside space for the softdevice */
#if MBED_APP_START == 0
  #define MBED_RAM_START  0x20000000
  #define MBED_RAM_SIZE   0x10000
#else
  #define MBED_RAM_START  0x200031D0
  #define MBED_RAM_SIZE   0xCE30
#endif

if I am correct, that means that if the softdevice is Enabled MBED sets aside a predefined amount of RAM, but that may not be enough. Debugging shows that sd_ble_enable(uint32_t * p_app_ram_base) sets 0x20007410 as app_ram_base. So one can see that the value in the linker script isnt even close to what is needed by the Softdevice. I tried changing the MBED_RAM_START address manually, but that leads to strange behaviour on my device, I think i am missing something.

So what am I missing here?

EDIT: I just experimented with the linker settings, and i got it to work! I put a breakpoint to nrf_sdh_ble_enable in nrf_sdh_ble.c and read the *p_app_ram_start, app_ram_start_link then I used the value of *p_app_ram_start as MBED_RAM_START and ram_end_address_get() - (*p_app_ram_start) as MBED_RAM_SIZE in the linker script. and voila it works! (although i had to perform a full clean for the changes to take effect)

then I checked if the values of *p_app_ram_start and app_ram_start_link would match now, but they dont. then I did some calculating and found out, that its not the MBED_RAM0 address thats important, but MBED_RAM1, so I have to subtract MBED_RAM0_SIZE from *p_app_ram_start and get the real intendet ram start address. again, I tried to verify it, and now the ram start address and the ram_start_link address differ by only 0x4. I guess thats because the ram start address is set to the next Memory page instead of the almost full one. anyways, I can accept wasting 4 bytes of memory and it now works! BUT i Highly suggest to change the linker script so that it calculates these values automatically, because its a real hassle to go through this. maybe I wrote this text a bit confusing, so if you have questions please ask, as i really would like to know if all of my assumptions were true.

thanks in advance, Jonas

this is a follow-up question regarding an issue discussed here: https://os.mbed.com/questions/83165/why-cant-i-connect-multiple-peripherals-/

1 Answer

2 years, 3 months ago.

Hi Jonas,

It's really impressive on the analysis! The way you adjust the MBED_RAM_START and MBED_RAM_SIZE is correct, the value is decided through sd_ble_enable(), please refer to this documentation, targets\TARGET_NORDIC\TARGET_NRF5x\TARGET_SDK_14_2\TARGET_SOFTDEVICE_S140_FULL\doc\s140_nrf52840_5.0.0-2.alpha_migration-document.pdf, section "SoftDevice RAM usage"

The required memory is got from execution time, but the linker script is used in compilation time, so it's hard to change these values automatically. But we could try to show some notification when this error happens, so that everyone will know how to deal with it.

If you have any other idea please let me know!

- Desmond, team Mbed

Accepted Answer

Hi, thanks for your quick reply. shouldnt it be possible to get an estimation of the softdevice ram usage by multiplying the usage of 1 connection with the NRF_SDH_BLE_TOTAL_LINK_COUNT ? for example, you could estimate it and if its still not enough MBED should throw an error. however, then my most important suggestion is to pass through all the errors from the nordic SDK, because in this case its impossible to find out that ram is missing when the applications hangs in BLE::Instance() and no error is returned. Also I would suggest to document this "issue" a little bit better, as I didnt find a single example utilizing more than 1 connection with MBED and no document that showed me how to change the ram start in MBED. anyways, I love your support and hope this question will help others, that struggle with the same issue :)

posted by Jonas Woerner 19 Nov 2018