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

Help for activating “Softdevice” with “USB CDC ACM”

Hello,

We are trying to upgrade two types of our existing projects with BLE connectivity. For simplifying this help-post, I’m referring only for the simplest project group. Basically our board has a sensor connected to an ADC which interrupts the CPU periodically with the converted results. The results are processed by the application SW on the board, and then sent to an application running on a PC, via USB connection. The PC application replies for each packet from the target, so it isn’t just a dump terminal.

So far:

1 - We bought two NRF52840 SDK board.

2 - Learned from two e-books: “Intro_to_Bluetooth_Low_Energy”   and

    “Bluetooth_5_and_Bluetooth_Low_Energy_-_A_Developer's_Guide”  (by Mohammad Afaneh).

 

3 – We added (“wired”) our ADC and sensor to one of the NRF52840 SDK boards.

4 – Implemented the “Server” role on the first nfr52840 board according to the e-book guide, i.e. using 

      sdk 14.2.0. Also our original “target side” application was added to this board SW.

 

5 – Implemented the “Client” role on the second nfr52840 board according to the e-book guide, i.e.       

       using SDK 14.2.0.

 

6 – Now we can see all characteristics exposed by our user defined service, updated by our application

      on the server board, in the debug window Segger Embedded Studio (SES), as well as in the “nrf     

      Connect” application, (Android and Windows).

 

7 – Expectedly, we want to forward this data to a PC application via USB, and optionally get some data in return from the PC.

However we are stuck here, unable to add the libraries and servers for using the USB hardware on the SDK board.  The problem according to DevZon’s experts is described on the following link:

https://devzone.nordicsemi.com/f/nordic-q-a/19550/can-nrf52840-usbd-work-with-softdevice/75998#75998

“Can nrf52840 usbd work with softdevice?”

over 2 years ago in reply to Sigurd

Hi, the reason for this is that the NRF_POWER interrupts that is set with the usb_start()/nrf_power_int_enable() function are cleared/removed when the SoftDevice is enabled. These interrupts are used to detect when the USB-cable is plugged in and out. The application has restricted access to the NRF_POWER peripheral after the SoftDevice is enabled, so it cannot set-up the interrupts after the SoftDevice is enabled. A new SoftDevice version is soon coming that will have the functionality to set-up these interrupts after the SoftDevice is enabled.

 

So we need an updated example for the “Central” role, running on SDK v15.0.0 (or v15.2.0).

It is really frustrating the usefulness of the old examples (SDK 14.2.0) inside “Bluetooth_5_and_Bluetooth_Low_Energy_-_A_Developer's_Guide”, for   SDK 15.0.0.

