cancel
Showing results for 
Search instead for 
Did you mean: 

STM32_USBD_OTG VCP example explanation

jjackbauer7
Associate III
Posted on March 17, 2013 at 12:51

Hi all,

I am a beginner to USB and after some days of reading USB OTG library and RM0033

in the scope of getting started with USB. I'll to try to explain the virual com

port example in my own words and fore w/o garantee.

The examples is the same for STM32F4xx and STM32F105/107 devices.

Thanks to post your corrections/comments and suggestios by replying to this post.

I will not cover the initialization and enumeration phases as it seems to be little

bit complicated (for a beginner) than communication phase.

The examples configures other than (EP0) the endpoints as following:

 - EP1: bulk IN / bulk OUT

 - EP2: Control IN

When sending data from terminal like application (from your host (PC)), the RXFLVL

flag (of GINTSTS register) is set and DCD_HandleRxStatusQueueLevel_ISR() is executed

within USBD_OTG_ISR_Handler()

In DCD_HandleRxStatusQueueLevel_ISR():

   - Read OTG_HS_GRXSTSP register

   - check the packet status filed

   - if packet status is data update (PKTSTS = 0010: OUT data packet received)

     (defined as STS_DATA_UPDT in USB lib)

     * read data from FIFO USB_OTG_ReadPacket(pdev,ep->xfer_buff, status.b.bcnt);

When reading data from FIFO is completed, the RXFLVL flag is set again and

DCD_HandleRxStatusQueueLevel_ISR() is executed within USBD_OTG_ISR_Handler()

In DCD_HandleRxStatusQueueLevel_ISR():

   - Read OTG_HS_GRXSTSP register

   - check the packet status filed

   - if packet status is transfer complete (PKTSTS = 0011: OUT transfer completed (triggers an interrupt))

     (defined as STS_XFER_COMP in USB lib)

     no special processing in this case !

The trasnfert complete triggers the EP1 OUT Endpoint hendler and USBD_OTG_EP1OUT_ISR_Handler()

is executed. Whithin USBD_OTG_EP1OUT_ISR_Handler():

   - Read DOEPINT register

   - Check that xfercompl flag is set set (XFRC bit in OTG_HS_DOEPINTx register)

   - If so inform upper layer that data are ready and call USBD_DataOutStage()

     which calls pdev->dev.class_cb->DataOut(pdev, epnum) ==> usbd_cdc_DataOut()

     ==> VCP_DataRx() ==> USART_SendData()

     (==> means function call)

When receiving data from external device to STM32 through USART_RX pin, the

EVAL_COM_IRQHandler() is executed which calls VCP_DataTx() which stores the received

data APP_Rx_Buffer[] buffer.

In usbd_cdc_SOF() which is called every SOF (125 µs in HS), check if FrameCounter

is equal to CDC_IN_FRAME_INTERVAL if so call Handle_USBAsynchXfer() and this stage

USB core will be aware that there are data to send over USB.

In Handle_USBAsynchXfer():

  - Set global variable USB_Tx_State

  - Configure EP1 (APP_Rx_Buffer, datalength)

  - Enable Tx FIFO empty interrupt source on EP1

In next call of USBD_OTG_ISR_Handler(), read GINTSTS register and inepint flag

is set and DCD_HandleInEP_ISR() is executed  and as EP1 has a dedicated IRQ handler

the interrupt was already masked to allow the execution on OTG_HS_EP1_IN_IRQHandler()

In OTG_HS_EP1_IN_IRQHandler()

  - read DIEPINT register and check if Tx empty flag is set (TXFE in DIEPINT in

    RM0033 and emptyintr in USB lib) if so call

    DCD_WriteEmptyTxFifo() ==> USB_OTG_WritePacket

OTG_HS_EP1_IN_IRQHandler() is triggered again with transfert complete flag set

this calls USBD_DCD_INT_fops->DataInStage(pdev , 1) ==> USBD_DataInStage()

==> usbd_cdc_DataIn() which resets USB_Tx_State = 0

 

Thanks & Regards,

 

Jack Bauer 

2 REPLIES 2
mikael239955_stm1
Associate
Posted on March 21, 2013 at 10:51

Nice 🙂

Since you have analyzed this inside out, where do you propose inserting a zero byte transfer to end a 64 byte transfer (see my bug post on this forum)? I fail to see how it could be done with a one-liner somewhere 🙂

tyronexj
Associate II
Posted on March 21, 2013 at 14:04

Great analysis. It is helpful.

Thanks.