Port pc-ble-driver application for nrf52840 dongle to run on the dongle

If this has an answer, I did not look as one loses position if one checks.

IN any case, I have a working application running on the PC that uses the pc-ble-driver to access the sd_* methods on the nrf52840 dongle. I would like to port this application to run directly on the dongle. I do not want to use the BTLE nrf_SDK  but only the sd_* methods. This is necessary as I am using BTLE profiles that are in the standardization process and do not yet exist. In fact the new profile uses none of the currently existing BT SIG profiles and services (except the two required one). So there is no support for them.

In addition direct calls to the gatt and gap methods are much simpler. However, the more difficult part is all the spin up code and methods needed to 'boot' up dongle.

I am looking at a segger example project for the health thermometer which I could modify to implement this GHS (generic health system) service. It uses only one service and two characteristics and bonding is optionally supported. As stated I already have code for all of this running on the PC using sd_* calls.

Would it be possible to port this code to install directly on the dongle?

I should add that I have an nrf51288 DK which I could use as an SWD debugger.

I have looked at the tutorial. The important thing here is not using the BTLE nrfSDK APIs but direct calls into softdevice.

Parents
  • Hi,

    I do not see why you want to avoid SDK libraries even though you may need to implement some services yourself (assuming you don't need similar code  on the PC side and nRF side). But if you want to avoid it, that is possible.

    You can reuse most of your code, as the SoftDevice API is essentially the same on the pc-ble-driver as when using it directly. You would have to make adjustments though, as you are suddenly writing code for the nRF rather than a PC. I suggest starting of with a simple example project that use the SoftDevice, and copy in your code adapting as you go.

    However, the more difficult part is all the spin up code and methods needed to 'boot' up dongle.

    There is not much needed for this, and you can refer to any existing SoftDevice examples. I do not follow your reasoning for not using SDK modules on the SDK, and if you like you could use for instance the SoftDevice handler library. But if not, it is also not much work to do this yourself. Essentially the typical things you need to do is to initialize the SoftDevice, by calling sd_softdevice_enable(), passing the LF clock configuration and enable interrupts. Then enable BLE by calling sd_ble_enable(). If you for some reason want to do that without helper libraries you can still look at the implementation in <SDK>\components\softdevice\common\nrf_sdh.c and <SDK>\components\softdevice\common\nrf_sdh_ble.c to see how this is done. The rest should be more or less like you have done before using the pc-ble-driver.

  • There are several reasons for not wanting to use the SDK. First, it is huge. The project is enormous with all these directories and methods that one wont use. Simplifying that would greatly help understanding and navigation. Second, there are no services or characteristics supported by the SDK that will be used. And third, it will maximize the portability of the code to other platforms. The more 'raw C' the easier to port.

    Personally, I have always found it simpler to work with the basic GATT and GAP calls than to use any API surrounding them on all platforms I have worked on - especially on the central side. I guess it is because I know what GATT and GAP have to do, and every API has to be able to do those operations ... somehow. However, when the API takes that extra step of creating and configuring existing standards in an effort to be helpful one has to learn all the ins and outs of how that API works and is configured (the tedious part) which is completely different on every platform.

    And yes, another reason - portability between the PC code and the on chip code. Right now I have a working GHS implementation on the PC and the lines of code is very small. It needs to support only characteristic writes, descriptor writes, and indications (and bonding/encryption). The standard is designed to be synchronous - including pairing. Reads are never done so the only reason one needs to create a database is for service discovery. No need to set readable characteristic values. The GHS uses one service and two characteristics in that service. That's it.

    To start with I am looking at the thermometer example in the SDK in Segger Embedded Studio. The trickiest part as I see it is those first calls

        // Initialize.
        log_init();
        timers_init(); // This looks like it is only for the Battery service
        buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        advertising_init();
        services_init();
        sensor_simulator_init();
        conn_params_init();
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("Health Thermometer example started.");
        application_timers_start();
        advertising_start(erase_bonds);

    relative to the spin up calls I have on the PC. Clearly I will need the buttons to start the app; on the PC I can have a UI. So I am contrasting my PC-based spin up with that above. What I don't seem to have in my PC spin up is equivalents for 'gap_params_init() and gatt_init(). Probably because on the PC side there are defaults being used by the pc-ble-driver.

    So if I work out those kinks then the next step is to connect my usb cable to my nrf51288 DK SWD debugger PIN 20 (easier to use) and connect the correct SWD pins to the dongle. (Softdevice already installed.)

    I assume that the dongle will get its power from the USB connection - but here is where I am most uncertain.

Reply
  • There are several reasons for not wanting to use the SDK. First, it is huge. The project is enormous with all these directories and methods that one wont use. Simplifying that would greatly help understanding and navigation. Second, there are no services or characteristics supported by the SDK that will be used. And third, it will maximize the portability of the code to other platforms. The more 'raw C' the easier to port.

    Personally, I have always found it simpler to work with the basic GATT and GAP calls than to use any API surrounding them on all platforms I have worked on - especially on the central side. I guess it is because I know what GATT and GAP have to do, and every API has to be able to do those operations ... somehow. However, when the API takes that extra step of creating and configuring existing standards in an effort to be helpful one has to learn all the ins and outs of how that API works and is configured (the tedious part) which is completely different on every platform.

    And yes, another reason - portability between the PC code and the on chip code. Right now I have a working GHS implementation on the PC and the lines of code is very small. It needs to support only characteristic writes, descriptor writes, and indications (and bonding/encryption). The standard is designed to be synchronous - including pairing. Reads are never done so the only reason one needs to create a database is for service discovery. No need to set readable characteristic values. The GHS uses one service and two characteristics in that service. That's it.

    To start with I am looking at the thermometer example in the SDK in Segger Embedded Studio. The trickiest part as I see it is those first calls

        // Initialize.
        log_init();
        timers_init(); // This looks like it is only for the Battery service
        buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        advertising_init();
        services_init();
        sensor_simulator_init();
        conn_params_init();
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("Health Thermometer example started.");
        application_timers_start();
        advertising_start(erase_bonds);

    relative to the spin up calls I have on the PC. Clearly I will need the buttons to start the app; on the PC I can have a UI. So I am contrasting my PC-based spin up with that above. What I don't seem to have in my PC spin up is equivalents for 'gap_params_init() and gatt_init(). Probably because on the PC side there are defaults being used by the pc-ble-driver.

    So if I work out those kinks then the next step is to connect my usb cable to my nrf51288 DK SWD debugger PIN 20 (easier to use) and connect the correct SWD pins to the dongle. (Softdevice already installed.)

    I assume that the dongle will get its power from the USB connection - but here is where I am most uncertain.

Children
  • Hi,

    brianreinhold said:
    To start with I am looking at the thermometer example in the SDK in Segger Embedded Studio. The trickiest part as I see it is those first calls

    The SoftDevice itself has very few requirements, and can be initialized as suggested earlier. Any additional features you need has to be configured separately. If you need buttons as you write, you can do that by the BSP library (highest level), button handling library, GPIOTE driver, or by direct register access. This is all up to you, really. I suggest you just copy from a SDK example for this. If you do not need any features, then just remove them.

    for instance, looking at the code snippet from the thermometer (BLE HTS) example in your last post:

    • If you want logging, ieep the log_init function from the example and the call to it in the start of main. You can refer to the Log module documentation within the SDK documentation for more documentation on the log module.
    • If you need app timers, then keep the timers_init() function and add initialization of your timers there. If not, remove it.
    • If you wan to use the BSP module for buttons and LEDs, keep the buttons_leds_init() function and adapt to you rneeds. If you want to handle buttons differently, that is up to you.
    • For power management you typically do not need a separate library for that. If you want to use the module that is fine, if not just make sure to call sd_app_evt_wait() in your main loop.
    • etc.

    None of this is related to the SoftDevice though, and as you want to keep your existing code there as much as possible, the SoftDevice and BLE related code is not relevant for you.

    The dongle is powered by the USB connection yes, and you do not need to think about that from a FW perspective other than that you should make sure to configure the regulator properly. If you specify that the board is a dongle and you use the BSP library, then that is handled automatically. If not, you must take extra care, as described in the last part of the nRF52840 Dongle Programming tutorial.

  • One feature is missing in the above - registration of the event handler. How it is done is hidden in a complex macro:

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

    Complex in the sense it is not clear how it is operating  It's not clear to me whether I am forced to use this macro as hidden methods are used to do the task or not (the text in the h-file suggests one MUST use this). Perhaps it would help if I could find the documentation which explains what an 'Observer' means in the context of this API. That would help me understand what the consequences of the parameters values are. So far I have not found such documentation. The 'context' parameter is also 'NULL' in the example but I have not yet been able to find what the 'context' means in the context of this API (no pun intended). 'Context' is such a generic term in APIs it can mean almost anything.

    Searching for the word 'Observer' or 'context' in the documentation returns 'no results'. However, I know the search is very unreliable so that does not mean such documentation does not exist. I will just need help to try and find it.

    Thanks.

  • Hi,

    The NRF_SDH_BLE_OBSERVER() is relevant if you use the SoftDevice handler (which is usually a good idea). In that case, this macro will add the function pointer you provide to an array (in form of a section variable populated by the linker, a bit black magic). That array is iterated by the SoftDevice handler whenever there is a BLE event from the SoftDevice, and the handler is called.

    To see more details you can see in SDK 17.0.2 that sdh_ble_observers is defined on line 64 in components\softdevice\common\nrf_sdh_ble.c and it is iterated over from nrf_sdh_ble_evts_poll() in the same file.

    If you do not use the SDH, then you get SoftDevice event by calling sd_ble_evt_get() when there is a SoftDevice interrupt, just as the SDH implementation does.

  • I think I will stick with the MACRO here. I am just trying to minimize the size of the project as well as minimize the number of platform-dependent calls.

  • Einar,

    If I use Segger Embedded Studio and connect the PC USB cable to the nrf51288 DK and connect the SWD port 20 directly to the dongle's SWDIO and SWDCLK  pins (the two plated half-holes close to the "head" of the dongle) will the voltages be okay?

    (Looking for the safest and easiest way to do the wiring tasks as I have VERY limited equipment to properly do this kind of work.)

    Thanks.

Related