NRF52840, gzll combine with USBD HID and USBD CLI, COM port no output

Good day,

I am trying to combine gzll, USBD HID and USBD CLI with SDK 17.1.0 and nrf 52840. GZLL receiving input, send to USBD HID, USBD CLI output logs and debugs.

Below is part of codes.

USBD_CLI_CDC_CAM.C

NRF_CLI_CDC_ACM_DEF(m_cli_cdc_acm_transport);
NRF_CLI_DEF(m_cli_cdc_acm,
            "usb_cli:~$ ",
            &m_cli_cdc_acm_transport.transport,
            '\r',
            CLI_EXAMPLE_LOG_QUEUE_SIZE);


NRF_CLI_RTT_DEF(m_cli_rtt_transport);
NRF_CLI_DEF(m_cli_rtt,
            "rtt_cli:~$ ",
            &m_cli_rtt_transport.transport,
            '\n',
            CLI_EXAMPLE_LOG_QUEUE_SIZE);

nrf_cli_t const * get_cli_cdc_acm_addr(void) {
    return &m_cli_cdc_acm;
}

nrf_cli_t const * get_cli_rtt_addr(void) {
    return &m_cli_rtt;
}

void dongle_usbd_cli_init(void)
{
    ret_code_t ret;

    if (USE_CYCCNT_TIMESTAMP_FOR_LOG)
    {
        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
        DWT->CYCCNT = 0;
        APP_ERROR_CHECK(NRF_LOG_INIT(cyccnt_get, 64000000));
    }
    else
    {
        APP_ERROR_CHECK(NRF_LOG_INIT(app_timer_cnt_get));
    }


    nrf_drv_clock_lfclk_request(NULL);

    ret = app_timer_create(&m_timer_0, APP_TIMER_MODE_REPEATED, timer_handle);
    APP_ERROR_CHECK(ret);

    ret = app_timer_start(m_timer_0, APP_TIMER_TICKS(1000), NULL);
    APP_ERROR_CHECK(ret);

    ret = nrf_cli_init(&m_cli_rtt, NULL, true, true, NRF_LOG_SEVERITY_INFO);
    APP_ERROR_CHECK(ret);

    ret = fds_init();
    APP_ERROR_CHECK(ret);

    UNUSED_RETURN_VALUE(nrf_log_config_load());

    APP_ERROR_CHECK(nrf_cli_task_create(&m_cli_rtt));

    flashlog_init();

    stack_guard_init();

    NRF_LOG_RAW_INFO("Command Line Interface example started.\n");
    NRF_LOG_RAW_INFO("Please press the Tab key to see all available commands.\n");
}

USBD_HID_SERVICE.C

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_RESET:
            m_report_pending = false;
            break;
        case APP_USBD_EVT_DRV_SUSPEND:  // 3
            m_report_pending = false;
            app_usbd_suspend_req();  // Allow the library to put the peripheral into sleep mode
            break;
        case APP_USBD_EVT_DRV_RESUME:  // 4
            m_report_pending = false;
            kbd_status(); /* Restore LED state - during SUSPEND all LEDS are turned off */
            break;
        case APP_USBD_EVT_STARTED:  // 2
            m_report_pending = false;
            break;
        case APP_USBD_EVT_STOPPED:
            app_usbd_disable();
            break;
        case APP_USBD_EVT_POWER_DETECTED:  // 0
            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();
            (void)nrf_cli_uninit(get_cli_cdc_acm_addr());
            break;
        case APP_USBD_EVT_POWER_READY: {    // 1
            ret_code_t ret;
            NRF_LOG_INFO("USB ready");
            app_usbd_start();
            nrf_cli_t const * m_cli_cdc_acm = get_cli_cdc_acm_addr();
            ret = nrf_cli_init(m_cli_cdc_acm, NULL, true, true, NRF_LOG_SEVERITY_INFO);
            APP_ERROR_CHECK(nrf_cli_task_create(m_cli_cdc_acm));
            APP_ERROR_CHECK(ret);

        }   break;
        default:
            break;
    }
}

void dongle_usb_keyboard_init(void) {
    ret_code_t                     ret;

    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);

    static const app_usbd_config_t usbd_config = {
                .ev_handler = app_usbd_event_execute,
                .ev_state_proc = usbd_user_ev_handler};

    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_generic_class_inst_get(&m_app_hid_kbd);
    ret            = app_usbd_class_append(class_inst_kbd);
    APP_ERROR_CHECK(ret);

    app_usbd_class_inst_t const * class_cli_cdc_acm;
    class_cli_cdc_acm = app_usbd_cdc_acm_class_inst_get(&nrf_cli_cdc_acm);
    ret = app_usbd_class_append(class_cli_cdc_acm);
    APP_ERROR_CHECK(ret);

    NRF_LOG_INFO("USBD HID composite example started.");
    ret = app_usbd_power_events_enable(); //make sure run it before all sub class all appended.
    APP_ERROR_CHECK(ret);
}

MAIN.C

static void power_management_init(void)
{
    ret_code_t err_code;
    err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);
}

static void timers_init(void) {
    ret_code_t err_code;
    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
}

static void idle_state_handle(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    for (;;) {
        if (NRF_LOG_PROCESS() == false) {
            nrf_pwr_mgmt_run();
        }
        // nrf_drv_wdt_channel_feed(m_channel_id);
        task_yield();
    }
}

