AN00124_CDC_VCOM_class as UART bridge

Technical questions regarding the XTC tools and programming with XMOS.
mmar
Experienced Member
Posts: 124
Joined: Fri Jul 05, 2013 5:55 pm

AN00124_CDC_VCOM_class as UART bridge

Post by mmar »

I try use this example with uart lib as bridge for ESP loading.
Now seems code works with short communication as for example

Code: Select all

esptool.py --not-stub read_mac
but something bigger result to error write timeout. Analyzer shows , that first around 700bytes is send to ESP and then stop.

Here is code

Code: Select all

#include <platform.h>
#include <xs1.h>
#include <stdio.h>
#include <string.h>
#include "xud_device.h"
#include "xud_cdc.h"
#include "uart.h"

#include <xccompat.h>

extern void set_global(unsigned write_val);
extern unsigned get_global(void);
extern void get_global_ref(REFERENCE_PARAM(unsigned, read_val));


port p_uart_rx = on tile[0] : XS1_PORT_1B;
port p_uart_tx = on tile[0] : XS1_PORT_1L;
#define RX_BUFFER_SIZE 256


/* USB Endpoint Defines */
#define XUD_EP_COUNT_OUT   2    //Includes EP0 (1 OUT EP0 + 1 BULK OUT EP)
#define XUD_EP_COUNT_IN    3    //Includes EP0 (1 IN EP0 + 1 INTERRUPT IN EP + 1 BULK IN EP)

/* Endpoint type tables - informs XUD what the transfer types for each Endpoint in use and also
 * if the endpoint wishes to be informed of USB bus resets
 */
XUD_EpType epTypeTableOut[XUD_EP_COUNT_OUT] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_BUL};
XUD_EpType epTypeTableIn[XUD_EP_COUNT_IN] =   {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_INT, XUD_EPTYPE_BUL};

/* Application task */
void app_virtual_com(client interface usb_cdc_interface cdc,
        client uart_rx_if uart_rx , client uart_tx_buffered_if uart_tx,
        client uart_config_if i_tx_cfg, client uart_config_if i_rx_cfg
){
    static unsigned baud,lbaud=115200,cba=0,cps;
    unsigned char databuf[1024];

    while (1)
    {
        cps=cdc.available_bytes();
        while(cps && uart_tx.get_available_buffer_size()>512)
        {
//        char cdc_char = cdc.get_char();
        if(cps>uart_tx.get_available_buffer_size()) cps = uart_tx.get_available_buffer_size();    //maybe
        cdc.read(databuf,cps);
        for (int i=0; i<cps; i++) uart_tx.write(databuf[i]);            
        if (cps > 100)
            cba += cps;
        cps=cdc.available_bytes();
        }

        if(get_global()&0x2000000) {
            //usb set speed reconfig uart
            baud = get_global()&0xffffff;
            if(baud > 1000000 || baud < 10000) baud=0; //error unsupported speed
            else if(baud != lbaud) {
                lbaud=baud;
                cba++;
                i_tx_cfg.set_baud_rate(baud);
                i_rx_cfg.set_baud_rate(baud);
            }
            set_global(baud);
        }
        // Wait for a byte to uart
        select {
        case uart_rx.data_ready():
        uint8_t data = uart_rx.read();
        cdc.put_char(data);
        break;
        default : break;
        }

    }
}

int main()
{
    /* Channels to communicate with USB endpoints */
    chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN];

    /* Interface to communicate with USB CDC (Virtual Serial) */
    interface usb_cdc_interface cdc_data;
    interface uart_rx_if i_rx;
    interface uart_tx_buffered_if i_tx;
    interface uart_config_if i_tx_cfg, i_rx_cfg;
    input_gpio_if i_gpio_rx[1];
    output_gpio_if i_gpio_tx[1];
    par
    {
        on USB_TILE: XUD_Main(c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN,
                      null, epTypeTableOut, epTypeTableIn,
                      XUD_SPEED_HS, XUD_PWR_SELF);

        on USB_TILE: Endpoint0(c_ep_out[0], c_ep_in[0]);

        on USB_TILE: CdcEndpointsHandler(c_ep_in[1], c_ep_out[1], c_ep_in[2], cdc_data);

        on tile[0]: output_gpio(i_gpio_tx, 1, p_uart_tx, null);
        on tile[0]: uart_tx_buffered(i_tx, i_tx_cfg, 16384, 115200, UART_PARITY_NONE, 8, 1, i_gpio_tx[0]);
        on tile[0].core[0] : input_gpio_with_events(i_gpio_rx, 1, p_uart_rx, null);
        on tile[0].core[0] : uart_rx(i_rx, i_rx_cfg, RX_BUFFER_SIZE, 115200, UART_PARITY_NONE, 8, 1,
        i_gpio_rx[0]);
        on tile[0]: app_virtual_com(cdc_data , i_rx, i_tx ,i_tx_cfg, i_rx_cfg);
    }
    return 0;
} 
Last edited by mmar on Sat Jun 17, 2023 4:32 pm, edited 1 time in total.
User avatar
Ross
Verified
XCore Expert
Posts: 981
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

