cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429i-DISCO : Use USB as device CDC class (VCP)

mitcharnaud31
Associate II
Posted on October 16, 2013 at 21:03

Hello everybody,

I am stuck during these last days with my STM32F429i-DISCO.

I tried to use it as USB device, CDC class as a VCP.

I have configured the as USE_USB_OTG_HS, USE_EMBEDDED_PHY.

Configure the HS_ISR, Enable the HS_ISR, Enable the RCC clock, configure the PINS.

My PC see the USB device, but not correctly recognized. The SW is stuck in the OTG_HS ISR (triggered infinitly...).

Anyone has the same problems ?

Anyone success to configure USB device VCP ?

I made some checks about PINS and frequencies with guys from the community, put the frequency to 168 Mhz and update the HSE to 8Mhz ... but without success.

Thank your for your feedback about USB device VCP experience ...

#stm32f4 #usb #otg #dual_role
19 REPLIES 19
Posted on March 21, 2014 at 04:36

Observed what I'm defining in the makefile, the first one is likely to directly impact how the firmware library code/includes are handled.

USE_STDPERIPH_DRIVER
 STM32F429_439xx
 USE_STM32F429I_DISCO
 USE_USB_OTG_HS
 USE_EMBEDDED_PHY
 HSE_VALUE=8000000

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
matteo
Associate II
Posted on March 21, 2014 at 18:18

[third reply attempt]

Thank you!

Adding the defines I had missed did indeed solve my problem. One of this days I should learn to read makefiles...

I now have the board appear as a ST VCP. I connect to it through the Termite terminal and it loops back what I send to it.

Now I would like to understand a bit more about what is going on. I would expect to see somewhere some callback to handle interrupts generated on data receive, but I cannot find them.

I'm super new to embedded programming. In my previous learning projects I used the stm32cube tool to generate the init code, then added lines in my main (to start timers) and callbacks at the bottom of main.c to manage interrupts. Things like HAL_TIM_PeriodElapsedCallback(...).

I see nothing similar in your code.

Thanks,

Matteo

Posted on March 21, 2014 at 18:35

I see nothing similar in your code.

The Cube stuff is a month old, I'm not using it. The code uses USB and USART interrupts.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
matteo
Associate II
Posted on March 23, 2014 at 03:27

Am I correct in my guess that this is the part in your code that I should change to implement a different behaviour of the board? This is where the loopback is happening, right?

void EVAL_COM_IRQHandler(void)
{
if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)
{
/* Send the received data to the PC Host*/
VCP_DataTx (0,0);
}
/* If overrun condition occurs, clear the ORE flag and recover communication */
if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)
{
(void)USART_ReceiveData(EVAL_COM1);
}
}

Correct me if I am wrong: To implement custom functionality, I should change the VCP_DataTx(0,0) line with something to receive the data (USART_ReceiveData(EVAL_COM1)) and pass it on to a function that would, for example, decode it as a command for the device, calling the appropriate response. Where should I put the output of this response? Would that be USART_SendData(EVAL_COM1, data) in a loop if my data is actually larger than 2 bytes? Best, Matteo
Posted on March 23, 2014 at 03:56

I'm not really looking to correct your assumptions, you need to analyze the code until you have an understanding of it. I understood the original ST code enough to port it, VCP devices don't play a big role in my product strategy.

The bulk of the magic occurs in usbd_cdc_vcp.c in VCP_DataRx() and VCP_DataTx(). I'm not particularly keen on ST's buffering strategy, but it appears sufficiently adequate to bond the virtual channel to a physical USART. If I were going for a totally virtual approach, where some other part of my device were generating, and sinking data, I would probably re-evaluate how that data was buffered, and supplied to the USB interface. This could be localized in usbd_cdc_vcp.c, and that's where I'd start.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
matteo
Associate II
Posted on March 23, 2014 at 23:26

Hello,

I was doing some testing and debugging and I think I broke something. No interrupt appears to ever trigger (USART1_IRQHandler is never triggered): When I send data to the board, VCP_DataRx is called (I added to it so it toggles a led when called). That should put data in the USART data register, and as a consequence trigger the RXNE interrupt. I would expect this to cause a call to USART1_IRQHandler (which would, among other things, light up another LED) but nothing happens. So the following code causes the green led to toggle each time i send data:

static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
{
uint32_t i;
STM_EVAL_LEDToggle(LED3);
//STM_EVAL_LEDOn(LED3);
for (i = 0; i < Len; i++)
{
USART_SendData(EVAL_COM1, *(Buf + i) );
while(USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXE) == RESET);
} 
return USBD_OK;
}

While the following code does not cause anything to happen, ever:

void EVAL_COM_IRQHandler(void)
{
STM_EVAL_LEDToggle(LED4);
if (USART_GetITStatus(EVAL_COM1, /*((uint16_t)0x0525)*/USART_IT_RXNE) != RESET)
{
/* Send the received data to the PC Host*/
VCP_DataTx (0,0);
}
/* If overrun condition occurs, clear the ORE flag and recover communication */
if (USART_GetFlagStatus(EVAL_COM1, ((uint16_t)0x0008)/*USART_FLAG_ORE*/) != RESET)
{
(void)USART_ReceiveData(EVAL_COM1);
}
}

I do not understand the reason for this behaviour. The functions to enable the interrupts are called correctly (both USAR_ITConfig and NVIC_Init).
matteo
Associate II
Posted on March 24, 2014 at 23:46

EUREKA!

I am a fool. I just realized I had not put a jumper between the PA9 and PA10 pins. Once I wired them together the system worked again like a charm. Way to waste a weekend nitpicking code line by line.... Now I am playing with it again, and I have new doubts. I tried to make the system send me the text ''FOo'' for any input I send. So:

void EVAL_COM_IRQHandler(void)
{
//STM_EVAL_LEDToggle(LED4);
if (USART_GetITStatus(EVAL_COM1, /*((uint16_t)0x0525)*/USART_IT_RXNE) != RESET)
{
STM_EVAL_LEDToggle(LED4);
/*My code starts here*/
 do
 {
 USART_ReceiveData(EVAL_COM1);
 }while(USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET);
uint8_t buf[3];
buf[0] = 70; //F
buf[1] = 79; //O
buf[2] = 111;//o
VCP_DataTx (buf, 3);
/*My code ends here*/
}
/* If overrun condition occurs, clear the ORE flag and recover communication */
if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET)
{
(void)USART_ReceiveData(EVAL_COM1);
}
}

And:

static uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len)
{
for(i = 0; i<Len;i++)
{
APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
APP_Rx_ptr_in++;
}
/* To avoid buffer overflow */
if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
{
APP_Rx_ptr_in = 0;
} 
return USBD_OK;
}

Instead of returning FOo only once, the board sends it 2 times for each char I am sending to it through my terminal.
matteo
Associate II
Posted on March 25, 2014 at 00:05

Quick update regarding my previous message:

The terminal was appending a termination character to my signal.

Now the issue I will try to solve is to have the board detect when the data it is being sent is a single stream, sort of thing, and not reply many times.

Thanks to all who pitched in here for getting me this far, and especially to clive1

Matteo

yasintasan
Associate II
Posted on August 28, 2015 at 14:06

when i implement this (VCP) project, can i use my microcontroller both in device and host modes? because OTG feature of USB peripheral tells us that we can use in both modes if i dont misunderstand. 

Posted on August 28, 2015 at 18:39

This is an implementation for a *DEVICE* only.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..