int main(void) {
    power_management_init();
    timers_init();
    base_services_init();
    dongle_usb_keyboard_init();
    dongle_usbd_cli_init();
    dongle_gzll_host_start();
    NRF_LOG_INFO("Dongle started");
    task_manager_start(idle_state_handle, (void *)NULL);
}

GZLL_HOST_SERVICE.C

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);
    NRF_LOG_INFO("Received packet on pipe %d, length %d, RSSI %d", pipe, data_payload_length, rx_info.rssi);
    if (!result_value)
    {
        NRF_LOG_ERROR("RX fifo error ");
    }
    ret_code_t ret = NRF_SUCCESS;
    if (NRF_USBD->ENABLE) {
        ret = hid_kbd_process_state(m_data_payload, data_payload_length);
    }
    APP_ERROR_CHECK(ret);
}

void start_gzll_tx_statistics(void *p_context) {
    UNUSED_PARAMETER(p_context);
    while (true)
    {
        // NRF_LOG_FLUSH();
        // __WFE();
    }
}

void dongle_gzll_host_start(void)
{
    // Set up the user interface.
    ret_code_t ret;

    // Initialize Gazell.
    bool result_value = nrf_gzll_init(NRF_GZLL_MODE_HOST);
    GAZELLE_ERROR_CODE_CHECK(result_value);

    // 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.");
    static char const task_name[] = "gzll_tx_stats";
    task_create(start_gzll_tx_statistics, task_name, (void *)NULL);
}

If not start GZLL_HOST_SERVICE, USBD HID and USBD CLI both working good. But if start GZLL_HOST_SERVICE, COM port could be connected, but no any output and reactions, even RTT_CLI no output, at the same time, USBD HID and GZLL's sending and receiving are working good.

I tried uncomment " NRF_LOG_FLUSH();__WFE();" in "void start_gzll_tx_statistics(void *p_context)", COM port still no output, but RTT_CLI output"lost logger, increase queue size", or suddenly flushed.

Pls help me to analyse where is the problem? I am guessing maybe GZLL's task blocked others?

Parents
  • I am not sure why the COM port and RTT are not working when you start GZLL_HOST_SERVICE. The resources used by Gazell are shown here and UART is not one among them. I am just guessing that when you start the Gazell host service, then the application is looping somewhere. Could you confirm if this is the case by running your application in the debugger and start the host service and let it run for a while and and pause and see if the application is working as intended apart from the UART/COM port? 

  • hi,Susheel

    I figured out the problem, after looking though solution of other posts with similar problem, the reason is cli_process  runned not enough frequently, and when Gazell host service running, the logs blocked the queue, once disconnected usb, cli_rtt suddenly flushed.

    My solution as below:

    1. close NRF_CLI_USES_TASK_MANAGER_ENABLED in sdk_config.h

    2. delete all nrf_cli_task_create() - think take manager having some problem with cli process.

    3. add below to USBD_CLI_CDC_CAM.C

    void cli_process(void)
    {
        nrf_cli_process(&m_cli_cdc_acm);
    
        nrf_cli_process(&m_cli_rtt);
    }

    4. ammend  void start_gzll_tx_statistics(void *p_context) as below in GZLL_HOST_SERVICE.C

    void start_gzll_tx_statistics(void *p_context) {
        UNUSED_PARAMETER(p_context);
        while (true)
        {
            cli_process()
            if(output_mod()!=GZLL) task_exit()
            //when stop gzll host service, task exit.
        }
    }

    5. ammend idle_state_handle() in Main.C

    static void idle_state_handle(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
        for (;;) {
            //if gzll host service stop, continue run cli_process() frequently.
            if (output_mode() != GZLL) cli_process();
            
            if (NRF_LOG_PROCESS() == false) {
                nrf_pwr_mgmt_run();
            }
            task_yield();
        }
    }

    after the above ammendments, everything run all good,

Reply
  • hi,Susheel

    I figured out the problem, after looking though solution of other posts with similar problem, the reason is cli_process  runned not enough frequently, and when Gazell host service running, the logs blocked the queue, once disconnected usb, cli_rtt suddenly flushed.

    My solution as below:

    1. close NRF_CLI_USES_TASK_MANAGER_ENABLED in sdk_config.h

    2. delete all nrf_cli_task_create() - think take manager having some problem with cli process.

    3. add below to USBD_CLI_CDC_CAM.C

    void cli_process(void)
    {
        nrf_cli_process(&m_cli_cdc_acm);
    
        nrf_cli_process(&m_cli_rtt);
    }

    4. ammend  void start_gzll_tx_statistics(void *p_context) as below in GZLL_HOST_SERVICE.C

    void start_gzll_tx_statistics(void *p_context) {
        UNUSED_PARAMETER(p_context);
        while (true)
        {
            cli_process()
            if(output_mod()!=GZLL) task_exit()
            //when stop gzll host service, task exit.
        }
    }

    5. ammend idle_state_handle() in Main.C

    static void idle_state_handle(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
        for (;;) {
            //if gzll host service stop, continue run cli_process() frequently.
            if (output_mode() != GZLL) cli_process();
            
            if (NRF_LOG_PROCESS() == false) {
                nrf_pwr_mgmt_run();
            }
            task_yield();
        }
    }

    after the above ammendments, everything run all good,

Children
Related