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

DFU and Serial communication over USB

I am trying to enable DFU over USB with the nRF52480, while keeping the possibility for Serial communication. I got a working example with both separate, however when I try to combine the examples I get a lot problems.

As of my understanding I have to use the nrf_dfu_trigger_usb.h library, however I can't seem to figure out how. The documentation says to call "nrf_dfu_trigger_usb_init()" after USB is initialized but before it is enabled. Do you have an example of how to do this, i.e. how to use DFU over USB while still using the USB for something else (Serial communication)?

I guess my main problem is that the DFU library initialises the variable "m_app_cdc_acm" and thus I cannot use do that myself for the Serial communication. Should I access this variable through something like: "extern const app_usbd_cdc_acm_t m_app_cdc_acm", or am I missing some basic understanding of how this works Slight smile

Also when compiling I get a lot of undefined reference to f.x. `slip_decode_add_byte' and `crc32_compute'. I have added the files containing these functions to my makefile, but I am wondering if the order of the includes makes a difference? 

Thanks Smiley

Parents
  • Finally, I got it working! The "nRF Connect DFU Trigger" now shows in the device manager, and the nRF Connect tool recognizes and triggers the DFU correctly. 

    For anyone in the future who might need to do the same I will try to document my findings as good as possible. This issue on Github gave me a lot of clues: https://github.com/NordicSemiconductor/pc-nrfconnect-programmer/issues/116

    I used the example USBD_CDC_ACM ("\examples\peripheral\usbd_cdc_acm") as a starting point, as this has most of the configuration already. I added/changed a few things to the sdk_config:

    // <s> APP_USBD_PID - Product ID.
    #ifndef APP_USBD_PID
    #define APP_USBD_PID 0xC00A
    #endif
    
    // <q> APP_USBD_CONFIG_SELF_POWERED  - Self-powered device, as opposed to bus-powered.
    #ifndef APP_USBD_CONFIG_SELF_POWERED
    #define APP_USBD_CONFIG_SELF_POWERED 0
    #endif
    
    // <q> APP_USBD_NRF_DFU_TRIGGER_ENABLED
    #ifndef APP_USBD_NRF_DFU_TRIGGER_ENABLED
    #define APP_USBD_NRF_DFU_TRIGGER_ENABLED 1
    #endif
    
    // <q> NRF_USB_DFU_TRIGGER_USB_SHARED  - Flag indicating whether USB is used for other purposes in the application.
    #ifndef NRF_DFU_TRIGGER_USB_USB_SHARED
    #define NRF_DFU_TRIGGER_USB_USB_SHARED 1
    #endif
    
    // <o> NRF_USB_DFU_TRIGGER_INTERFACE_NUM - The USB interface to use for the DFU Trigger library.  <0-255>
    #ifndef NRF_DFU_TRIGGER_USB_INTERFACE_NUM
    #define NRF_DFU_TRIGGER_USB_INTERFACE_NUM 0
    #endif

    And changed the interface numbers for the actual USB:

    // As DFU Trigger uses interface 0, CDC must use 1 and 2
    #define CDC_ACM_COMM_INTERFACE  1
    #define CDC_ACM_DATA_INTERFACE  2

    I added the function usb_init which is called just at the beginning of main:

    void usb_init()
    {
        ret_code_t ret;
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
        
        nrf_drv_clock_lfclk_request(NULL);
    
        while(!nrf_drv_clock_lfclk_is_running()){}
    
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
        app_usbd_serial_num_generate();
    
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
        // Enable DFU Trigger library over USB (should happen right after usbd_init)
        nrf_dfu_trigger_usb_init();
    
        // USBD CDC ACM example started
        app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
        if (USBD_POWER_DETECTION)
        {
            ret = app_usbd_power_events_enable();
            APP_ERROR_CHECK(ret);
        }
        else
        {
            // No USB power detection enabled. Starting USB now
            app_usbd_enable();
            app_usbd_start();
        }
    }

    And of course, imported the needed libraries:

    INC_FOLDERS += \
      $(SDK_ROOT)/components/libraries/bootloader/dfu \
      $(SDK_ROOT)/components/libraries/usbd/class/nrf_dfu_trigger \
      $(SDK_ROOT)/components/libraries/block_dev \
    
    SRC_FILES += \
      $(SDK_ROOT)/components/libraries/usbd/class/nrf_dfu_trigger/app_usbd_nrf_dfu_trigger.c \
      $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c \

    I guess it was quite easy after all, it was just hard to find the documentation needed to do so. An example added to the SDK would be a good way to go in the future :D 

