2022-11-06 10:00 AM
Hi
I can not find out how to correctly use a Virtual Port Com over USB.
I used STM32CubeMx to configure the USB_OTG_FS and USB_DEVICE middleware. I selected the Class "Communication Device Class (Virtual Port Com).
I found the CDC_Transmit_FS() function to send data. It works, but I have a problem:
When calling this function twice short after each other, not all data is send. Do I have to check if transmission has ended before calling again? If so, which function does that?
I'm not sure that I use the correct function because when compiling I get the warning that this function is implicitely declared. So I mis the correct include file. I can get rid of the warning when including "usbd_cdc_if.h". But normally when using STM32CubeMx one does not have to include extra files to make things work. So I'm not sure I'm doing the right thing.
I can not find a simple USB VPC example that just sends one or more strings over the USB.
(I'm using STM32H743)
2022-11-06 02:27 PM
First, the CDC_Transmit must be called from an interrupt service routine of the same priority as the USB interrupt. CDC transmit returns busy status if the previous transfer is not finished.You may also use TransmitCplt callback or check TxBusy status in USB device handle.
2022-11-07 12:10 AM
Thx for quick answer!
Unfortunately I need to call CDC_Transmit() from the main loop. Will it not be enough to wait for the TxBusy state to be cleared and then call CDC_Transmit()?
If not then it may be possible to disable the USB interrupt during the call?
I assume CDC_Transmit() is none blocking.
BTW, where can we read this information about CDC_Transmit()?
2022-11-10 06:04 PM
> If not then it may be possible to disable the USB interrupt during the call?
That should work.
Also consider not torturing yourself with ST's broken bloatware and use something decent:
https://github.com/hathach/tinyusb/tree/master/examples/device/cdc_dual_ports/src
2022-11-11 05:42 AM
> Also consider not torturing yourself with ST's broken bloatware and use something decent:
Is this suitable for the STM devices?
How to use it? There is no documentation at all.
Is the software of ST really so bad?
2022-11-11 06:03 PM
STM32 hardware is fine. Nothing is perfect, but the devices are decent. The word "bloatware" typically means "bloated software". About HAL/Cube software quality... For example, take a look on Ethernet/lwIP:
And USB is not much better. Running everything in interrupts and using malloc() is a good indicator...
There is a basic documentation:
https://github.com/hathach/tinyusb#docs
Or the same here:
2022-11-11 10:47 PM
One can do a handshake both ways over CDC. There is no need to use Tiny USB, which works but according to a colleague who has worked on it for about a year, it has various subtle bugs.
There are various previous threads here on CDC flow control, and there is this one
That thread also contains my working source code for cdc_transmit_fs.
I found exactly the same problem you have: rapid calls to it cause data loss. I spent some time quantifying the max packet rate etc, and workarounds are possible if you are happy with limiting this with conservative margins, but doing it properly is better.
You also may need to do flow control in the opposite direction, which is possible too - cdc_receive_fs.
The use of malloc() in the ST code is not related to this. In the code I had, the heap was used in init() and de_init(). This seemed ok but actually windoze puts USB to sleep periodically and then de-Init was getting called, and the use of free() there caused eventual memory shortage due to fragmentation. You want to change these functions to use a static block of RAM; it's only about 1k, IIRC.
I have rock solid CDC and MSC running now, using the ST code. (MSC via FatFS, talking to a serial FLASH over SPI at 21MHz; runs nicely). This forum is poor for getting info (too many posts for anyone to read, few people respond, and the ones that do tend to respond after many weeks) but a search on EEVBLOG will dig out some threads on this.
2022-11-12 05:09 PM
> Tiny USB ... according to a colleague ... has various subtle bugs.
But you can report bugs and, contrary to ST, people will actually care solving the problem. Also it will most likely happen in some reasonable time frame and overall the project evolves pretty rapidly.
> The use of malloc() in the ST code
Even if robustness is not a problem, it's still bad because that single call with it's dependencies pulls in code and variables, which take 2 KB of RAM and several KB of FLASH.
And here we have another fresh example of how broken this junk is:
2022-11-13 12:28 AM
Is there some example how to use TinyUSB with STM32? It is not clear to me.
Does it replace the middleware part? Do I have to write some adaption layer?
2024-12-13 12:38 PM
CDC_Transmit_FS is non-blocking and also it uses your buffer directly without copying it anywhere, so the data may get modified by your code before being transmitted. You can make a simple blocking wrapper like this:
extern USBD_HandleTypeDef hUsbDeviceFS;
void CDC_Transmit_FS_Wait(uint8_t* Buf, uint16_t Len)
{
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
while (hcdc->TxState);
CDC_Transmit_FS(Buf, Len);
while (hcdc->TxState);
}
Maybe add some timeouts to avoid freezing the sw in case of USB failure.