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

Dynamic allocate BLE observers

Hi

I am working on a firmware which can be used in serveral custom boards. While it works perfect in old sdk, I met the following problem when migrating from Sdk 12.2 to 14.2. Would you please take a look? Thanks

Since I HAVE serveral boards which will acts in different role, I need to add BLE observers dynamically. For example, one may acts as HID service and another acts NUS service. It works fine in sdk 12 because I can determine which service need to be initialised and which event handler will be added into evt_dispatch(). However, sdk14.2 is using static allocation, for example, BLE_HIDS_DEF. I can not control observers section. 

How can I dynamically allocate these observers?

Parents
  • Hi,

     

    Most of this is done in linker sections. This is what BLE_HIDS_DEF expands to:

    #define BLE_HIDS_DEF(_name)                                                                         \
    static ble_hids_t _name;                                                                            \
    NRF_SDH_BLE_OBSERVER(_name ## _obs,                                                                 \
                         BLE_HIDS_BLE_OBSERVER_PRIO,                                                    \
                         ble_hids_on_ble_evt, &_name)

    And NRF_SDH_BLE_OBSERVER(...) expands to defining a linker section (though several steps), which shall be declared in your linker script as the .sdh_ble_observer section:

    *snip*
      .sdh_ble_observers :
      {
        PROVIDE(__start_sdh_ble_observers = .);
        KEEP(*(SORT(.sdh_ble_observers*)))
        PROVIDE(__stop_sdh_ble_observers = .);
      } > FLASH
    *snip*

    This tells the linker where the section is located both with a __start and a __stop symbol (think of it like a pointer), so that it is able to statically allocate 'n' amount of observers based on how many BLE_ANY_SERVICE_DEF(...) that you have in your application.

    The library nrf_sdh will then iterate over all the BLE_*_DEF() objects so you do not have to go into your main.c::on_ble_evt() function to add another function call.

    In order to migrate your current project to SDK 14.x, you need to conform to the BLE_*_DEF() API for your BLE observers, and updated your linker script. The linker script can be taken from almost any ble_app_* example, as they all include the sections needed. Remember that you might need to adjust the RAM start address.

    Let me know if you run into trouble.

    Cheers,

    Håkon

Reply
  • Hi,

     

    Most of this is done in linker sections. This is what BLE_HIDS_DEF expands to:

    #define BLE_HIDS_DEF(_name)                                                                         \
    static ble_hids_t _name;                                                                            \
    NRF_SDH_BLE_OBSERVER(_name ## _obs,                                                                 \
                         BLE_HIDS_BLE_OBSERVER_PRIO,                                                    \
                         ble_hids_on_ble_evt, &_name)

    And NRF_SDH_BLE_OBSERVER(...) expands to defining a linker section (though several steps), which shall be declared in your linker script as the .sdh_ble_observer section:

    *snip*
      .sdh_ble_observers :
      {
        PROVIDE(__start_sdh_ble_observers = .);
        KEEP(*(SORT(.sdh_ble_observers*)))
        PROVIDE(__stop_sdh_ble_observers = .);
      } > FLASH
    *snip*

    This tells the linker where the section is located both with a __start and a __stop symbol (think of it like a pointer), so that it is able to statically allocate 'n' amount of observers based on how many BLE_ANY_SERVICE_DEF(...) that you have in your application.

    The library nrf_sdh will then iterate over all the BLE_*_DEF() objects so you do not have to go into your main.c::on_ble_evt() function to add another function call.

    In order to migrate your current project to SDK 14.x, you need to conform to the BLE_*_DEF() API for your BLE observers, and updated your linker script. The linker script can be taken from almost any ble_app_* example, as they all include the sections needed. Remember that you might need to adjust the RAM start address.

    Let me know if you run into trouble.

    Cheers,

    Håkon

Children
  • Hi Håkon,

    Thanks a lot for your detailed reply! Following your guide, I can define these observers successfully. However, it is *STATIC*.

    For example, my firmware needs to start with HID and NUS service for DEVICE A, so I add the following lines in my code:

    BLE_HIDS_DEF(m_hids);

    BLE_NUS_DEF(m_nus);

    However, when this firmware starts for DEVICE B, it only needs NUS service ONLY. As a result, m_hids is not used, and the hid listener is added anyway. 

    How can I add NUS service and listen for NUS events only for DEVICE B? (while DEVICE A works well)

    Thanks,

    Vincent

  • Hi Vincent,

    Sorry for misunderstanding, and thanks for clarifying your use-case!

    I am functions from SDK v14, application ble_app_hids_keyboard as an example here;

    you can mimic the "older" use-case by declaring the m_hids variable as you did in SDK 12, and then call "ble_hids_on_ble_evt(p_ble_evt, NULL)" from main.c::ble_evt_handler() with an if-condition for dynamic handling. Note that you'll also need to comment out (or, wrap an if-condition around if dynamic handling of HIDS) hids_init() in main.c::services_init().

    If DEVICE B never needs the hid-service, then I would just use #ifdef to remove it from the project when compiling for this specific device.

    Best regards,

    Håkon

  • Hi Håkon,

    Thanks a lot for your reply!

    Your suggestions look great to me and I will have a try :-)

    Vincent

Related