I think you will have to give is a bit more detail on the failure mechanisms. Where does the code end up? Can you supply full code listings? Any USB traces?
mmar
Experienced Member
Posts: 124
Joined: Fri Jul 05, 2013 5:55 pm

Post by mmar »

Thanks Ross , attached trace enable pytool, but not other traces now.
I update first post to full main.xc other files is AN
makefile

Code: Select all

APP_NAME = app_usb_cdc_esp

BUILD_FLAGS = -O3 -g -report

XCC_FLAGS_200 = $(BUILD_FLAGS) -DDEBUG_PRINT_ENABLE=1

TARGET = x216_C20A_VCOM

USED_MODULES = lib_gpio lib_logging lib_uart lib_xud


XMOS_MAKE_PATH ?= ../..
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 
You do not have the required permissions to view the files attached to this post.
mmar
Experienced Member
Posts: 124
Joined: Fri Jul 05, 2013 5:55 pm

Post by mmar »

Ross i read cdc code part and dont understand this in example :

Code: Select all

        case XUD_GetData_Select(c_epbulk_out, epbulk_out, length, result):

           if(result == XUD_RES_OKAY)
           {
               /* Received some data */
               rxLen[!readBufId] = length;

               /* Check if application has completed reading the read buffer */
               if(rxLen[readBufId] == 0) {
                   /* Switch buffers */
                   readBufId = !readBufId;
                   readIndex = 0;
                   /* Make the OUT endpoint ready to receive data */
                   XUD_SetReady_Out(epbulk_out, rxBuf[!readBufId]);
               } else {
                   /* Application is still reading the read buffer
                    * Say that another buffer is also waiting to be read */
                   readWaiting = 1;
               }
           } else {
               XUD_SetReady_Out(epbulk_out, rxBuf[!readBufId]);
           }
           break;
what and why is here last else ?
User avatar
Ross
Verified
XCore Expert
Posts: 981
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

I guess its intention is to mark the EP ready to accept data after a bus reset from the host (result would be XUD_RES_RST)
mmar
Experienced Member
Posts: 124
Joined: Fri Jul 05, 2013 5:55 pm

Post by mmar »

Im two weeks OOO , but still need code , that will work as CP2102 for example.
mmar
Experienced Member
Posts: 124
Joined: Fri Jul 05, 2013 5:55 pm

Post by mmar »

@Ross now i do loopback and second com loopback testing and handle code to work OK to speed 115200, but rx part lib_uart seems have here top limit.
Any speed over fail received data.
Transmit part work ok on higher speeds.
My tip is lib_gpio used on rx isnt able use higher speed, but i cant handle why?
User avatar
Ross
Verified
XCore Expert
Posts: 981
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

How did you solve the original problem?
Perhaps use of the other APIs provided?
mmar
Experienced Member
Posts: 124
Joined: Fri Jul 05, 2013 5:55 pm

Post by mmar »

I go back to most simple while based on references :

Code: Select all

while (1)
{
// Wait for a byte to uart
select {
case uart_rx.data_ready():
{
uint8_t data = uart_rx.read();
cdc.put_char(data);
}
break;
default : break;
}

if (cdc.available_bytes() != 0) {
char data_from_cdc = cdc.get_char();
uart_tx.write(data_from_cdc);
}

if(get_global()&0x2000000) {
//usb set speed reconfig uart
baud = get_global()&0xffffff;
if(baud > 1000000 || baud < 10000) baud=0; //error unsupported speed
else if(baud != lbaud) {
lbaud=baud;
cba++;
i_tx_cfg.set_baud_rate(baud);
i_rx_cfg.set_baud_rate(baud);
}
set_global(baud);
}

}