Skip to content
Snippets Groups Projects
usb.c 7.43 KiB
#include "stm32_usb.h"
#include "usbd_cdc.h"

#define RX_DATA_SIZE  64
#define TX_DATA_SIZE  64

// private variables
extern PCD_HandleTypeDef PCDHandle;
USBD_HandleTypeDef USBHandle;
TComm *usb_comm_dev;
uint8_t usb_rx_buffer[RX_DATA_SIZE];
uint8_t usb_tx_buffer[TX_DATA_SIZE];
unsigned char usb_dma_phase;
unsigned char *usb_dma_phase_data;
unsigned short int usb_dma_phase_length;
unsigned short int usb_dma_phase_write_ptr;

// private functions
/**
  * @brief  CDC_Init_FS
  *         Initializes the CDC media low layer over the FS USB IP
  * @param  None
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t usb_cdc_init(void)
{
  /* USER CODE BEGIN 3 */
  /* Set Application Buffers */
  USBD_CDC_SetTxBuffer(&USBHandle, usb_tx_buffer, 0);
  USBD_CDC_SetRxBuffer(&USBHandle, usb_rx_buffer);

  /* initialize internal variables */
  usb_dma_phase=0x00;
  usb_dma_phase_data=0x00;
  usb_dma_phase_length=0;
  usb_dma_phase_write_ptr=0;

  return (USBD_OK);
  /* USER CODE END 3 */
}

/**
  * @brief  CDC_DeInit_FS
  *         DeInitializes the CDC media low layer
  * @param  None
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t usb_cdc_deinit(void)
{
  /* USER CODE BEGIN 4 */
  return (USBD_OK);
  /* USER CODE END 4 */
}

/**
  * @brief  CDC_Control_FS
  *         Manage the CDC class requests
  * @param  cmd: Command code            
  * @param  pbuf: Buffer containing command data (request parameters)
  * @param  length: Number of data to be sent (in bytes)
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t usb_cdc_control(uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
  /* USER CODE BEGIN 5 */
  switch (cmd)
  {
    case CDC_SEND_ENCAPSULATED_COMMAND:
      break;
    case CDC_GET_ENCAPSULATED_RESPONSE:
      break;

    case CDC_SET_COMM_FEATURE:
      break;

    case CDC_GET_COMM_FEATURE:
      break;

    case CDC_CLEAR_COMM_FEATURE:
      break;
  /*******************************************************************************/
  /* Line Coding Structure                                                       */
  /*-----------------------------------------------------------------------------*/
  /* Offset | Field       | Size | Value  | Description                          */
  /* 0      | dwDTERate   |   4  | Number |Data terminal rate, in bits per second*/
  /* 4      | bCharFormat |   1  | Number | Stop bits                            */
  /*                                        0 - 1 Stop bit                       */
  /*                                        1 - 1.5 Stop bits                    */
  /*                                        2 - 2 Stop bits                      */
  /* 5      | bParityType |  1   | Number | Parity                               */
  /*                                        0 - None                             */
  /*                                        1 - Odd                              */
  /*                                        2 - Even                             */
  /*                                        3 - Mark                             */
  /*                                        4 - Space                            */
  /* 6      | bDataBits  |   1   | Number Data bits (5, 6, 7, 8 or 16).          */
  /*******************************************************************************/
    case CDC_SET_LINE_CODING:
      break;

    case CDC_GET_LINE_CODING:
      pbuf[0]=(uint8_t)115200;
      pbuf[1]=(uint8_t)(115200>>8);
      pbuf[2]=(uint8_t)(115200>>16);
      pbuf[3]=(uint8_t)(115200>>24);
      pbuf[4]=0;
      pbuf[5]=0;
      pbuf[6]=8;
      break;

    case CDC_SET_CONTROL_LINE_STATE:
      break;

    case CDC_SEND_BREAK:
      break;

    default:
      break;
  }

  return (USBD_OK);
  /* USER CODE END 5 */
}

