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

esb stops after APP_USBD_EVT_POWER_REMOVED

I have the nRF52840 DK running a USB HID and an ESB PTX.

It is sending sensor data to a PRX continuously, with ACK.

The end product will be a power-sensitive device, so I figured enabling APP_USBD_CONFIG_POWER_EVENTS_PROCESS would reduce power consumption be turning the USB device off when not required.

The HID is configured like this:

APP_USBD_CONFIG_SELF_POWERED 1
APP_USBD_CONFIG_POWER_EVENTS_PROCESS 1

When the USB cable is inserted, the board enumerates correctly, and functions fine as the HID, and the ESB transmission continues.

However, when the USB cable is removed and app_usbd_stop() is called, the ESB transmission stops.

I'm guessing that a clock somewhere has stopped.

Any suggestions on the best way to keep ESB going after the USB disconnect?

Parents
  • Hello,

    I believe that your call to app_usbd_stop() stops the HFCLK. It will unless you have requested the HFCLK from somewhere else.

    Looking at the two examples from the SDK, esb_ptx and usbd_ble_uart, I see that both will start the HFLCK. The main difference is that the esb_ptx does it in a very down-to-metal way, while the usbd example uses the clock driver.

    esb_ptx uses:

    void clocks_start( void )
    {
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    }

    while the usbd example uses nrf_drv_clock_hfclk_request() (from within the usbd driver, app_usbd.c).

    When you call app_usbd_stop(), it will release the HFCLK. Since the usbd driver is the only one that requested the HFCLK, the clock driver will think that it is no longer needed, and it will turn the HFCLK off.

    The solution is simply to call nrf_drv_clock_hfclk_request() one more time, e.g. when you initialize your esb. This way, when you call app_usbd_stop(), it will release it's request to the HFCLK, but there will still be one instance that has requested the HFCLK, and the clock driver will keep the HFCLK running.

    Best regards,

    Edvin

  • nrf_drv_clock_hfclk_request() requires an event handler. I have called it with NULL. Is this OK?

    It seems to work, though.

  • It is a callback to tell you when the clock is actually started. See the implementation of nrf_drv_clock_hfclk_request():

    void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
    {
        ASSERT(m_clock_cb.module_initialized);
    
        if (m_clock_cb.hfclk_on)
        {
            if (p_handler_item)
            {
                p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
            }
            CRITICAL_REGION_ENTER();
            ++(m_clock_cb.hfclk_requests);
            CRITICAL_REGION_EXIT();
        }
        else
        {
            CRITICAL_REGION_ENTER();
            if (p_handler_item)
            {
                item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head,
                    p_handler_item);
            }
            if (m_clock_cb.hfclk_requests == 0)
            {
                hfclk_start();
            }
            ++(m_clock_cb.hfclk_requests);
            CRITICAL_REGION_EXIT();
        }
    
        ASSERT(m_clock_cb.hfclk_requests > 0);
    }

    If you request the hfclk from the usbd module first, then the clock is already started by the time out request it from the second module. The only thing that the second request does then is to increment the m_clock_cb.hfclk_requests, so that the clock is not turned off when you disconnect the USB.

Reply
  • It is a callback to tell you when the clock is actually started. See the implementation of nrf_drv_clock_hfclk_request():

    void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
    {
        ASSERT(m_clock_cb.module_initialized);
    
        if (m_clock_cb.hfclk_on)
        {
            if (p_handler_item)
            {
                p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
            }
            CRITICAL_REGION_ENTER();
            ++(m_clock_cb.hfclk_requests);
            CRITICAL_REGION_EXIT();
        }
        else
        {
            CRITICAL_REGION_ENTER();
            if (p_handler_item)
            {
                item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head,
                    p_handler_item);
            }
            if (m_clock_cb.hfclk_requests == 0)
            {
                hfclk_start();
            }
            ++(m_clock_cb.hfclk_requests);
            CRITICAL_REGION_EXIT();
        }
    
        ASSERT(m_clock_cb.hfclk_requests > 0);
    }

    If you request the hfclk from the usbd module first, then the clock is already started by the time out request it from the second module. The only thing that the second request does then is to increment the m_clock_cb.hfclk_requests, so that the clock is not turned off when you disconnect the USB.

Children
No Data
Related