Reply
  • Finally, I got it working! The "nRF Connect DFU Trigger" now shows in the device manager, and the nRF Connect tool recognizes and triggers the DFU correctly. 

    For anyone in the future who might need to do the same I will try to document my findings as good as possible. This issue on Github gave me a lot of clues: https://github.com/NordicSemiconductor/pc-nrfconnect-programmer/issues/116

    I used the example USBD_CDC_ACM ("\examples\peripheral\usbd_cdc_acm") as a starting point, as this has most of the configuration already. I added/changed a few things to the sdk_config:

    // <s> APP_USBD_PID - Product ID.
    #ifndef APP_USBD_PID
    #define APP_USBD_PID 0xC00A
    #endif
    
    // <q> APP_USBD_CONFIG_SELF_POWERED  - Self-powered device, as opposed to bus-powered.
    #ifndef APP_USBD_CONFIG_SELF_POWERED
    #define APP_USBD_CONFIG_SELF_POWERED 0
    #endif
    
    // <q> APP_USBD_NRF_DFU_TRIGGER_ENABLED
    #ifndef APP_USBD_NRF_DFU_TRIGGER_ENABLED
    #define APP_USBD_NRF_DFU_TRIGGER_ENABLED 1
    #endif
    
    // <q> NRF_USB_DFU_TRIGGER_USB_SHARED  - Flag indicating whether USB is used for other purposes in the application.
    #ifndef NRF_DFU_TRIGGER_USB_USB_SHARED
    #define NRF_DFU_TRIGGER_USB_USB_SHARED 1
    #endif
    
    // <o> NRF_USB_DFU_TRIGGER_INTERFACE_NUM - The USB interface to use for the DFU Trigger library.  <0-255>
    #ifndef NRF_DFU_TRIGGER_USB_INTERFACE_NUM
    #define NRF_DFU_TRIGGER_USB_INTERFACE_NUM 0
    #endif

    And changed the interface numbers for the actual USB:

    // As DFU Trigger uses interface 0, CDC must use 1 and 2
    #define CDC_ACM_COMM_INTERFACE  1
    #define CDC_ACM_DATA_INTERFACE  2

    I added the function usb_init which is called just at the beginning of main:

    void usb_init()
    {
        ret_code_t ret;
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
        
        nrf_drv_clock_lfclk_request(NULL);
    
        while(!nrf_drv_clock_lfclk_is_running()){}
    
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
        app_usbd_serial_num_generate();
    
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
        // Enable DFU Trigger library over USB (should happen right after usbd_init)
        nrf_dfu_trigger_usb_init();
    
        // USBD CDC ACM example started
        app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
        if (USBD_POWER_DETECTION)
        {
            ret = app_usbd_power_events_enable();
            APP_ERROR_CHECK(ret);
        }
        else
        {
            // No USB power detection enabled. Starting USB now
            app_usbd_enable();
            app_usbd_start();
        }
    }

    And of course, imported the needed libraries:

    INC_FOLDERS += \
      $(SDK_ROOT)/components/libraries/bootloader/dfu \
      $(SDK_ROOT)/components/libraries/usbd/class/nrf_dfu_trigger \
      $(SDK_ROOT)/components/libraries/block_dev \
    
    SRC_FILES += \
      $(SDK_ROOT)/components/libraries/usbd/class/nrf_dfu_trigger/app_usbd_nrf_dfu_trigger.c \
      $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c \

    I guess it was quite easy after all, it was just hard to find the documentation needed to do so. An example added to the SDK would be a good way to go in the future :D 

Children
No Data
Related