2017-12-13 02:43 AM
hello,
i am trying to send data to pc over the otg used as a virtual com port. The data is received with a terminal program (HTerm). In order to send data i am using the function CDC_Transmit_FS. For a basic test the string 'start' is sent to the pc. Therefor i use the following code. The code is implemented in the while loop of the int main function:
while(1)
{
if(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState==0)
{
while(CDC_Transmit_FS(((uint8_t*)&'start'),sizeof('start')) != USBD_OK);
}
}
This works and i can receive the data on the terminal program on my pc.
What doesn't work: If i try to send 'stop' after the 'start' string.
while(1)
{
if(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState==0)
{
while(CDC_Transmit_FS(((uint8_t*)&'start'),sizeof('start')) != USBD_OK);
}
if(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState==0)
{
while(CDC_Transmit_FS(((uint8_t*)&'stop'),sizeof('stop')) != USBD_OK);
}
}
what i hoped to receive is: start stop start stop start stop.... in an alternating order
but what i get is somehow confusing because now there is no order of the received data. I get start start stop start stop stop ... start and stop are in different orders
Thank you for your help!
#transmit #cubemx #cdc #vcp #cubehalSolved! Go to Solution.
2017-12-14 01:46 AM
If you don't wait for the TxState to turn 0, you cannot expect a sequential order of execution. How to fix it:
while
(
1
)
{
while
(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState!=0
);
(void)CDC_Transmit_FS(((uint8_t*)&
'start'
),
sizeof
(
'start'
));
while
(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState!=0
);
(void)
CDC_Transmit_FS(((uint8_t*)&'stop'
),
sizeof
(
'stop'
));
}
2017-12-13 05:23 AM
i think it has something todo with the TxState flag. But i don't know wht it is not set to 0 directly after a successful transmission?!
After a successful transmission:
Interrupt occures:
OTG_FS_IRQHandler calls HAL_PCD_IRQHandler
HAL_PCD_IRQHandler calls HAL_PCD_DataInStageCallback
HAL_PCD_DataInStageCallback calls USBD_LL_DataInStage
USBD_LL_DataInStage calls DataIn
and DataIn is USBD_CDC_DataIn and there you can find:
hcdc->TxState = 0;
which sets the TxState to 0 and so the next transmission can be started. but somehow it looks like this happens to slow.
2017-12-14 01:46 AM
If you don't wait for the TxState to turn 0, you cannot expect a sequential order of execution. How to fix it:
while
(
1
)
{
while
(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState!=0
);
(void)CDC_Transmit_FS(((uint8_t*)&
'start'
),
sizeof
(
'start'
));
while
(((USBD_CDC_HandleTypeDef*)(hUsbDeviceFS.pClassData))->TxState!=0
);
(void)
CDC_Transmit_FS(((uint8_t*)&'stop'
),
sizeof
(
'stop'
));
}
2017-12-15 01:14 AM
Hello Ben,
thank you for the information! this helped a lot.
What i didn't mentioned was that i invoked the transmit function in a Callback of an interrupt service routine. The clou is that the transmission is based on an interrupt either.
Because of the reason that i didn't distribute priorities to the interrupts the hole system fall in a loop.
in this postin a similar problem with the HAL_Delay function (the HAL_Delay function is also based on an interrupt (SysTick)) occures and there you can find a good explanation:
have a nice day
2017-12-16 05:48 AM
The timeout handling of HAL is definitely one of its most ill-conceived part. I already posted an interrupt-safe alternative HAL_Delay() method in this thread: