Trigger library does not work

After a painful sequence here

https://devzone.nordicsemi.com/f/nordic-q-a/80283/how-to-use-the-trigger-library-to-program-the-nrf52840-dongle

I managed to merge the projects and insert all those c-files and h-files and tried to match all the correct items in the sdk_config.h file (perhaps the hardest part) into the project to support the single function added to my project nrf_dfu_trigger_usb_init().

It finally built with no undefined references and I was able to use nRF Connect to install SoftDevice and my trigger-usb loaded application onto the dongle. Though the application worked fine, nRF Connect gave the message

Nordic DFU Trigger Interface was not found. Please physically reset the device.

I have no idea how to test this and why it should fail. Since there is not much I have to do with respect to writing code (add one h-file and one init method), if you can get all the dependencies right so the project builds, what could go wrong? The only thing I can think of is the sdk_config.h file. There are all kinds of things in there mostly undocumented and I have no idea what they do.

Since my original project did not use USB in any way, I assumed the share option would be off. The example project \examples\connectivity\ble_connectivity\pca10059\ser_s140_usb_hci had it set to shared, but I do not know what it is sharing it with.

Has anyone ever gotten this to work with their BTLE-SoftDevice application?

In the connectivity sdk_config.h file the following items are enabled:

sdk_config.h(151) : #define BLE_DTM_ENABLED 1
sdk_config.h(209) : #define NRFX_CLOCK_ENABLED 1
sdk_config.h(294) : #define NRFX_POWER_ENABLED 1
sdk_config.h(334) : #define NRFX_PRS_ENABLED 1
sdk_config.h(368) : #define NRFX_PRS_BOX_4_ENABLED 1
sdk_config.h(428) : #define NRFX_SYSTICK_ENABLED 1
sdk_config.h(434) : #define NRFX_UARTE_ENABLED 1
sdk_config.h(560) : #define NRFX_UART_ENABLED 1
sdk_config.h(681) : #define NRFX_USBD_ENABLED 1
sdk_config.h(746) : #define NRF_CLOCK_ENABLED 1
sdk_config.h(789) : #define POWER_ENABLED 1
sdk_config.h(832) : #define SYSTICK_ENABLED 1
sdk_config.h(838) : #define UART_ENABLED 1
sdk_config.h(915) : #define UART0_ENABLED 1
sdk_config.h(938) : #define USBD_ENABLED 1
sdk_config.h(1001) : #define APP_SCHEDULER_ENABLED 1
sdk_config.h(1022) : #define APP_TIMER_ENABLED 1
sdk_config.h(1117) : #define APP_USBD_ENABLED 1
sdk_config.h(1388) : #define APP_USBD_NRF_DFU_TRIGGER_ENABLED 1
sdk_config.h(1395) : #define CRC16_ENABLED 1
sdk_config.h(1401) : #define NRF_BALLOC_ENABLED 1
sdk_config.h(1458) : #define NRF_MEMOBJ_ENABLED 1
sdk_config.h(1464) : #define NRF_QUEUE_ENABLED 1
sdk_config.h(1479) : #define NRF_SECTION_ITER_ENABLED 1
sdk_config.h(1486) : #define NRF_SORTLIST_ENABLED 1
sdk_config.h(1493) : #define NRF_STRERROR_ENABLED 1
sdk_config.h(1503) : #define APP_USBD_CDC_ACM_ENABLED 1
sdk_config.h(1526) : #define NRF_FPRINTF_ENABLED 1
sdk_config.h(1533) : #define NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 1
sdk_config.h(4212) : #define NRF_SDH_BLE_LOG_ENABLED 1
sdk_config.h(4263) : #define NRF_SDH_LOG_ENABLED 1
sdk_config.h(4314) : #define NRF_SDH_SOC_LOG_ENABLED 1
sdk_config.h(4467) : #define PM_LOG_ENABLED 1
sdk_config.h(4584) : #define NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED 1
sdk_config.h(4646) : #define NRF_SDH_BLE_ENABLED 1
sdk_config.h(5127) : #define NRF_SDH_ENABLED 1
sdk_config.h(5295) : #define NRF_SDH_SOC_ENABLED 1

