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

USB device suspend/resume issue when requesting HFCLK

Hello,

I'm having problems with resuming usbdevice from susspend state.
I'm working on SDK 15.2 with SD140 (6.1.0). on custom board with nRF52840 IC rev. 2.

My application runs usbd with HID generic profile and Softdevice.
SoftDevice is enabled, than usb is initialized and device is connected to PC usb port.

When host(PC) is requesting suspend to usbdevice, it enters to suspend state, but can not resume when host requests it.
I can see on debug traces that device is reporitng USB_RESUME events, but communication with hosts ends with error (host usb driver can not connect to the device).

After some investigations I've found that requesting of High Frequency Clock is somehow indirectly causing suspend/resume issue.
In my application I'm requesting HFCLK and later on usb device is initialized and opened.
If I remove HFCLK request than device is succesfully resuming from suspend state and there is no connection error on usb bus.

Below sequence of initialization code for my application:

	//... 
    clock_init();
    err_code = nrf_sdh_enable_request();
	ASSERT(err_code == NRF_SUCCESS);
	while (!nrf_sdh_is_enabled())
	{
		;
	}
	
	//... 
	
    nrf_drv_clock_hfclk_request(NULL);
	while (!nrf_drv_clock_hfclk_is_running()) 
	{
		;
	}
	
	//...
	
	ret_code_t err_code;

    err_code = app_usbd_init(&usbd_config);
    SYS_ASSERT(err_code == NRF_SUCCESS);

    app_usbd_class_inst_t const * class_inst_generic;
    class_inst_generic = app_usbd_hid_generic_class_inst_get(&m_app_hid_generic);

    err_code = app_usbd_class_append(class_inst_generic);
    SYS_ASSERT(err_code == NRF_SUCCESS);

    err_code = app_usbd_power_events_enable();
    SYS_ASSERT(err_code == NRF_SUCCESS);
	
	//...

And some of usbd configurations from sdk_config:

#define USBD_ENABLED 1
#define USBD_CONFIG_IRQ_PRIORITY 6
#define USBD_CONFIG_DMASCHEDULER_MODE 0
#define USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1
#define USBD_CONFIG_ISO_IN_ZLP 0

#define APP_USBD_ENABLED 1
#define APP_USBD_CONFIG_SELF_POWERED 0
#define APP_USBD_CONFIG_MAX_POWER 500
#define APP_USBD_CONFIG_POWER_EVENTS_PROCESS 1
#define APP_USBD_CONFIG_EVENT_QUEUE_ENABLE 0
#define APP_USBD_CONFIG_SOF_HANDLING_MODE 2

#define APP_USBD_HID_ENABLED 1
#define APP_USBD_HID_DEFAULT_IDLE_RATE 0
#define APP_USBD_HID_REPORT_IDLE_TABLE_SIZE 4
#define APP_USBD_HID_GENERIC_ENABLED 1
#define APP_USBD_HID_KBD_ENABLED 0
#define APP_USBD_HID_MOUSE_ENABLED 0

My question is - why requesting HFCLK by application(outside of app_usbd) is causing issues with resuming from suspend state (it seems that internal app_usbd fsm for suspend mode is not working properly)?
Are there any restrictions for using nrf_drv_clock_hfclk_request() when usbdevice is running?
Please advice,

Best Regards,
Krystian

  • In meantime I've modified usbd configuration for nrf_sdk example peripheral/usbd_hid_generic.
    I've disabled usbd events queue and changed SOF handling mode to interrupt - below relevant sdk_config defines:

    #define APP_USBD_CONFIG_EVENT_QUEUE_ENABLE 0
    
    #define APP_USBD_CONFIG_SOF_HANDLING_MODE 2

    I've builded and flashed such application on PCA10056 and everything works fine - I can move "mouse pointer" with PCA buttons.

    If device goes to suspend and I press any of 4 PCA buttons, hid device is resumed succesfully and I can see on host that communication works (mouse pointer is moving, etc.).

    But if I request HFCLK clock in main application and flash PCA again than after device will go suspend it can not resume successfully when PCA buttons are pressed.

    In details I can see PCA debugtraces on UART 

    (APP_USBD_EVT_DRV_RESUME/APP_USBD_EVT_DRV_SUSPEND -I've added NRF_LOG_INFO to usbd_user_ev_handler for such events),

    but communication with host in broken - no mouse pointer is moving etc. 

    So this behavior is similar to one I've described in post above (for my custom board).

    Below relevant changes in main.c:

    //...
    
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
    //...
            case APP_USBD_EVT_DRV_SUSPEND:
                NRF_LOG_INFO("APP_USBD_EVT_DRV_SUSPEND");   //ADDED DEBUG TRACE
                m_report_pending = false;
                app_usbd_suspend_req(); // Allow the library to put the peripheral into sleep mode
                bsp_board_leds_off();
                break;
            case APP_USBD_EVT_DRV_RESUME:
                NRF_LOG_INFO("APP_USBD_EVT_DRV_RESUME");    //ADDED DEBUG TRACE
                m_report_pending = false;
                bsp_board_led_on(LED_USB_START);
                break;
    //...
    
    int main(void)
    {
        ret_code_t ret;
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        ret = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(ret);
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
    
        nrf_drv_clock_lfclk_request(NULL);
        nrf_drv_clock_hfclk_request(NULL);   //ADDITIONAL HFCLK REQUEST added by me
    
        while(!(nrf_drv_clock_lfclk_is_running() && nrf_drv_clock_hfclk_is_running()))
        {
            /* Just waiting */
        }
    
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
        //...
        
        while (true)
        {
    //POLLING of usb events removed because they are processed now in Interrupt mode    
    //        while (app_usbd_event_queue_process())
    //        {
    //            /* Nothing to do */
    //        }
            hid_generic_mouse_process_state();
            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();
        }
    //...    

    If host is not sending SUSPEND requests to hid device after a few seconds than probably registers settings for Enhanced Power Management must be changed in windows register like below:

    This modified example shows that hid device is not correctly resuming from suspend state if SOF handling mode is set to interrupt.
    Please advice.

    BR,

    Krystian

  • Hi Krystian,

     

    I have tested this in SDK v16, and found that the issue is also present there.

    I can confirm that I see this issue, but at my end it takes approx. 7 to 8 seconds, then the mouse movement starts working as it should, until it is suspended again.

     

    Ordering, meaning requesting the hfclk after usbd init, does not seem to have any effect. As long as there's more than one requesting it, it seems to give a delay before properly waking up.

    Changing irq priorities doesn't give any change in this behavior.

    I haven't been able to find a solution to this problem, and I'll report this internally to the developers.

     

    Kind regards,

    Håkon

  • Hi Hakon,

    Thank you for investigating this issue and forwarding it to other developers.

    I'll wait for response from them, but because at Monday (06.04) I start 2 weeks vacation period it could happen that I'll be not responsive within this time. In such a case I'll respond to any eventual questions after I get be back to work (@ 20.04).

    Best Regards,

    Krystian

  • Hello Hakon,

    I'm back from holidays - any news regarding this issue?

    BR,

    Krystian

  • Hello Nordic Team,

    could you please update status of this issue?

    Is anyone investigating case with modified nrf_sdk example peripheral/usbd_hid_generic, which I've descibed in my post above and Hakon have reproduced at his desk(see his answer above)?

    BR,

    Krystian

Related