Skip to main content
bdill.1
Associate II
September 15, 2023
Question

Problems with CDC and FreeRTOS streams

  • September 15, 2023
  • 0 replies
  • 1059 views

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);
 }
 }

}

 

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.

This topic has been closed for replies.