cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Discovery Board and VCP USB drivers/application

jsvirzi
Associate II
Posted on January 17, 2015 at 22:16

Hello,

I have a STM32F4 Discovery board, which I plan to use as sensor-based data acquisition board, switching from RS232 to USB communication with host. The simplest path I see to take is to make the device a Virtual Com Port.

There are a lot of examples with code such as

https://github.com/MaJerle/stm32f429/tree/master/24-STM32F429_USB_VCP

 and this is highly appreciated.

I use the STMCubeMX application to generate the system skeleton, and I develop within the ''/* BEGIN USER CODE */ and /* END USER CODE */. This is great because I can swap out configurations, and STMCube writes out new code, but preserves my code.

I naively tried to use the USB packages from STMCubeMX but it doesn't work. I do have the example described above to work, but now I am tied to that particular configuration of code. Therefore, I cannot use STMCubeMX anymore to change settings and write new code.

My question is whether anyone knows what needs to be done to the USB code generated by STMCubeMX to get it to work as a CDC VCP? That way, I can continue to work within the STMCubeMX/Keil framework.

Thanks,

-Joe

****************************

P.S. - This has been very happily resolved, complete with working code and a summary of steps required. Please see the reply to this thread on 19 Jan for the information

#st
12 REPLIES 12
jirik09
Associate II
Posted on January 17, 2015 at 23:10

I had the same problem. How does your usbd_cdc_if.c looks like? My functions were doing nothing. Try to use this. It makes echo function. 

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

{

  /* USER CODE BEGIN 7 */

  static uint8_t buff_TX[256];

  int i = 0;

  for (i = 0; i < *Len; i++){

    buff_TX[i] = *(Buf++);

  }

  USBD_CDC_ReceivePacket(&hUsbDeviceFS);

  CDC_Transmit_FS(buff_TX,*Len);

  return (USBD_OK);

  /* USER CODE END 7 */

}

uint8_t CDC_Transmit_FS(uint8_t* UserTxBufferFS, uint16_t Len)

{

  uint8_t result = USBD_OK;

  /* USER CODE BEGIN 8 */

  USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len); 

  result = USBD_CDC_TransmitPacket(hUsbDevice_0);

  /* USER CODE END 8 */

  return result;

}

jsvirzi
Associate II
Posted on January 18, 2015 at 07:11

Thanks. I see what the code does. However, my problem is even more basic than that. My device is not being recognized by the host. Using the above link, that code does make the STM32F4 Discovery board recognizable as a VCP to the host. And everything works.

I would like to see code out of the STMCube box that identifies itself as a VCP to the host. Maybe I have a wrong configuration somewhere. Do you have this code, or even the STMCube project file?

jirik09
Associate II
Posted on January 18, 2015 at 09:34

I generated code by STMCube. I just selected STM32F4-discovery board, set USB_OTG_FS in Peripherals to Device_Only and  USB_DEVICE in MiddleWares to CDC. Then I changed clocks to HSE and generated it.

And I forgot that I deleted something from usbd_conf.c. I guess that your MCU got stuck in OTG_FS_WKUP_IRQHandler if so try to deactivate this interrupt and don‘t care about wake up. You can deactivate it by deleting part of code below from usbd_conf.c

   if(hpcd->Init.low_power_enable == 1)

    {....}

Then PC should recognize your board. If it recognize but not configure (fails on error: device cannot start code 10) try to reduce USB_HS_MAX_PACKET_SIZE and CDC_DATA_HS_MAX_PACKET_SIZE from 512 to 256. Even though it is not using HS configuration, it helped me.

I’m using VPC driver 1.40 from ST http://www.st.com/web/en/catalog/tools/PF257938

Hope it help

jsvirzi
Associate II
Posted on January 19, 2015 at 06:57

Hi,

I tried what you said, but Windows 7 still considers this an ''unknown device''. I commented out the wakeup interrupt code as you mentioned, and that helped.

I reduced the buffer/packet sizes to 256 from 512, but that didn't seem to do much.

You DID have this working, right? You seem to be the only person who could get the STM32CubeMX code to work out of the box,

except for the modifications you described. There are some other lost souls in these forums looking to do something similar.

My plan is to get this working and post the code and project files and credit you, of course.

Thanks,

Joe

jirik09
Associate II
Posted on January 19, 2015 at 10:53

Yes I did. And PC which never saw STM32-VCP before found it as ''STM32 Virtual ComPort'' and said that driver is mising. 

Here is project which works on my PCs https://www.dropbox.com/s/d20dygj3yp8vt0a/USB_VCP_Echo.zip

If this don't work, try to reinstall VCP driver.

jsvirzi
Associate II
Posted on January 19, 2015 at 20:33

Forget bitcoin, they should have bitbeer and then I could buy you one!

