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

Porting USB to mesh serial example

I am tried porting the USBD to mesh serial example according to usbd_ble_uart this days, and some functionality are test fine including Tx and Rx between Provisioner(USBD) and PC(Host).

I refer to the way of function m_char_rx_cb(NRF_UART0->RXD); to add a byte one by one.

//serial_uart.c
//Original code
void serial_uart_process(void)
{
    /* receive all pending bytes */
    while (m_can_receive && NRF_UART0->EVENTS_RXDRDY)
    {
        NRF_UART0->EVENTS_RXDRDY = 0;
        (void) NRF_UART0->EVENTS_RXDRDY;
        if (m_char_rx_cb != NULL)
        {
            m_char_rx_cb(NRF_UART0->RXD);
        }
    }

    /* transmit any pending bytes */
    if (NRF_UART0->EVENTS_TXDRDY)
    {
        NRF_UART0->EVENTS_TXDRDY = 0;
        (void) NRF_UART0->EVENTS_TXDRDY;
        if (m_char_tx_cb != NULL)
        {
            m_char_tx_cb();
        }
    }
}

//Refer and simulate the code to send data to Rx handler.
void usb_rx(serial_uart_rx_cb_t m_rx_buffer, uint8_t len)
{
    for(uint8_t i=0;i<len;i++)  m_char_rx_cb(m_rx_buffer[i]);
}



//serial_uart.h
/** Starts a transfer. */
static inline void serial_uart_tx_start(void)
{
    NRF_UART0->EVENTS_TXDRDY = 0;
    NRF_UART0->TASKS_STARTTX = 1;
}

/** Stops a transfer. */
static inline void serial_uart_tx_stop(void)
{
    NRF_UART0->TASKS_STOPTX = 1;
}

/** Sets the next byte to send. */
static inline void serial_uart_byte_send(uint8_t value)
{
    NRF_UART0->TXD = value;
}



//Refer and simulate the code to send data to Rx handler.
void usb_byte_send(uint8_t value)
{
    usb_byte = value;
}

void usb_tx_start(void)
{
    uint8_t usb_char = usb_byte;
    is_usb_tx_start = true;
    ret_code_t ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, &usb_char, 1);
}

void usb_tx_stop(void)
{
    is_usb_tx_start = false;
}

Now, I found that USBD could not receive the first byte and is able to receive up to 64 bytes. If I increasing the parameter of NRFX_USBD_EPSIZE higher than  64, the USBD will not be recognized by PC(Host). Since the process of establishing a Provisioner needs to transmit a chunk of data, the above issues needs to be solved. I will refer to the code in serial_uart.h to transmit data to PC(Host).

As the framework of mesh_uart is huge and complicated, it really hard to modify the code. Could you estimate above methods whether works fine or provide me easier way to modify code.

Hello Nordic team,

I use the above functions defined by myself to replace those three function 1.static inline void serial_uart_tx_start(void) 2.inline void serial_uart_tx_stop(void) 3.static inline void serial_uart_byte_send(uint8_t value), and it sometimes communicate fine occasionally. Is there any suggestion for me to avoid the issue occured?

Parents
  • Hello,

    I didn't quite get the issue. You get more characters when using the USB? Have you tried just forwarding this string to m_char_rx_cb()?

    Can you describe in a bit more detail what the issue is?

  • Hi Edvin,

    I've fixed the Rx issue. Device can get the entire data from event of APP_USBD_CDC_ACM_USER_EVT_RX_DONE. Currently, I want to utilize the event of APP_USBD_CDC_ACM_USER_EVT_RX_DONE  to collect whole data and then forwarding to m_char_rx_cb() to trigger specified command, I also use the event of APP_USBD_CDC_ACM_USER_EVT_TX_DONE to inform m_char_tx_cb() that it's time to transmit the next byte.

    The following code is part of code I modified.

    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, app_usbd_cdc_acm_user_event_t event)
    {
        ....
        switch (event)
        {
        .....
            case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                if(is_usb_tx_start)
                    serial_uart_process();              //Indicating that TX is done.
                break;
            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
                ....    // Data collect
                for(uint8_t i=0;i<m_rx_buffer[0]+1;i++)
                    m_char_rx_cb(m_rx_buffer[i]);       //Forwarding data to Rx event.
                break;
        }
    }
    
    //Use the function usb_send_stop to replace the function serial_uart_tx_stop
    void usb_send_stop(void)
    {
        is_usb_tx_start = false;
        tx_buffer_index = 0;
    __LOG_XB(LOG_SRC_APP, LOG_LEVEL_INFO, "usb_tx_stop ", m_tx_buffer, m_tx_buffer[0] + 1);
    }
    
    //Use the function usb_byte_send to replace the function serial_uart_byte_send
    void usb_byte_send(uint8_t value)
    {
        uint8_t usb_byte = value;
    
        is_usb_tx_start = true;
        m_tx_buffer[tx_buffer_index++] = value;
        app_usbd_cdc_acm_write(&m_app_cdc_acm, &usb_byte, 1);
    }

    I've verified the function with the command of provision and composition_data_get, and device can get the correct result, however, the communication over USB interface is unstable and often got nothing.

    How to fix this issue and to make communication stable?

    Thanks.

Reply
  • Hi Edvin,

    I've fixed the Rx issue. Device can get the entire data from event of APP_USBD_CDC_ACM_USER_EVT_RX_DONE. Currently, I want to utilize the event of APP_USBD_CDC_ACM_USER_EVT_RX_DONE  to collect whole data and then forwarding to m_char_rx_cb() to trigger specified command, I also use the event of APP_USBD_CDC_ACM_USER_EVT_TX_DONE to inform m_char_tx_cb() that it's time to transmit the next byte.

    The following code is part of code I modified.

    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, app_usbd_cdc_acm_user_event_t event)
    {
        ....
        switch (event)
        {
        .....
            case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                if(is_usb_tx_start)
                    serial_uart_process();              //Indicating that TX is done.
                break;
            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
                ....    // Data collect
                for(uint8_t i=0;i<m_rx_buffer[0]+1;i++)
                    m_char_rx_cb(m_rx_buffer[i]);       //Forwarding data to Rx event.
                break;
        }
    }
    
    //Use the function usb_send_stop to replace the function serial_uart_tx_stop
    void usb_send_stop(void)
    {
        is_usb_tx_start = false;
        tx_buffer_index = 0;
    __LOG_XB(LOG_SRC_APP, LOG_LEVEL_INFO, "usb_tx_stop ", m_tx_buffer, m_tx_buffer[0] + 1);
    }
    
    //Use the function usb_byte_send to replace the function serial_uart_byte_send
    void usb_byte_send(uint8_t value)
    {
        uint8_t usb_byte = value;
    
        is_usb_tx_start = true;
        m_tx_buffer[tx_buffer_index++] = value;
        app_usbd_cdc_acm_write(&m_app_cdc_acm, &usb_byte, 1);
    }

    I've verified the function with the command of provision and composition_data_get, and device can get the correct result, however, the communication over USB interface is unstable and often got nothing.

    How to fix this issue and to make communication stable?

    Thanks.

Children
Related