2014-04-11 01:07 AM
Hey everybody,
in order to initialize a working Virtual Com Port with CubeMX on the STM32F4 Discovery, I had to changepdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
topdev->pClassData = (void *) USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
Without the type cast pClassData would always be null, which will make the parent function (USBD_CDC_Init in usbd_cdc.c) return before initializing the interface. Btw I used firmware 1.1.0.EDIT: Sorry, that was too fast. This line was actually not the root cause, it was the following line in USB_CDC.h &sharpdefine CDC_DATA_HS_MAX_PACKET_SIZE 512Changing that value to 256 made it work for me now. In case anyone is interested, here's a small code example for a vcp mirror. Add this code to CDC_Receive in usb_cdc_if.c
static uint8_t buff_RX[256];
static uint8_t buff_TX[256]; int i = 0; for (i = 0; i < *Len; i++) buff_TX[i] = buff_RX[i]; USBD_CDC_SetTxBuffer(&hUsbDeviceFS, &buff_TX[0], *Len); USBD_CDC_TransmitPacket(&hUsbDeviceFS); USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &buff_RX[0]); USBD_CDC_ReceivePacket(&hUsbDeviceFS);Also you will have to add
extern USBD_HandleTypeDef hUsbDeviceFS;
to this file.
#usb #cdc #cdc #cdc #cdc_receive_fs #full-echo #usb-cdc #vcp #vcp2015-03-26 02:04 AM
Thank you again for your answer!
In facts, I have no problems in echoing a few characters, up to 63. When I attempt to send a large quantity, some packets are lost. Perhaps I should use USB FS instead than HS, but on this particular Discovery board this is not possible. In any case, I am not really worried about this behavior, because echoing chars was just an exercise... it was useful to learn a bit of HAL.2015-03-26 08:02 AM
Hi,
I am having the same problem that others have reported, USBD_CDC_Init() is never called, hence CDC_Init_FS() is never called as well. hUsbDevice.pClass is never malloc'ed (see screenshot) and any subsequent calls to USBD_CDC_SetTxBuffer will set off a HardFault Handler. I have applied the fixes described in this and other forums but am still getting the same problem. CDC_Receive_FS() works and I can use it to run a simple echo function, which surprises me because I can see in the debugger that pClassData is not initialized. What am I missing? In my *.ld script/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x00400;
/* required amount of heap */
_Min_Stack_Size = 0x000400;
/* required amount of stack */
In my usb_device.c generated by STM32CubeMx /* USB Device Core handle declaration */
USBD_HandleTypeDef hUsbDeviceFS;
/* init function */
void
MX_USB_DEVICE_Init(
void
)
{
/* Init Device Library,Add Supported Class and Start the library*/
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Start(&hUsbDeviceFS);
}
In my usbd_cdc.h, I have fixed the bug as described by previous posters #define CDC_DATA_HS_MAX_PACKET_SIZE 256 /* Endpoint IN & OUT Packet size */
As well as applied the fix to the bug in USBD_CDC_TransmitPacket(), which set flag after transmit had begun. 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);
return
USBD_OK;
I have a static malloc (which is never used in any case since UBSD_CDC_Init() is never called /**
* @brief static single allocation.
* @param size: size of allocated memory
* @retval None
*/
void
*USBD_static_malloc(uint32_t size)
{
static
uint32_t mem[
sizeof
(USBD_CDC_HandleTypeDef)];
return
mem;
}
My device is being recognised by both Windows and Linux as a Virtual Com Port, with all descriptors in order. I just cannot call USBD_CDC_SetTxBuffer() (as described in the User Manual) to send data from the MCU to the PC. My device is a STM32F302K8, using code generated by STM32CubeMX version 4.6.0 and my IDE is Atollic True Studio.
________________
Attachments : PClassData_NULL.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzOY&d=%2Fa%2F0X0000000bLA%2FrF1il7ghIYcbcK4fTRBA7mtJ.kohUYr0qFlnxJ9rh0o&asPdf=false
2015-03-26 08:59 AM
My device is a STM32F302K8, using code generated by STM32CubeMX version 4.6.0 and my IDE is Atollic True Studio.
Hi Zikhali, what version of STM32CubeF3you are using
?2015-03-26 09:25 AM
Hi Petr,
I am using version 1.1.1 of STM32CubeF32015-03-27 05:02 AM
Hi Zikhali,
I have no development board with STM32F3 family, butI
tried
to generate
your project.
I compared
the files
forUSB
fromSTM32CubeF3
and
STM32CubeF0
. Middleware USB files fromSTM32CubeF3
are older andsome changes
were made. F
iles
for
STM32F0
and
STM32F3
are identical
, so tryto replace
all your
files
newer
fromSTM32F0
(see. attachment).The USB
CD
Cworks
well
for me
withSTM32F0
family.I just had
problems identifying the
initialization
before the
transmitting(
u8_usb_initialized).I use
STM32CubeMX
4.7.0
and
STM32CubeF0
1.2.1
.I have
to test
available
yet
STM32F1
,STM32F2
and
STM32F4
boards
.
________________ Attachments : Middlewares.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzGi&d=%2Fa%2F0X0000000bL9%2FxAm7yEMBf5g_Z8y14wbJTQhs_c7TbkRpi06PvFTczqU&asPdf=false2015-03-30 07:39 AM
Thank you Petr!!! You were right, my code was trying to send data before the port had been opened.
I realised during the weekend that I would never be able to see the initialization of u8_cdc_initialized whilst the MCU was connected to the debugger, which is why I had initially said your solution was not working for me. The solution I found was to disconnect and reconnect the MCU and read the output from the terminal, and I can see my data being sent from the MCU after a slight pause where the port is being opened. Do you have the link to the forum you read this on? It sounds more informative than ST's own documentation which actually told me to call USBD_CDC_Init() [Page 52 Part 7.5.6 of User manual UM1734] which cost me three days of debugging! Thank you so much for your help. Let me now try and create a protocol for my application. Thank you again, and to all the posters who pointed our the bugs in the libraries, thank you.2015-03-30 02:06 PM
Do you have the link to the forum you read this on?
I am pleased that I have been able to help you
.
I
found the main
information
here
http://visualgdb.com/tutorials/arm/stm32/usb/
.I hope
that
these experiences
the CubeMX
team
added to
the next
version of
HAL
libraries
.2015-04-09 07:34 AM
Sorry to pollute the thread but I thought it best to post here. I have managed to get the µC working and sending data to my PC which acts as a host. I am now however confronted with a new problem and two days of debugging later, I have no idea how to surmount it.
Whenmy µC is sending data via USB, it NEEDS an application on the other side of the USB to consume the data apparently. When connected to my PC, and a program displaying the data is active (Realterm, Python script etc...) it will function indefinitely. If for any reason the program on PC closes, or is never opened, the µC will function for half a minute then freeze. Here is the code for my transmission, I have tried to get the µC to test if there is activity on the bus before sending data but that apparently doesn't work. Using LEDS I I think the µC freezes on one of the while conditions surrounding USBD_CDC_TransmitPacket() and USBD_CDC_SetTxBuffer() below:uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len){
uint8_t result = USBD_OK;
volatile
uint8_t bDeviceState = (
volatile
uint8_t) hUsbDevice_0->dev_state
// If no activity on the bus for past 3 seconds fail
if
(bDeviceState == USBD_STATE_SUSPENDED)
return
USBD_FAIL;
// wait for previous transfer to complete
USBD_CDC_HandleTypeDef *pCDC = (USBD_CDC_HandleTypeDef * hUsbDevice_0->pClassData;
while
(pCDC->TxState) { }
USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
result = USBD_CDC_TransmitPacket(hUsbDevice_0);
// wait until transfer is done
while
(pCDC->TxState) { }
return
result;
}
This is a simplified version of the send function, a more complex recursive function (based on the tutorial on visualgdb.com) which takes into account cases where the data to send is larger than the packet size shows the same behaviour, in either case I'm not too worried because my application for the time being is sending data byte by byte. (Stupid I know but I am still at the testing stage). Why is my µC behaving like this and any ideas for methods of debugging since I cannot use the normal debugger in True Studio (if I run the code under debug, the USB fails to initalize and my code hangs in the initialization active wait).
In unrelated weirdness, when connected to a Windows PC, the µC runs normally. When I connect it to Linux, it runs at about half normal speed (judging from the speed of my flashing LEDS). Any ideas why this weird behaviour? Sorry for the many questions but I am new to USB programming and the STm32 environment and ST software is not the best documented in the world #understatement2015-04-09 09:16 AM
Here's how I do it. I have implemented _write() so I can simply use printf(), etc. to send output to my laptop (running Linux, of course) and then I can just use ''screen /dev/ttyACM0'' to interact with my program on the MCU.
int _write(int fd, void *buf, size_t count) {
static int failed;
if(fd == 1) {
if(hUsbDeviceFS.dev_state != USBD_STATE_CONFIGURED)
return 0;
if(failed) {
if(CDC_Transmit_FS(buf, count) == USBD_OK) {
failed = 0;
return count;
}
return 0;
}
uint32_t timeout = HAL_GetTick() + 500; // 0.5 second timeout
while(HAL_GetTick() < timeout) {
if(hUsbDeviceFS.dev_state != USBD_STATE_CONFIGURED)
return 0;
int result = CDC_Transmit_FS(buf, count);
if(result == USBD_OK)
return count;
if(result != USBD_BUSY)
return -1;
// save some power!
__WFI();
}
failed = 1;
return 0;
}
return -1;
}
2015-04-09 09:19 AM
Sorry, I forgot this in the last post.
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
result = USBD_CDC_TransmitPacket(hUsbDevice_0);
/* USER CODE END 7 */
return result;
}