The migration process guide supplied by Nordic is too difficult, unacceptable, and it contradicts the Nordics boast to let the programmers be concentrated on developing their own application. Actually it took us just two days to wire our hardware sensors + ADC to the SDK board and migrating our SW to the board. The rest of the time, since my first post on DevZone at 26/08/2018 was spent on fighting with Nordic SW issues.  

  • Hi,

    “Can nrf52840 usbd work with softdevice?”

    The SoftDevice API added access to the USB power handling registers starting from s140_nrf52840_6.0.0-6.alpha. SDK 15.2 uses S140 v6.1.1, so I recommend upgrading to SDK 15.2.

    So we need an updated example for the “Central” role, running on SDK v15.0.0 (or v15.2.0).

     We have several central examples in the folder SDK15_2_folder\examples\ble_central\experimental

    Regarding the title of this post, "Help for activating “Softdevice” with “USB CDC ACM”, you might want to take a look at the example usbd_ble_uart, in the folder SDK15_2_folder\examples\peripheral\usbd_ble_uart, to see how the USBD and SoftDevice is used together. In that example USB CDC ACM is used together with the SoftDevice

    We have a migration guide for SDK 14.2 to SDK 15.0 here, but if you are struggling with the migration, you might find it easier to start with a SDK 15.2 example, and then add your application code to that example. In your case the usbd_ble_uart example could be a good starting point.

  • Hi Sigurd,

     Thanks for your answer.

    A week ago I’ve got a preliminary example for the  “CENTRAL” case, updated to sdk 15.0.0, thanks to Mohammad Afaneh from novelbits.io, the author of “Bluetooth_5_and_Bluetooth_Low_Energy_-_A_Developer's_Guide”.

    Since I’ve made my best to promote my project and adding to the Central SDK board the ability to forward data received from the Peripheral SDK, to a PC, via USB_CDC_ACM.

    The already implemented  user defined Peripheral/Server doesn’t support NUS and thus the usbd_ble_uart_example doesn’t fit our goals.

    Finally I’ve succeeded to compile our “Central”  SW with the usb_cdc_acm example merged to it. (Both  from sdk v15.0.0,  s140 v6.0.0).

     The   program stuck in the file "nrf_drv_usbd.c", in the function function "void nrf_drv_usbd_enable(void)"  inside the empty loop, line 1754.

     /* Waiting for peripheral to enable, this should take a few us */
    
     while (0 == (NRF_USBD_EVENTCAUSE_READY_MASK     &       nrf_usbd_eventcause_get()   ) )
        {
         /* Empty loop */
        }
    
    

     This is because    "nrf_usbd_eventcause_get()"   (from the file "nrf_usbd.h")   returns always 0x00000000;

    uint32_t nrf_usbd_eventcause_get(void)
    {
      uint32_t ret;
      ret = NRF_USBD->EVENTCAUSE;
      return  ret;
    }

    Marking out the   line   “//  ret = nrf_drv_power_usbevt_init(&config);”  causes the program being executed correctly, i.e. the “Central”  board communicates as expected with the “Peripheral”, but no USB functionality of course. (so Windows Device Manager doesn’t detect “nRF52 USB CDC Demo”!). So far I have two genius boards, but suffering of autism, lack of interaction with the environment.  

    Regarding my own mental diagnosis after this intensive BLE study, let me quote from Harry Belafonte’s song –  Monkey:

    “Well by dis time I was in despair
    I was using de shoe brush to brush me hair
    I ask him to leave but he stayed around
    He pulled de chain and I almost went down”. 

    songmeanings.com/.../   

    The merged main program flows as following, (quit similar to  usb_cdc_acm example).

    int main(void)
    {
      uint32_t dly, i;
      ret_code_t ret = 0;
    
        // Initialize various services
        log_init();
        timers_init();
        buttons_leds_init();
    
       //======  USB prj  part  =======//
    
        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())
        {
            /* Just waiting */
        }
    
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
       //==//    init_bsp();
       //==//    init_cli();
    
        app_usbd_serial_num_generate();
    
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
        NRF_LOG_INFO("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)
        {
          static const nrf_drv_power_usbevt_config_t config =
           {
            .handler = power_usb_event_handler
           };
    
            ret = nrf_drv_power_usbevt_init(&config);
            APP_ERROR_CHECK(ret);
        }
        else
        {
            NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now");
    
            app_usbd_enable();
            app_usbd_start();
        }
    
       //======  Central prj  part  =======//
    
        ble_stack_init();
        db_discovery_init();
        central_init();
        adv_scan_start();
     
    
        // Start execution.
        NRF_LOG_INFO("My App Started.");
    
    
        while (true)
        {
          while (app_usbd_event_queue_process())
            {
                /* Nothing to do */
            }
            
            if(m_send_flag)
            {
                static int  frame_counter;
                size_t size = sprintf(m_tx_buffer, "Hello USB CDC FA demo: %u\r\n", frame_counter);
                ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
            }
            
    //==//      nrf_cli_process(&m_cli_uart);
    
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
            /* Sleep CPU only if there was no interrupt since last loop processing */
            __WFE();
        }
    }
    

  • Hi,

    Finally I’ve succeeded to compile our “Central”  SW with the usb_cdc_acm example merged to it. (Both  from sdk v15.0.0,  s140 v6.0.0).

    Please note that there is an error in nrf_drv_usbd_errata.h with SDK 15.0, the correct implementation of nrf_drv_usbd_errata_type_52840_fp1() should be:

    static inline bool nrf_drv_usbd_errata_type_52840_fp1(void)
    {
    return ( nrf_drv_usbd_errata_type_52840() &&
    ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x20 ) &&  // note: modified from 0x10 to 0x20!
    ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) );
    }

     

  • Hi Sigurd,

     Thanks for your answer.

     I did not check your suggestion regarding the erroneous function “nrf_drv_usbd_errata_type_52840_fp1”, because meanwhile I’ve migrated to SDK 15.2.0, and the file “nrf_drv_usbd_errata.h” doesn’t contain any more that function.

    I’m happy with the fact that in version 15.2.0 the USB_CDC_ACM module seems to function well  with SoftDevice, However, quite embarrassed from the fact that I couldn’t done it just via the sdk_config.h file  and/or the main module + the files in the application folder.

    I’ve reached the welcomed functionality only after the following changes inside the Stack files, and quite concerned about their impact on the usb_cdc functionality and of other examples functionality that  I probably will need in the future.    

    Here are the changes, right from the main.c file, where I wrote them in real time on behalf of a successful fold-back, in case of crash or if other examples will not work:

    //=================================================================================//
    
    /////////////////////////
    // CHANGED IN IFLEs:   //
    /////////////////////////
    //
    // 1)     in the file C:\Nordic_Semi\nRF5_SDK_15.2.0\components\drivers_nrf\nrf_soc_nosd\nrf_error.h  I’ve marked out:
    //        //==//==// #ifndef SOFTDEVICE_PRESENT
    //
    // 2)     pm_mutex.c   exclude from project because no such file in sdk v15.2.0
    //
    // 3)     The file C:\Nordic_Semi\nRF5_SDK_15.2.0\modules\nrfx\drivers\src\nrfx_uarte.c
    //
    //        must be excluded from the project because it conflicts with the file:
    //
    //        C:\Nordic_Semi\nRF5_SDK_15.2.0\modules\nrfx\drivers\src\nrfx_uart.c
    //
    //        ...
    //
    //        Linking BLE_XXXXXXXXXX_Client_v006_(SDK15.2.0).elf
    //        Output/BLE_XXXXXXXXXX_Client_v006_(SDK15.2.0) Release/Obj/nrfx_uarte.o: In function
    //        UARTE0_UART0_IRQHandler':nrfx_uarte.c:(.text.UARTE0_UART0_IRQHandler+0x0): multiple definition of `UARTE0_UART0_IRQHandler'
    //        nrfx_uart.c:(.text.UARTE0_UART0_IRQHandler+0x0): first defined here
    //
    // 4)     The C:\Nordic_Semi\nRF5_SDK_15.2.0\components\drivers_nrf\usbd\nrf_drv_usbd_errata.h
    //        Doesn't contain anymore the erroneous function "static inline bool nrf_drv_usbd_errata_type_52840_fp1(void)" of SDK 15.0.0
    //        So the problem is not there!
    //        However setting "NRF_DRV_USBD_ERRATA_ENABLE" to "0" doese't have any feel-able effect on USB functionality!
    //
    //        // #ifndef NRF_DRV_USBD_ERRATA_ENABLE
    //        /**
    //         * @brief The constant that informs if errata should be enabled at all
    //         * If this constant is set to 0, all the Errata bug fixes will be automatically disabled.
    //         */
    //        #define NRF_DRV_USBD_ERRATA_ENABLE 1
    //        #endif
    //
    //  5)    The attachment /removal of the usb cord is detected by Win7 device manager but not by
    //        “Windows message” cases:   “case WM_DEVICECHANGE:”  “case DBT_DEVICEARRIVAL:” and “case DBT_DEVICEREMOVECOMPLETE:”
    //         in contrary to other usb vcoms!
    //
    //

    Actually item “5)” is not a change in file, but it causes wrong behavior of my PC program, regarding the connection establishment. Currently it can be done only if the SDK runs prior to the startup of my PC application. This is obvious given that Windows7 doesn’t create messages for  “nRF52 USB CDC Demo” removal and arrival. This behavior doesn’t particular to the merging with SoftDevice. It occurs with the untouched original usb_cdc_acm example from the peripheral folder.  

     

  • Hi,

     I did not check your suggestion regarding the erroneous function “nrf_drv_usbd_errata_type_52840_fp1”, because meanwhile I’ve migrated to SDK 15.2.0, and the file “nrf_drv_usbd_errata.h” doesn’t contain any more that function.

    Yes, in SDK 15.2 it's been removed and replaced by nrf_drv_usbd_errata_187() called in nrf_drv_usbd_enable().

    I’m happy with the fact that in version 15.2.0 the USB_CDC_ACM module seems to function well  with SoftDevice

    Great!

    This is obvious given that Windows7 doesn’t create messages for  “nRF52 USB CDC Demo” removal and arrival.

    I'm not familiar with “Windows message” cases, but it could be that your windows app need to use RegisterDeviceNotification() to register to receive notification messages from the system. See this link.

Related