cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with CDC and FreeRTOS streams

bdill.1
Associate II

I'm experiencing a weird race condition / hangup with an application that I've built for my STM32F407VGTx. Basically I connect to the device via a USB cable and open a terminal to type commands on the device like a CLI. Everything works fine until I paste a large buffer into the console - at which point it locks up and seems to get frozen in some FreeRTOS related calls.

in my CDC callback i have this:

 

 

void CDCSystem::halalCDCReceiveFSCallback(uint8_t* data, uint32_t* length) { if (this->protocol == nullptr) { return; } this->protocol->handleIncoming(data, *length); }

 

The `handleIncoming` method parses the incoming data and will likely print return characters to the console. I'm using a FreeRTOS stream buffer for the outgoing data, here's the write method:

 

void CDCSystem::write(uint8_t* data, std::size_t length) { std::size_t consumed = 0; while (consumed < length) { BaseType_t pxHigherPriorityTaskWoken; bool isr = halal_IS_ISR(); auto crit = halal_ENTER_CRITICAL(); if (isr) { consumed += xStreamBufferSendFromISR(outputBuffer, data + consumed, length - consumed, &pxHigherPriorityTaskWoken); } else { consumed += xStreamBufferSend(outputBuffer, data + consumed, length - consumed, 10); } halal_EXIT_CRITICAL(crit); halal_YIELD_FROM_ISR(pxHigherPriorityTaskWoken); } ; }

 

I then have a FreeRTOS task that consumes the data written to this stream and writes it back out to the CDC device: 

 

void StartCDCSystemTask(void *argument) { auto cdcSystem = CDCSystem::getInstance(); outputBuffer = xStreamBufferCreate(HALAL_CDC_SYSTEM_OUTPUT_BUFFER_SIZE, std::max(1, HALAL_CDC_SYSTEM_OUTPUT_BUFFER_SIZE / 2)); uint8_t readBuffer[HALAL_CDC_SYSTEM_OUTPUT_BUFFER_READ_SIZE]; while (true) { std::size_t read = xStreamBufferReceive( outputBuffer, &readBuffer[0], HALAL_CDC_SYSTEM_OUTPUT_BUFFER_READ_SIZE, 10); if (read == 0) { continue; } uint8_t iterations = 0; uint8_t result; do { result = CDC_Transmit_FS(&readBuffer[0], read); iterations++; } while (result != USBD_OK && iterations < HALAL_USB_SERIAL_SYSTEM_MAX_SEND_ITERATIONS && cdcSystem->isUsbConnected()); if (iterations >= HALAL_USB_SERIAL_SYSTEM_MAX_SEND_ITERATIONS) { app_fault_raise(APP_ERROR_MAX_ITERATIONS_DURING_SEND); } } }
View more

 

It seems to get stuck in the `write` method because it's unable to write all of the data to the stream (`xStreamBufferSendXXX` returns 0) - so my loop continues infinitely trying to write that data to the stream. I would expect that the task processing said stream would drain it enough so that eventually the `write` method would be able to put data into the stream.

The other thing I noticed is that when I pause the application in MXCubeIDE the `CDCSystemTask` seems to be stuck in the `write` method... (i can see that in the stack), but it should have never gotten to that method because it never does that... I assume this has something to do with YIELD and preemption?

Screenshot 2023-09-14 at 8.21.27 PM.png

 All of my `write` methods should be called from the CDC incoming ISR.

0 REPLIES 0