cancel
Showing results for 
Search instead for 
Did you mean: 

STm32F USB VCP example

B Zikhali
Associate III
Posted on March 10, 2015 at 16:12

I am building a microcontroller based on the STM32F302K8 chip and I am trying to send data to host PC via USB. My echo code below based on an example in the forums works:

static
int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 7 */
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);
return
(USBD_OK);
/* USER CODE END 7 */
}

But when I implement the following code to send from MCU to host, I fall into an Infinite Loop (Default_Handler in startup_stm32f302x8.s)

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 8 */
int
i;
//memcpy(UserTxBufferFS, Buf, Len); //not sure why but memcpy is not working here
for
(i=0;i<Len;i++)
{
UserTxBufferFS[i]=Buf[i];
}
USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);
result = USBD_CDC_TransmitPacket(hUsbDevice_0);
/* USER CODE END 8 */
return
result;
}

I have looked all over the internet for a solution including the forums on this site, why is this happening? With regards to the recieve code, how is the loop reading from RX_Buff when it is set as the Receiving buffer only after the loop? Does anyone have the USB as VCP examples mentioned in the Software Development Kit PDF? I have been to every nook and cranny of this website and all the links seem to be dead! #stm32f3xx #stm32 #usb #usb #stm32f #stm32f3 #vcp #lmgtfy:-stm32-resources
11 REPLIES 11
Mauri
Associate II
Posted on October 28, 2015 at 12:11

Hi Zikhali,

may help.

Find out what happens when a char is received that triggers the TX and trigger it from your target.

I did this by old USB-Device-library for F407 and it worked well.

elvis

Posted on October 29, 2015 at 12:25

Zikhali,

I believe the root of your problem is that you are not checking the busy status of the USB Tx channel before sending.  ie; when you do a

USBD_CDC_TransmitPacket(&hUsbDeviceFS); it starts the transmit process.  If you do this again before the last transmission is complete you will step on the previous transmission by overwriting parameters and end up in the infinite loop error interrupt handler.

It works in your earlier code because the transmit function is waiting for your input before starting the next transmission.  When you allow the transmitter to send whenever your program has something to say (necessary if you are implementing a VCP for logging etc) your transmit routine needs to check status before sending. 

Unfortunately many of the VCP examples, even if you get them running, ignore this because they implement a RS232 Port - to USB VCP translator.  This also does not exhibit the problem because the RS232 source is never fast enough to flood the USB transmitter so it is self throttling.

I've developed several tutorials for using CubeMX code with the Free CooCox CoIDE toolchain, and among them is a VCP, printf implementation that fixes this problem.  Take a look at my modifications to the cdc_if.c file for the Tx routine that holds up subsequent xmissions until the previous one is complete.

https://www.dropbox.com/sh/yg4iy7h6xmca7lk/AACouu73L44JaYNdtgqSV0pna?dl=0

Here's the snippet from the code module:

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)

{

  uint8_t result = USBD_OK;

  /* USER CODE BEGIN 7 */

  do {

     result = USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);

    }

    while(result != USBD_OK);

    do {

     result = USBD_CDC_TransmitPacket(hUsbDevice_0);

    }

    while(result != USBD_OK);

  /* USER CODE END 7 */

  return result;

}