Some I understand, most I do not. Which of these MUST be enabled in order for the trigger to work?

  • Hello,

    I have put toghether a demo example with the DFU trigger library based on the the ACM CDC USB example in SDK 17.1.0 in case it helps. This one is without the Softdevice, but I can configure it for the Softdevice later if needed.

    SES project (copy to nRF5_SDK_17.1.0_ddde560\examples\peripheral\ before building)

    usbd_cdc_acm_w_dfu_trigger.zip

  • One of the things it appears I need to do is to initialize and start usb. I just assumed the trigger library did that. in the example I have been referencing 

    project \examples\connectivity\ble_connectivity\pca10059\ser_s140_usb_hci 

    there is a softdevice wait ret_code_t ret_code = sd_app_evt_wait(); in main() and in  the fike nrf_sdh_ble.c a call to

    sd_ble_evt_get(evt_buffer, &evt_len);

    However, in my main() I handle events myself using the same call (BLE events for the most part). Can I have two sets of 

    sd_app_evt_wait();

    and

    sd_ble_evt_get()

    in the same code?

    From what I can read about it I think not. It sounds like they would conflict.

    Is there an easier way to initialize and handle USB when using the trigger? My app is pure Bluetooth; it does not use USB at all.

    This is my primary wait-loop where I poll for and dispatch events:

    static void main_loop(void)
    {
        uint8_t enabled;
        uint16_t len;
        ret_code_t result;
        for (;;)
        {
            send_data();            // when flag is set, a set of data is indicated or notified depending upon setup. 
                                    // Flag is reset in method
            main_wait();            // Contains the sd_app_evt_wait()
            if (!isEmpty(queue))
            {
                void *data = front(queue);
                if (encodeLiveData(data))
                {
                    NRF_LOG_INFO("Measurement taken from queue");
                    send_flag = true;
                    dequeue(queue);
                    bsp_board_led_off(RED_LED);
                }
            }
            if (restartAdv)
            {
                bsp_board_led_off(DISCONNECTED_LED);
                bsp_board_led_on(RED_LED);
                bsp_board_led_on(BLUE_LED);
                restartAdv = false;
                bring_up_adver();
            }
            while(true)
            {
                // uint32_t evt_id;
    
                // Don't continue on if disabled, for example when writing flash at the end
                sd_softdevice_is_enabled(&enabled);
                if (enabled != 1)
                {
                    NRF_LOG_DEBUG("Restarting application");
                    initializeBluetooth();
                 //   while(NRF_LOG_PROCESS());
                 //   NRF_POWER->RESETREAS = 0;
                 //   NVIC_SystemReset();
                 //   return;
                }
                result = sd_ble_evt_get(NULL, &len);    // Get size of event
                if (result == NRF_ERROR_NOT_FOUND)      // If there aren't any, go back to wait
                {
                    break;
                }
                evt_buf = (uint8_t *)calloc(1, len);                // Make space for event. evt_buf is 4-byte aligned
                result = sd_ble_evt_get((uint8_t *)evt_buf, &len);  // get the event
                if (result == NRF_SUCCESS)
                {
                    ble_evt_t *evt = (ble_evt_t *)evt_buf;
                    ble_evt_dispatch(evt);                          // dispatch event to handler. This handles only BTLE related events
                }
                else                                                // Hopefully no error but just in case log it.
                {                                                   // Should I do an NVIC_SystemReset() here?
                    NRF_LOG_DEBUG("PENDING BLE Event return error: %u", result);
                    free(evt_buf);  // Clean up
                    break;          // back to wait
                }
                free(evt_buf);      // clean up and get the next event
            }
        }
    }
    

  • Your assumption is correct, as long as the NRF_DFU_TRIGGER_USB_USB_SHARED option is disabled in sdk_config.h, the nrf_dfu_trigger_usb_init() will perform all the necessary initialization and starting of the USB stack. I tried that first, but the problem was that there were no standalone USB drivers available for the Trigger library, so Windows failed to recognize the device. This is why I opted to copy the configuration used by the connectivity FW and made a composite device with the CDC ACM class and the DFU trigger library. This allowed the me to re-use the existing driver we have for the connectivity dongle. If you want, I can try to integrate the same in your project.

    sd_app_evt_wait() is OK to call at multiples places, but  sd_ble_evt_get() should only be called from one place as events are cleared from the SD internal FIFO buffer as soon as they are read.

  • If you could do that it would be great. I set the interface to 0 and am trying to use BOARDS_WITH_USB_DFU_TRIGGER to get the trigger library to do all the usb work.

    I did not know there could be multiple calls to sd_app_evt_wait(). I got the impression (ages ago) that it could only be called in one location. Had I known that it could be called multiple places I would have let the SDK sdh library continue to call my event handler.

    All I wanted to do was to wait for an indication/notification to finish. After calling sd_ble_gatts_hvx() if the return was busy or tx queue full I needed to wait for the event or wait for the tx queue to empty and try again. So I jumped out of the send method and handled everything in the main_loop() where I had the wait call. Now it sounds like I could have just called the wait in the send method and retried there when it returned. Arrg. Would have made the code much simpler to follow!

    ble_app_ghs_keiser_bike.zip

    In your CDC example, is there a way to integrate my for(;;) loop with the one here. Is it possible to exit that loop once the USB has reached a certain state?

  • Here is your project with the DFU library:

     6431.ble_app_ghs_keiser_bike.zip

    Let me know if you have any questions/concerns to my changes. I took the liberty of removing the event polling from you main loop as you already had the nrf_sdh_ble.c module in your project. Doing this ensures that SDK libraries and drivers also receives SoC and BLE events from the Softdevice.

    I also updated the sdk_config.h header to fix some syntax errors (the CMSIS wizard couldn't parse it).

Related