Arm Mbed OS support forum

USB CDC receive example

Hellow. I am learning cpp and mbed recently. please help to write 6 uint numbers from usb cdc. I read the documentation https://os.mbed.com/docs/mbed-os/v5.15/apis/usbcdc.html but found in it just an example of sending. I apologize for not showing the code. I don’t even know where to start

Hello Nikita,

You can try the following:

#include "mbed.h"
#include "USBCDC.h"

USBCDC          cdc;
unsigned int    data[6] = { };              // data array
uint8_t*        p_data = (uint8_t*)data;    // write pointer
uint32_t        size_read;                  // the number of bytes actually received

int main(void)
{
    while (1) {
        cdc.receive_nb(p_data, 1, &size_read);          // write received byte to data array
        p_data += size_read;                            // advance the write pointer by the number of bytes actually received
        if (p_data == (uint8_t*)data + sizeof(data)) {  // when array is full
            printf("Data received:\r\n");
            for (uint8_t i = 0; i < 6; i++) {
                printf("data[%d] = %d\r\n", i, data[i]);
            }
            p_data = (uint8_t*)data;                    // reset the write pointer
        }
        thread_sleep_for(10);
    }
}

Hello Hudakz,

I need to receive a JSON string using USB CDC without knowing the length of the JSON string. The data has de following structure:

0x01 | two bytes for JSON string len | JSON string

In the example above you use receive_nb() but you have a fixed length for the data received. How can I receive the JSON string without previously knowing its length?

Hello Yan,

You can get started for example with the following code:

#include "mbed.h"
#include "USBCDC.h"

#define MAX_LEN 512                         // packet max length

USBCDC      cdc;
uint8_t     packet_data[MAX_LEN] = { 0 };   // allocate memory for a packet and clear content
uint8_t*    receive_pointer;                // set receive pointer
uint16_t    packet_len;
uint16_t    json_len;                       // length of the json string received
uint32_t    read_len;                       // number of bytes actually received
bool        receiving_packet;               // status variable
bool        receiving_json;                 // status variable

void reset_vars()
{
    memset(packet_data, 0, MAX_LEN);    // clear packet data
    receive_pointer = packet_data;      // reset receive pointer
    packet_len = 0;
    json_len = 0;
    receiving_packet = false;
    receiving_json = false;
}

void parse_json()
{
    char* json_string = (char*) &packet_data[3];

    printf("JSON string received:\r\n");
    printf("%s\r\n", json_string);

    // ... your json parser
}

void set_json_len()
{
    json_len = (uint16_t) packet_data[1];   // set json string length
    receiving_json = true;
}

void get_json_data()
{
    if (packet_len > (1 + 2 + json_len)) {
        printf("Error: Garbage packet received\r\n");
        reset_vars();
        return;         // get new packet
    }

    if (packet_len == (1 + 2 + json_len)) {
        printf("Packet is complete\r\n");

        parse_json();   // Parse the received json string
        reset_vars();   // Reset variables
    }
}

int main(void)
{
    reset_vars();

    while (1) {
        cdc.receive_nb(receive_pointer, 64, &read_len);  // write received bytes (if any) to packet_data and update read_len
        if (read_len > 0) {
            if (receiving_packet) {
                receive_pointer += read_len;            // advance the receive pointer by the number of bytes actually received
                packet_len += read_len;                 // number of packet bytes received so far
                if (receiving_json) {
                    get_json_data();
                }
                else if (packet_len >= (1 + 2)) {

                    // json string legth data available
                    set_json_len();
                }
            }
            else {

                // check if the first byte is equal to 0x01 -> start of a new packet
                if (packet_data[0] == 0x01) {

                    // Start of a new packet
                    receiving_packet = true;
                    receive_pointer += read_len;        // advance the receive pointer by the number of bytes actually received
                    packet_len += read_len;             // number of packet bytes received so far
                    if (packet_len >= (1 + 2)) {
                        set_json_len();
                        get_json_data();
                    }
                }
            }
        }

        thread_sleep_for(10);                           // wait for new bytes
    }
}

The code above compiles but has not been tested.

Best regards, Zoltan

1 Like

Hello Zoltan!

The code is working! I just had to change the following function to consider the two bytes of the size field:

void set_json_len()
{
    json_len = packet_data[1] << 8 | packet_data[2];   // set json string length
    receiving_json = true;
}

I really appreciate your help. Thank you very much!

Hello Yan,

I’m glad you made it work :slight_smile:
Yes, you are right. I made a mistake in the set_json_len():frowning: I should make a cast as below:

void set_json_len()
{
    //json_len = (uint16_t) packet_data[1];   // set json string length
    json_len = *((uint16_t*) &packet_data[1]);  // set json string length
    receiving_json = true;
}

But your code solved it.

Best regards, Zoltan

1 Like