Gazell Host Callback function not being call back when USB turn into suspend

I try to use Gazell and USB HID to remote wake up my computer. But after compter turns into sleep, the callback function on the Gazell Host Device doesn't being called back anymore. The callback function will start work again after I wake my computer up.

I don't know whether it is the problem of the Gazell Timer. The gazell will use Timer0 of the nrf52840.

/*****************************************************************************/
/** @name Gazell callback function definitions.  */
/*****************************************************************************/
/**
 * @brief RX data ready callback.
 *
 * @details
 */
void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
{
     uint32_t data_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
    // Pop packet and write first byte of the payload to the GPIO port.
     bool result_value = nrf_gzll_fetch_packet_from_rx_fifo(pipe,
         m_data_payload,
         &data_payload_length);

     if (!result_value)
    {
         NRF_LOG_ERROR("RX fifo error ");
     }

     if (data_payload_length > 0)
    {
         output_present(m_data_payload);
     }

    // Read buttons and load ACK payload into TX queue.
     m_ack_payload[0] = custom_LED_state_get(&m_app_hid_kbd); // Button logic is inverted.

     result_value = nrf_gzll_add_packet_to_tx_fifo(pipe, m_ack_payload, TX_PAYLOAD_LENGTH);
     if (!result_value)
    {
         NRF_LOG_ERROR("TX fifo error ");
     }

     LED_On(LED1);
}

/**
 * @brief Gazelle callback.
 * @warning Required for successful Gazell initialization.
 */
void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
{
}

/**
 * @brief Gazelle callback.
 * @warning Required for successful Gazell initialization.
 */
void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
{
}

/**
 * @brief Gazelle callback.
 * @warning Required for successful Gazell initialization.
 */
void nrf_gzll_disabled()
{
}

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())
    //{
    //     /* Just waiting */
    // }

    ret = app_usbd_init(&usbd_config);
    APP_ERROR_CHECK(ret);

    app_usbd_class_inst_t const *class_inst_kbd;

    class_inst_kbd = app_usbd_hid_kbd_class_inst_get(&m_app_hid_kbd);
    ret = app_usbd_class_append(class_inst_kbd);

    APP_ERROR_CHECK(ret);

    // NRF_LOG_INFO("USBD HID composite example started.");

    if (USBD_POWER_DETECTION)
    {
        ret = app_usbd_power_events_enable();
        APP_ERROR_CHECK(ret);
    }
    else
    {
        // NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now");

        app_usbd_enable();
        app_usbd_start();
    }

    for (uint32_t i = 0; i < 200000; i++)
    {
        app_usbd_event_queue_process();
    }
}

/*****************************************************************************/
/**
 * @brief Main function.
 * @return ANSI required int return type.
 */
/*****************************************************************************/
int main()
{
    Pin_Cfg();

    // Set up the user interface.
    ui_init();

    // Initialize Gazell.
    bool result_value = nrf_gzll_init(NRF_GZLL_MODE_HOST);
    GAZELLE_ERROR_CODE_CHECK(result_value);
    // set Time Slot Period
    nrf_gzll_set_timeslot_period(900);

    result_value = nrf_gzll_set_base_address_1(0xbc010827);
    GAZELLE_ERROR_CODE_CHECK(result_value);
    result_value = nrf_gzll_set_address_prefix_byte(PIPE_NUMBER, 0x27);
    GAZELLE_ERROR_CODE_CHECK(result_value);

    // set frequency hopping
    nrf_gzll_set_channel_table(Channel_Table, Channel_Table_Size);
    nrf_gzll_set_timeslots_per_channel(3);
    nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync(20);
    nrf_gzll_set_device_channel_selection_policy(NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_CURRENT);
    nrf_gzll_set_sync_lifetime(45);

    // Load data into TX queue.
    m_ack_payload[0] = custom_LED_state_get(&m_app_hid_kbd);

    result_value = nrf_gzll_add_packet_to_tx_fifo(PIPE_NUMBER, m_data_payload, TX_PAYLOAD_LENGTH);
    if (!result_value)
    {
        // NRF_LOG_ERROR("TX fifo error ");
        NRF_LOG_FLUSH();
    }
    usb_init();

    // Enable Gazell to start sending over the air.
    result_value = nrf_gzll_enable();
    GAZELLE_ERROR_CODE_CHECK(result_value);

    NRF_LOG_INFO("Gzll ack payload host example started.");
    //nrfx_timer_enable(&TIMER_KBD);
    while (true)
    {        
        app_usbd_event_queue_process();
        //   NRF_LOG_FLUSH();
        if(nrf_gzll_is_enabled())
        {
          LED_On(LED0);
        }
        else
        {
        LED_Off(LED0);
        }
        LED_Off(LED1);
        __WFE();
        
    }
}

Parents Reply Children
  • Hi,

    Yes, the usbd_user_ev_handler will go APP_USBD_EVT_DRV_SUSPEND event. I just copy this part fo code from the SDK keyboard example. I have tried to remove the app_usbd_suspend_req(), but the gzll device still cannot communicate with the host.

    regards,

    Letian.

    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
        case APP_USBD_EVT_DRV_SOF:
            break;
        case APP_USBD_EVT_DRV_SUSPEND:
            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:
            // LED_On(BSP_LED_3);
            //  kbd_status(); /* Restore LED state - during SUSPEND all LEDS are turned off */
            break;
        case APP_USBD_EVT_STARTED:
            // LED_On(BSP_LED_3);
            break;
        case APP_USBD_EVT_STOPPED:
            app_usbd_disable();
            break;
        case APP_USBD_EVT_POWER_DETECTED:
            NRF_LOG_INFO("USB power detected");
    
            if (!nrf_drv_usbd_is_enabled())
            {
                app_usbd_enable();
            }
            break;
        case APP_USBD_EVT_POWER_REMOVED:
            NRF_LOG_INFO("USB power removed");
            app_usbd_stop();
            break;
        case APP_USBD_EVT_POWER_READY:
            NRF_LOG_INFO("USB ready");
            app_usbd_start();
            break;
        default:
            break;
        }
    }

  • I have noticed that, the problem is because the APP_USBD_EVT_DRV_SUSPEND event will turn off the hfclk, and the gzll timer is not function. Is there anyway to keep hfclk active when APP_USBD_EVT_DRV_SUSPEND event happened?

  • Sounds like you are closing on to the problem yes, how/where did you find that hfclk is stopped?

    Kenneth

  • I have check the instructions in app_usbd_suspend_req() and the description of the APP_USBD_EVT_DRV_SUSPEND, both of them indicate that it will release(stop) the hfclk. 

    So, I add an code in the while loop in mian() function, use an LED to indicate the status of the hfclk (as my laptop is sleeping, I cannot check the Log). the LED indicate when the USB suspend, the hfclk will turn off.

    I put nrfx_clock_hfclk_start() just after the app_usbd_suspend_req(). the problem is solved, but I don't know if there are any problems may caused by the restart of the hfclk.

  • Can you try a different workaround:

    After calling app_usbd_init() in main, can you add following line:

    nrf_drv_clock_hfclk_request(NULL);

    I believe this should ensure hfclk is running.

    Kenneth

Related