/**
  * @brief  CDC_Receive_FS
  *         Data received over USB OUT endpoint are sent over CDC interface 
  *         through this function.
  *           
  *         @note
  *         This function will block any OUT packet reception on USB endpoint 
  *         untill exiting this function. If you exit this function before transfer
  *         is complete on CDC interface (ie. using DMA controller) it will result 
  *         in receiving more data while previous ones are still not sent.
  *                 
  * @param  Buf: Buffer of data to be received
  * @param  Len: Number of data received (in bytes)
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t usb_cdc_receive(uint8_t* Buf, uint32_t *Len)
{
  int i=0;
  
/* USER CODE BEGIN 6 */
  for(i=0;i<(*Len);i++)
  {
    if(!usb_dma_phase)
      comm_do_irq_receive(usb_comm_dev,Buf[i]);
    else /* do DMA phase */
    {
      usb_dma_phase_data[usb_dma_phase_write_ptr]=Buf[i];
      usb_dma_phase_length--;
      usb_dma_phase_write_ptr++;
      if(usb_dma_phase_length==0)
        comm_do_dma_receive(usb_comm_dev);
    }
  }  
  USBD_CDC_ReceivePacket(&USBHandle);

  return (USBD_OK);
  /* USER CODE END 6 */
}

USBD_CDC_ItfTypeDef usb_cdc_ops =
{
  usb_cdc_init,
  usb_cdc_deinit,
  usb_cdc_control,
  usb_cdc_receive
};

// interrupt handlers
void USB_LP_CAN_RX0_IRQHandler(void)
{
  /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */

  /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */
  HAL_PCD_IRQHandler(&PCDHandle);
  /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */

  /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */
}

/* public functions*/
void usb_init(TComm *comm_dev,USBD_DescriptorsTypeDef *pdesc,USBD_ClassTypeDef *pclass)
{
  /* Initialize the comm structure */
  comm_dev->send_irq=usb_send_irq;
  comm_dev->enable_tx_irq=usb_enable_tx_irq;
  comm_dev->receive_irq=usb_receive_irq;
  comm_dev->cancel_receive_irq=usb_cancel_receive_irq;
  if(comm_dev->use_dma)
  {
    comm_dev->send_dma=usb_send_dma;
    comm_dev->receive_dma=usb_receive_dma;
    comm_dev->cancel_receive_dma=usb_cancel_receive_dma;
  }
  comm_dev->irq_send_cb=0x00000000;
  comm_dev->irq_receive_cb=0x00000000;
  comm_dev->dma_send_cb=0x00000000;
  comm_dev->dma_receive_cb=0x00000000;

  /* initialize internal variables */
  usb_comm_dev=comm_dev;

  /* initialize and start the USB device */
  USBD_Init(&USBHandle, pdesc, DEVICE_FS);
  USBD_RegisterClass(&USBHandle, pclass);
  USBD_CDC_RegisterInterface(&USBHandle, &usb_cdc_ops);
  USBD_Start(&USBHandle);
}

void usb_disconnect(void)
{
  HAL_PCD_DevDisconnect(&PCDHandle);
}

void usb_connect(void)
{
  HAL_PCD_DevConnect(&PCDHandle);
}

/* IRQ functions */
unsigned char usb_send_irq(unsigned char first_byte)
{
  return 0x00;
}

unsigned char usb_enable_tx_irq(void)
{
  return 0x00;
}

unsigned char usb_receive_irq(void)
{
  usb_dma_phase=0x00;

  return 0x00;
}

unsigned char usb_cancel_receive_irq(void)
{
  return 0x00;
}

/* DMA functions */
unsigned char usb_send_dma(unsigned char *data,unsigned short int length)
{
  uint8_t byte;

  /* USER CODE BEGIN 7 */
  USBD_CDC_SetTxBuffer(&USBHandle,data,length);
  USBD_CDC_TransmitPacket(&USBHandle);
  /* force the tx completion */
  comm_do_dma_send(usb_comm_dev);
  comm_do_irq_send(usb_comm_dev,&byte);
  /* USER CODE END 7 */

  return 0x00;
}

unsigned char usb_receive_dma(unsigned char *data,unsigned short int length)
{
  usb_dma_phase=0x01;
  usb_dma_phase_data=data;
  usb_dma_phase_length=length;
  usb_dma_phase_write_ptr=0;

  return 0x00;
}

unsigned char usb_cancel_receive_dma(void)
{
  usb_dma_phase=0x00;
  usb_dma_phase_data=0x00;
  usb_dma_phase_length=0;
  usb_dma_phase_write_ptr=0;

  return 0x00;
}