Your example worked out-of-the-box, just as I love examples to work.

I (or you) should probably pass this code along to the other lost souls out there doing this.

I would like to finish this thread off by summarizing from start-to-finish the steps in producing this example.

To that end, I have a few questions.

a) what did you do about SOF and VBUS? enable/disable within STMCubeMX?

b) did you do anything else besides the edits described above?

Thanks,

Joe

jsvirzi
Associate II
Posted on January 20, 2015 at 08:04

Thanks to ''jirik09'' I have summarized the necessary steps to create a USB Virtual Com Port starting from code generated by STM32CubeMX.

The following directions are for the STM32F4 Discovery board. If you are using Windows, at some point you should install the USB VCP drivers.

You can find those here:

http://www.st.com/web/en/catalog/tools/PF257938

The code that follows simply echoes. But it works, with some massaging after the STM32CubeMX.

jirik09 has graciously included the code that you would build below:

https://www.dropbox.com/s/d20dygj3yp8vt0a/USB_VCP_Echo.zip

Step 1: Create project with STMCubeMX:

a) select USB_OTG_FS. Pins PA11 and PA12 should now be configured for USB.

b) do not select neither activate SOF nor VBUS

c) do not select USB_OTG_HS. So it is disabled. Ignore red or yellow warnings

d) keep all the default settings under Middlewares configuration and USB_FS configuration

Step 2: Save the STM32CubeMX project, generate the code and open the tool chain (MDK ARM, etc.) project

Step 3: Edit the usb_cdc_if.c. Replace the existing functions with those below:

 static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len){

   /* USER CODE BEGIN 7 */

   static uint8_t buff_TX[256];

   int i = 0;

   for (i = 0; i < *Len; i++){

     buff_TX[i] = *(Buf++);

   }

   USBD_CDC_ReceivePacket(&hUsbDeviceFS);

   CDC_Transmit_FS(buff_TX,*Len);

   return (USBD_OK);

   /* USER CODE END 7 */

 }

 

 uint8_t CDC_Transmit_FS(uint8_t* UserTxBufferFS, uint16_t Len){

   uint8_t result = USBD_OK;

   /* USER CODE BEGIN 8 */

   USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);

   result = USBD_CDC_TransmitPacket(hUsbDevice_0);

   /* USER CODE END 8 */

   return result;

 }

Step 4: Edit usbd_def.h to reflect the following define directive (probably should already have 512)

#define USB_HS_MAX_PACKET_SIZE 256

Edit usbd_cdc.h to reflect the following define directive (probably should already have 512)

#define CDC_DATA_HS_MAX_PACKET_SIZE 256

Step 5: Edit usbd_conf.h and comment out the following code as below:

#if 0  

    if(hpcd->Init.low_power_enable == 1)

    {

      /* Enable EXTI Line 18 for USB wakeup */

      __HAL_USB_FS_EXTI_CLEAR_FLAG();

      __HAL_USB_FS_EXTI_SET_RISING_EGDE_TRIGGER();

      __HAL_USB_FS_EXTI_ENABLE_IT();

      HAL_NVIC_SetPriority(OTG_FS_WKUP_IRQn, 0, 0);

      HAL_NVIC_EnableIRQ(OTG_FS_WKUP_IRQn);

    }

#endif

Step 6: Compile and run. Then plug it into your USB.

Windows should pop up with a new entry in the Device Manager under ''Ports (COM and LPT)'' as something like STMicroelectronics Virtual COM Port (COM28).

jsvirzi
Associate II
Posted on January 20, 2015 at 19:40

FYI,

In addition to the above edits, a subtle bug has been reported

    

http://visualgdb.com/tutorials/arm/stm32/usb/

Look at item 22, regarding a bug in the ordering of code in the function ''USBD_CDC_TransmitPacket()''. I will replicate the final steps here:

*********************

The ST's USBD_CDC_TransmitPacket() function contains a bug: it sets the 'transmission in progress' flag AFTER starting the actual transmission, so if the 'transmission done' interrupt happens too early, the flag will be set AFTER the interrupt and hence will never be cleared. To fix this, move ''hcdc->TxState = 1'' line before the call to USBD_LL_Transmit():

if

(hcdc->TxState == 0)

{

    hcdc->TxState = 1;

    USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer,

                     hcdc->TxLength);

   

return

USBD_OK;

}
ed
Associate
Posted on January 25, 2015 at 22:10

Thanks so much for this post as it works as said .

Would you have any idea why when you add FreeRTOS to the project is breaks again. I have re-adjusted the generated code with the said values.

Tracing the code the first received packet arrives but after that it will no longer receive. I suspect that the changing of interrupt priorities to match FreeRTOS and the Stack switching may have something to do with it. I was fighting both problems at once so now I've seen the USB code working I'll concentrate on the latest issue.