USB CDC receive not working

I was trying to get the USB CDC example to work so that I could use the serial console to let the Daisy know when I’m ready for it to run a test.

I simplified my code to just check for any activity on the UsbCallback. As far as I can tell, it is never called. I’ve tried on Linux using cu “cu -l /dev/ttyACM0 --baud=115200”, and Mac using CoolTerm. Both work fine to display from the Daisy USB CDC transmit. Just won’t receive.

Is this a known issue?

Here is my test code:


// USB CDC receive test
#include 
#include 
#include 
#include 
#include "daisy_pod.h"
#include "fatfs.h"

using namespace daisy;

static DaisySeed hw;

#define DBG_BUFFER_SIZE 4096
char dbgBuf[DBG_BUFFER_SIZE];
char *dbgPtr = dbgBuf;

void dbgPrintf(const char *fmt, ...) {
    if ((dbgPtr - dbgBuf) >= (int)sizeof(dbgBuf)) {
        return;
    }

    va_list valist;
    va_start(valist, fmt);
    dbgPtr += vsnprintf(dbgPtr, &dbgBuf[sizeof(dbgBuf)] - dbgPtr, fmt, valist);
    va_end(valist);
}

void dbgDump() {
    dbgBuf[sizeof(dbgBuf) - 1] = 0;
    hw.usb_handle.TransmitInternal((uint8_t *)dbgBuf, strlen(dbgBuf));
    dbgPtr = dbgBuf;
    dsy_system_delay(10);
}

volatile uint32_t usbCbCount = 0;
volatile int32_t usbCbLen = 0;
volatile char usbCbFirstChar = 0;

void UsbCallback(uint8_t *buf, uint32_t *len) {
    if (!buf || !len) {
        usbCbCount++;
        usbCbLen = -1;
        return;
    }

    if (usbCbCount == 0) {
        usbCbLen = *len;
        usbCbFirstChar = buf[0];
    }
}

int main(void) {
    // Init hardware
    hw.Configure();
    hw.Init();
    dsy_tim_start();

    // Init USB serial
    hw.usb_handle.Init(UsbHandle::FS_INTERNAL);
    hw.usb_handle.SetReceiveCallback(UsbCallback, UsbHandle::FS_INTERNAL);

    while (true) {
        dsy_system_delay(1000);

        dbgPrintf("USB callbacks received %ld, first length %ld, first char %c\n\r",
                  usbCbCount, usbCbLen, usbCbFirstChar ? usbCbFirstChar : ' ');
        dbgDump();
    }
}

Anybody that could try my code? Am I posting in the wrong place? Should I create an issue in github instead?

I tried it. After some editing (#includes) to get it to compile, I got the same result. I also tried simplifying the callback to only increment the counter, still doesn’t appear to be called.

1 Like

Thanks for trying it out! Looks like I hit an html issue when pasting the system level includes.

I think I’ve seen others saying that USB CDC receive was working, so what am I missing? Has something changed in libdaisy that breaks this recently? Or am I missing something from the code?

The example in DaisyExamples/seed/USB_CDC also doesn’t work for receive.
@shensley , ideas?

Hmm, there’s a chance something with the build has caused it to stop working.

I’ll start looking into this, and post back with what I find (or fix).

Confirmed it doesn’t work. It’s definitely build/linker related. I’ll try to get it sorted in the next few days.

Basically, malloc() isn’t working so the ClassData for USB isn’t getting allocated, causing all Transfer/reception from working. (This also affects using rand() from the standard library).

I had seen this issue come up a long time ago (but only in the Visual GDB build), and had fixed it at one point.

@hexcode you mentioned that you’re still able to do Tx – are you on an up to date version of libdaisy? Also, are you building with the project’s Makefile, or using an IDE with different build settings?

Didn’t pull libdaisy that long ago, looks like it is pointing at this:
git ls-tree -r HEAD | grep commit
160000 commit ddaa1588c793e115f9e0ca915069376caf2e120a DaisySP
160000 commit b92e4be7f7ce87769b90e2b7c4c10f1fabb347eb libdaisy

I’m building on Linux. Just copied DaisyExamples/seed/USB_CDC completely and changed the source. Using make at command line to build.

I just did a new clone of latest libdaisy, and the USB_CDC example transmits OK, doesn’t receive.
On Mac OS 10.14.6, using the project’s Makefile.

Okay, good to know. That’s helpful!

Seems like the Rx issue is separate from the malloc() issue I’m seeing (which could just be local to this Visual Studio project I’m testing).

I’ll get this sorted out ASAP!

1 Like

Alright, I think I’ve tracked down the issue. It looks like a lot of the USB initialization is done asynchronously. So if you call SetReceiveCallback immediately after init the callback will get overwritten as it takes several milliseconds before the actual USB Init is completed and the default empty callback is set.

A temporary band-aid is to add large delays between the UsbHandle::Init, and the UsbHandle::SetReceiveCallback functions. I’m going to clean up the existing code a little and add a status function to the API to make this a bit more straight forward.

This code works on my end with libdaisy unchanged:

#include "daisy_seed.h"
#include <string.h>

using namespace daisy;

static DaisySeed hw;
static uint8_t sumbuff[1024];
static uint32_t rx_size;
static bool update;

void UsbCallback(uint8_t* buf, uint32_t* len)
{
    memcpy(sumbuff, buf, *len);
    rx_size = *len;
    update  = true;
}

int main(void)
{
    hw.Configure();
    hw.Init();
    update  = false;
    rx_size = 0;
    hw.usb_handle.Init(UsbHandle::FS_INTERNAL);
	// Todo: replace delay with while(!usb_handle.IsInitialized()) {} or similar
    dsy_system_delay(500);
    hw.usb_handle.SetReceiveCallback(UsbCallback, UsbHandle::FS_INTERNAL);
	for(;;)
    {
        if (update && rx_size > 0)
        {
            hw.usb_handle.TransmitInternal(sumbuff, rx_size);
            update = false;
        }
        dsy_system_delay(2);
    }
}

Great! Good enough for now, is working on my end with that change. Thank you.

1 Like