2014-11-04 08:22 AM
- STM32CubeF4 V1.3.0
-STM32_USB_Device_Library from STM32CubeF4 V1.3.0
- VCP_V1.3.1_Setup.exe (ST's host side USB CDC driver for Windows 7)
- STM32F4Discovery (STM32F407)
- FreeRTOS 8.1.2
I'm using the CDC class driver bundled with the USB device library.
My goal is to stream binary data from USB device to host through USB CDC. The streaming works fine, but problem arises when there is no client application connected to the virtual COM port when data is beeing transmitted from the USB device.
See USBD_CDC_TransmitPacket function from usbd_cdc.c below. It has been modified according toPoint no. 22 at this page:
http://visualgdb.com/tutorials/arm/stm32/usb/
.
uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
{ USBD_CDC_HandleTypeDef *hcdc = pdev->pClassData; if(pdev->pClassData != NULL)
{ if(hcdc->TxState == 0)
{ /* Tx Transfer in progress */ hcdc->TxState = 1; /* Transmit next packet */ USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer, hcdc->TxLength); returnUSBD_OK;
} else { returnUSBD_BUSY;
} } else { returnUSBD_FAIL;
} }As you can see this function just returns ''busy'' if the previous transfer is in progress. This happens if nobody is listening on the PC side. This is probably correct and kind of an improvement to a regular COM port without flow control.
What I want is to block (for some time) until I can transmit my next packet. This is possible by polling on TxState flag, not very elegant but it works.This is the code that resets the TxFlag:
static
uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)
{ USBD_CDC_HandleTypeDef *hcdc = pdev->pClassData; if(pdev->pClassData != NULL)
{ hcdc->TxState = 0; returnUSBD_OK;
} else { returnUSBD_FAIL;
} }Two questions:
1. What does
USBD_CDC_DataIn
really mean? Is this the callback for when a (bulk) transfer has succesfully been transmitted to the host PC? 2. Is there a way to implement blocking version of a ''USB transmit''-function? I'm using FreeRTOS which indeed have mutexes, but I'm unsure where I should lock and unlock. 3. Before callingUSBD_CDC_TransmitPacket
one have to callUSBD_CDC_SetTxBuffer.
Can this ruin the ongoing transfer? There is not TxState check in this function. #usb-cdc-vcp #discovery #freertos2015-02-05 06:24 AM
Hi hornang,
Please find below answers to your questions: What does USBD_CDC_DataIn really mean? >> Yes this the callback for when a (bulk) transfer has succesfully been transmitted to the host PC2. Is there a way to implement blocking version of a ''USB transmit''-function? >> Can you test the code below. USBD_CDC_SetTxBuffer(&USBD_Device, ''Hi this the second buffer'', 25); USBD_CDC_TransmitPacket(&USBD_Device); // The first call of USBD_CDC_TransmitPacket() returns USBD_OK while(USBD_CDC_TransmitPacket(&USBD_Device) == USBD_BUSY); // while the previuos is not yet USBD_CDC_TransmitPacket() sent returns USBD_BUSYBe aware the data transfer over USB is handled by interrupt so the code above can't work if called inside interrupt handler whose the interrupt priority is higher than USB.With best regards,2015-06-05 04:14 AM
Ok, thanks I have implemented a similar solution, although instead of busy waiting I'm sleeping the task using RTOS primitive.
I have a follow-up question. When receiving with USB_CDC you have to at some point callUSBD_CDC_ReceivePacket
to get ready for the next packet to be received, right?When should it be called?- In the interrupt handler? Problems: The main thread may be transmitting usingUSBD_CDC_TransmitPacket
and the ''hpcd'' me be locked and theUSBD_CDC_ReceivePacket
call will fail since__HAL_LOCK(hpcd)
will just returnHAL_BUSY
- In the main thread? (when signaled by the interrupt) Problem: There may be an incoming reception and the same problem will happen as above, but now the lock is held by the interrupt handler rather than the main thread.The problem in both cases is that no further USB packets will be received.Please advice the correct way to handle this problem.Using STM32Cube v1.4.02015-09-02 02:52 PM
The callbacks you are looking for are:
__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) These are defined in stm32f3xx_hal_pcd.c.