diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c index 402fba2ce5..e0f387eb7e 100644 --- a/stmhal/usbd_cdc_interface.c +++ b/stmhal/usbd_cdc_interface.c @@ -1,553 +1,393 @@ -/** - ****************************************************************************** - * @file USB_Device/CDC_Standalone/Src/usbd_cdc_interface.c - * @author MCD Application Team - * @version V1.0.1 - * @date 26-February-2014 - * @brief Source file for USBD CDC interface - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include -#include "stm32f4xx_hal.h" -#include "usbd_cdc.h" -#include "usbd_cdc_interface.h" -#include "pendsv.h" -#include "usb.h" - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @{ - */ - -/** @defgroup USBD_CDC - * @brief usbd core module - * @{ - */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE (was 2048) -#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048) - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ - -static uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; // received data from USB OUT endpoint is stored in this buffer -static uint16_t UserRxBufCur = 0; // points to next available character in UserRxBuffer -static uint16_t UserRxBufLen = 0; // counts number of valid characters in UserRxBuffer - -static uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer -static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available -static uint16_t UserTxBufPtrOut = 0; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained - -static int user_interrupt_char = VCP_CHAR_NONE; -static void *user_interrupt_data = NULL; - -/* TIM handler declaration */ -TIM_HandleTypeDef USBD_CDC_TimHandle; -/* USB handler declaration */ -extern USBD_HandleTypeDef hUSBDDevice; - -/* Private function prototypes -----------------------------------------------*/ -static int8_t CDC_Itf_Init (void); -static int8_t CDC_Itf_DeInit (void); -static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length); -static int8_t CDC_Itf_Receive (uint8_t* pbuf, uint32_t *Len); - -static void Error_Handler(void); -//static void ComPort_Config(void); -static void TIM_Config(void); - -const USBD_CDC_ItfTypeDef USBD_CDC_fops = { - CDC_Itf_Init, - CDC_Itf_DeInit, - CDC_Itf_Control, - CDC_Itf_Receive -}; - -/* Private functions ---------------------------------------------------------*/ - -/** - * @brief CDC_Itf_Init - * Initializes the CDC media low layer - * @param None - * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Itf_Init(void) -{ -#if 0 - /*##-1- Configure the UART peripheral ######################################*/ - /* Put the USART peripheral in the Asynchronous mode (UART Mode) */ - /* USART configured as follow: - - Word Length = 8 Bits - - Stop Bit = One Stop bit - - Parity = No parity - - BaudRate = 115200 baud - - Hardware flow control disabled (RTS and CTS signals) */ - UartHandle.Instance = USARTx; - UartHandle.Init.BaudRate = 115200; - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - UartHandle.Init.StopBits = UART_STOPBITS_1; - UartHandle.Init.Parity = UART_PARITY_NONE; - UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; - UartHandle.Init.Mode = UART_MODE_TX_RX; - - if(HAL_UART_Init(&UartHandle) != HAL_OK) - { - /* Initialization Error */ - Error_Handler(); - } - - /*##-2- Put UART peripheral in IT reception process ########################*/ - /* Any data received will be stored in "UserTxBuffer" buffer */ - if(HAL_UART_Receive_IT(&UartHandle, (uint8_t *)UserTxBuffer, 1) != HAL_OK) - { - /* Transfer error in reception process */ - Error_Handler(); - } -#endif - - /*##-3- Configure the TIM Base generation #################################*/ - TIM_Config(); - - /*##-4- Start the TIM Base generation in interrupt mode ####################*/ - /* Start Channel1 */ - if(HAL_TIM_Base_Start_IT(&USBD_CDC_TimHandle) != HAL_OK) - { - /* Starting Error */ - Error_Handler(); - } - - /*##-5- Set Application Buffers ############################################*/ - USBD_CDC_SetTxBuffer(&hUSBDDevice, UserTxBuffer, 0); - USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer); - - UserRxBufCur = 0; - UserRxBufLen = 0; - - user_interrupt_char = VCP_CHAR_NONE; - user_interrupt_data = NULL; - - return (USBD_OK); -} - -/** - * @brief CDC_Itf_DeInit - * DeInitializes the CDC media low layer - * @param None - * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Itf_DeInit(void) -{ -#if 0 - /* DeInitialize the UART peripheral */ - if(HAL_UART_DeInit(&UartHandle) != HAL_OK) - { - /* Initialization Error */ - Error_Handler(); - } -#endif - return (USBD_OK); -} - -/** - * @brief CDC_Itf_Control - * Manage the CDC class requests - * @param Cmd: Command code - * @param Buf: Buffer containing command data (request parameters) - * @param Len: Number of data to be sent (in bytes) - * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length) -{ - switch (cmd) - { - case CDC_SEND_ENCAPSULATED_COMMAND: - /* Add your code here */ - break; - - case CDC_GET_ENCAPSULATED_RESPONSE: - /* Add your code here */ - break; - - case CDC_SET_COMM_FEATURE: - /* Add your code here */ - break; - - case CDC_GET_COMM_FEATURE: - /* Add your code here */ - break; - - case CDC_CLEAR_COMM_FEATURE: - /* Add your code here */ - break; - - case CDC_SET_LINE_CODING: - #if 0 - LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\ - (pbuf[2] << 16) | (pbuf[3] << 24)); - LineCoding.format = pbuf[4]; - LineCoding.paritytype = pbuf[5]; - LineCoding.datatype = pbuf[6]; - - /* Set the new configuration */ - ComPort_Config(); - #endif - break; - - case CDC_GET_LINE_CODING: - #if 0 - pbuf[0] = (uint8_t)(LineCoding.bitrate); - pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8); - pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16); - pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24); - pbuf[4] = LineCoding.format; - pbuf[5] = LineCoding.paritytype; - pbuf[6] = LineCoding.datatype; - #endif - - /* Add your code here */ - 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; // stop bits (1) - pbuf[5] = 0; // parity (none) - pbuf[6] = 8; // number of bits (8) - break; - - case CDC_SET_CONTROL_LINE_STATE: - /* Add your code here */ - break; - - case CDC_SEND_BREAK: - /* Add your code here */ - break; - - default: - break; - } - - return (USBD_OK); -} - -/** - * @brief TIM period elapsed callback - * @param htim: TIM handle - * @retval None - */ -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -{ - uint32_t buffptr; - uint32_t buffsize; - - if(UserTxBufPtrOut != UserTxBufPtrIn) - { - if(UserTxBufPtrOut > UserTxBufPtrIn) /* rollback */ - { - buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut; - } - else - { - buffsize = UserTxBufPtrIn - UserTxBufPtrOut; - } - - buffptr = UserTxBufPtrOut; - - USBD_CDC_SetTxBuffer(&hUSBDDevice, (uint8_t*)&UserTxBuffer[buffptr], buffsize); - - if(USBD_CDC_TransmitPacket(&hUSBDDevice) == USBD_OK) - { - UserTxBufPtrOut += buffsize; - if (UserTxBufPtrOut == APP_RX_DATA_SIZE) - { - UserTxBufPtrOut = 0; - } - } - } -} - -#if 0 -/** - * @brief Rx Transfer completed callback - * @param huart: UART handle - * @retval None - */ -void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) -{ - /* Increment Index for buffer writing */ - UserTxBufPtrIn++; - - /* To avoid buffer overflow */ - if(UserTxBufPtrIn == APP_RX_DATA_SIZE) - { - UserTxBufPtrIn = 0; - } - - /* Start another reception: provide the buffer pointer with offset and the buffer size */ - HAL_UART_Receive_IT(huart, (uint8_t *)(UserTxBuffer + UserTxBufPtrIn), 1); -} -#endif - -/** - * @brief CDC_Itf_DataRx - * Data received over USB OUT endpoint is processed here. - * @param Buf: Buffer of data received - * @param Len: Number of data received (in bytes) - * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL - * @note The buffer we are passed here is just UserRxBuffer, so we are - * free to modify it. - */ -static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) { -#if 0 - // this sends the data over the UART using DMA - HAL_UART_Transmit_DMA(&UartHandle, Buf, *Len); -#endif - - if (user_interrupt_char == VCP_CHAR_NONE) { - // no special interrupt character - UserRxBufLen = *Len; - - } else { - // filter out sepcial interrupt character from the buffer - bool char_found = false; - uint8_t *dest = Buf; - uint8_t *src = Buf; - uint8_t *buf_top = Buf + *Len; - for (; src < buf_top; src++) { - if (*src == user_interrupt_char) { - char_found = true; - } else { - if (char_found) { - *dest = *src; - } - dest++; - } - } - - // set length of remaining characters - UserRxBufLen = dest - Buf; - - if (char_found) { - // raise exception when interrupts are finished - user_interrupt_char = VCP_CHAR_NONE; - pendsv_nlr_jump(user_interrupt_data); - } - } - - // there are new characters at the start of the buffer, so point there - UserRxBufCur = 0; - - if (UserRxBufLen == 0) { - // initiate next USB packet transfer now that UserRxBuffer has been drained - USBD_CDC_ReceivePacket(&hUSBDDevice); - } - - return (USBD_OK); -} - -void USBD_CDC_SetInterrupt(int chr, void *data) { - user_interrupt_char = chr; - user_interrupt_data = data; -} - -void USBD_CDC_Tx(const char *str, uint32_t len) { - for (int i = 0; i < len; i++) { - UserTxBuffer[UserTxBufPtrIn] = str[i]; - UserTxBufPtrIn = (UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1); - } -} - -int USBD_CDC_RxNum(void) { - return UserRxBufLen - UserRxBufCur; -} - -int USBD_CDC_RxGet(void) { - // wait for buffer to have at least 1 character in it - while (USBD_CDC_RxNum() == 0) { - __WFI(); - } - - // get next character - int c = UserRxBuffer[UserRxBufCur++]; - if (UserRxBufCur >= UserRxBufLen) { - // initiate next USB packet transfer now that UserRxBuffer has been drained - USBD_CDC_ReceivePacket(&hUSBDDevice); - } - return c; -} - -#if 0 -/** - * @brief Tx Transfer completed callback - * @param huart: UART handle - * @retval None - */ -void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) -{ - /* Initiate next USB packet transfer once UART completes transfer (transmitting data over Tx line) */ - USBD_CDC_ReceivePacket(&hUSBDDevice); -} - -/** - * @brief ComPort_Config - * Configure the COM Port with the parameters received from host. - * @param None. - * @retval None. - * @note When a configuration is not supported, a default value is used. - */ -static void ComPort_Config(void) -{ - if(HAL_UART_DeInit(&UartHandle) != HAL_OK) - { - /* Initialization Error */ - Error_Handler(); - } - - /* set the Stop bit */ - switch (LineCoding.format) - { - case 0: - UartHandle.Init.StopBits = UART_STOPBITS_1; - break; - case 2: - UartHandle.Init.StopBits = UART_STOPBITS_2; - break; - default : - UartHandle.Init.StopBits = UART_STOPBITS_1; - break; - } - - /* set the parity bit*/ - switch (LineCoding.paritytype) - { - case 0: - UartHandle.Init.Parity = UART_PARITY_NONE; - break; - case 1: - UartHandle.Init.Parity = UART_PARITY_ODD; - break; - case 2: - UartHandle.Init.Parity = UART_PARITY_EVEN; - break; - default : - UartHandle.Init.Parity = UART_PARITY_NONE; - break; - } - - /*set the data type : only 8bits and 9bits is supported */ - switch (LineCoding.datatype) - { - case 0x07: - /* With this configuration a parity (Even or Odd) must be set */ - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - break; - case 0x08: - if(UartHandle.Init.Parity == UART_PARITY_NONE) - { - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - } - else - { - UartHandle.Init.WordLength = UART_WORDLENGTH_9B; - } - - break; - default : - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - break; - } - - UartHandle.Init.BaudRate = LineCoding.bitrate; - UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; - UartHandle.Init.Mode = UART_MODE_TX_RX; - - if(HAL_UART_Init(&UartHandle) != HAL_OK) - { - /* Initialization Error */ - Error_Handler(); - } - - /* Start reception: provide the buffer pointer with offset and the buffer size */ - HAL_UART_Receive_IT(&UartHandle, (uint8_t *)(UserTxBuffer + UserTxBufPtrIn), 1); -} -#endif - -/** - * @brief TIM_Config: Configure TIMx timer - * @param None. - * @retval None. - */ -static void TIM_Config(void) -{ - /* Set TIMx instance */ - USBD_CDC_TimHandle.Instance = USBD_CDC_TIMx; - - /* Initialize TIM3 peripheral as follow: - + Period = 10000 - 1 - + Prescaler = ((SystemCoreClock/2)/10000) - 1 - + ClockDivision = 0 - + Counter direction = Up - */ - USBD_CDC_TimHandle.Init.Period = (USBD_CDC_POLLING_INTERVAL*1000) - 1; - USBD_CDC_TimHandle.Init.Prescaler = 84-1; - USBD_CDC_TimHandle.Init.ClockDivision = 0; - USBD_CDC_TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; - if(HAL_TIM_Base_Init(&USBD_CDC_TimHandle) != HAL_OK) - { - /* Initialization Error */ - Error_Handler(); - } -} - -#if 0 -/** - * @brief UART error callbacks - * @param UartHandle: UART handle - * @retval None - */ -void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle) -{ - /* Transfer error occured in reception and/or transmission process */ - Error_Handler(); -} -#endif - -/** - * @brief This function is executed in case of error occurrence. - * @param None - * @retval None - */ -static void Error_Handler(void) -{ - /* Add your own code here */ -} - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - +/** + ****************************************************************************** + * @file USB_Device/CDC_Standalone/Src/usbd_cdc_interface.c + * @author MCD Application Team + * @version V1.0.1 + * @date 26-February-2014 + * @brief Source file for USBD CDC interface + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include +#include "stm32f4xx_hal.h" +#include "usbd_cdc.h" +#include "usbd_cdc_interface.h" +#include "pendsv.h" +#include "usb.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE (was 2048) +#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +static uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; // received data from USB OUT endpoint is stored in this buffer +static uint16_t UserRxBufCur = 0; // points to next available character in UserRxBuffer +static uint16_t UserRxBufLen = 0; // counts number of valid characters in UserRxBuffer + +static uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer +static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available +static uint16_t UserTxBufPtrOut = 0; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained + +static int user_interrupt_char = VCP_CHAR_NONE; +static void *user_interrupt_data = NULL; + +/* TIM handler declaration */ +TIM_HandleTypeDef USBD_CDC_TimHandle; +/* USB handler declaration */ +extern USBD_HandleTypeDef hUSBDDevice; + +/* Private function prototypes -----------------------------------------------*/ +static int8_t CDC_Itf_Init (void); +static int8_t CDC_Itf_DeInit (void); +static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length); +static int8_t CDC_Itf_Receive (uint8_t* pbuf, uint32_t *Len); + +static void TIM_Config(void); + +const USBD_CDC_ItfTypeDef USBD_CDC_fops = { + CDC_Itf_Init, + CDC_Itf_DeInit, + CDC_Itf_Control, + CDC_Itf_Receive +}; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief CDC_Itf_Init + * Initializes the CDC media low layer + * @param None + * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Itf_Init(void) +{ +#if 0 + /*##-1- Configure the UART peripheral ######################################*/ + /* Put the USART peripheral in the Asynchronous mode (UART Mode) */ + /* USART configured as follow: + - Word Length = 8 Bits + - Stop Bit = One Stop bit + - Parity = No parity + - BaudRate = 115200 baud + - Hardware flow control disabled (RTS and CTS signals) */ + UartHandle.Instance = USARTx; + UartHandle.Init.BaudRate = 115200; + UartHandle.Init.WordLength = UART_WORDLENGTH_8B; + UartHandle.Init.StopBits = UART_STOPBITS_1; + UartHandle.Init.Parity = UART_PARITY_NONE; + UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + UartHandle.Init.Mode = UART_MODE_TX_RX; + + if(HAL_UART_Init(&UartHandle) != HAL_OK) + { + /* Initialization Error */ + Error_Handler(); + } + + /*##-2- Put UART peripheral in IT reception process ########################*/ + /* Any data received will be stored in "UserTxBuffer" buffer */ + if(HAL_UART_Receive_IT(&UartHandle, (uint8_t *)UserTxBuffer, 1) != HAL_OK) + { + /* Transfer error in reception process */ + Error_Handler(); + } +#endif + + /*##-3- Configure the TIM Base generation #################################*/ + TIM_Config(); + + /*##-4- Start the TIM Base generation in interrupt mode ####################*/ + /* Start Channel1 */ + if(HAL_TIM_Base_Start_IT(&USBD_CDC_TimHandle) != HAL_OK) + { + /* Starting Error */ + } + + /*##-5- Set Application Buffers ############################################*/ + USBD_CDC_SetTxBuffer(&hUSBDDevice, UserTxBuffer, 0); + USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer); + + UserRxBufCur = 0; + UserRxBufLen = 0; + + user_interrupt_char = VCP_CHAR_NONE; + user_interrupt_data = NULL; + + return (USBD_OK); +} + +/** + * @brief CDC_Itf_DeInit + * DeInitializes the CDC media low layer + * @param None + * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Itf_DeInit(void) +{ +#if 0 + /* DeInitialize the UART peripheral */ + if(HAL_UART_DeInit(&UartHandle) != HAL_OK) + { + /* Initialization Error */ + } +#endif + return (USBD_OK); +} + +/** + * @brief CDC_Itf_Control + * Manage the CDC class requests + * @param Cmd: Command code + * @param Buf: Buffer containing command data (request parameters) + * @param Len: Number of data to be sent (in bytes) + * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length) +{ + switch (cmd) + { + case CDC_SEND_ENCAPSULATED_COMMAND: + /* Add your code here */ + break; + + case CDC_GET_ENCAPSULATED_RESPONSE: + /* Add your code here */ + break; + + case CDC_SET_COMM_FEATURE: + /* Add your code here */ + break; + + case CDC_GET_COMM_FEATURE: + /* Add your code here */ + break; + + case CDC_CLEAR_COMM_FEATURE: + /* Add your code here */ + break; + + case CDC_SET_LINE_CODING: + #if 0 + LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\ + (pbuf[2] << 16) | (pbuf[3] << 24)); + LineCoding.format = pbuf[4]; + LineCoding.paritytype = pbuf[5]; + LineCoding.datatype = pbuf[6]; + + /* Set the new configuration */ + #endif + break; + + case CDC_GET_LINE_CODING: + #if 0 + pbuf[0] = (uint8_t)(LineCoding.bitrate); + pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8); + pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16); + pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24); + pbuf[4] = LineCoding.format; + pbuf[5] = LineCoding.paritytype; + pbuf[6] = LineCoding.datatype; + #endif + + /* Add your code here */ + 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; // stop bits (1) + pbuf[5] = 0; // parity (none) + pbuf[6] = 8; // number of bits (8) + break; + + case CDC_SET_CONTROL_LINE_STATE: + /* Add your code here */ + break; + + case CDC_SEND_BREAK: + /* Add your code here */ + break; + + default: + break; + } + + return (USBD_OK); +} + +/** + * @brief TIM period elapsed callback + * @param htim: TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + uint32_t buffptr; + uint32_t buffsize; + + if(UserTxBufPtrOut != UserTxBufPtrIn) + { + if(UserTxBufPtrOut > UserTxBufPtrIn) /* rollback */ + { + buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut; + } + else + { + buffsize = UserTxBufPtrIn - UserTxBufPtrOut; + } + + buffptr = UserTxBufPtrOut; + + USBD_CDC_SetTxBuffer(&hUSBDDevice, (uint8_t*)&UserTxBuffer[buffptr], buffsize); + + if(USBD_CDC_TransmitPacket(&hUSBDDevice) == USBD_OK) + { + UserTxBufPtrOut += buffsize; + if (UserTxBufPtrOut == APP_RX_DATA_SIZE) + { + UserTxBufPtrOut = 0; + } + } + } +} + +/** + * @brief CDC_Itf_DataRx + * Data received over USB OUT endpoint is processed here. + * @param Buf: Buffer of data received + * @param Len: Number of data received (in bytes) + * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL + * @note The buffer we are passed here is just UserRxBuffer, so we are + * free to modify it. + */ +static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) { +#if 0 + // this sends the data over the UART using DMA + HAL_UART_Transmit_DMA(&UartHandle, Buf, *Len); +#endif + + if (user_interrupt_char == VCP_CHAR_NONE) { + // no special interrupt character + UserRxBufLen = *Len; + + } else { + // filter out sepcial interrupt character from the buffer + bool char_found = false; + uint8_t *dest = Buf; + uint8_t *src = Buf; + uint8_t *buf_top = Buf + *Len; + for (; src < buf_top; src++) { + if (*src == user_interrupt_char) { + char_found = true; + } else { + if (char_found) { + *dest = *src; + } + dest++; + } + } + + // set length of remaining characters + UserRxBufLen = dest - Buf; + + if (char_found) { + // raise exception when interrupts are finished + user_interrupt_char = VCP_CHAR_NONE; + pendsv_nlr_jump(user_interrupt_data); + } + } + + // there are new characters at the start of the buffer, so point there + UserRxBufCur = 0; + + if (UserRxBufLen == 0) { + // initiate next USB packet transfer now that UserRxBuffer has been drained + USBD_CDC_ReceivePacket(&hUSBDDevice); + } + + return (USBD_OK); +} + +void USBD_CDC_SetInterrupt(int chr, void *data) { + user_interrupt_char = chr; + user_interrupt_data = data; +} + +void USBD_CDC_Tx(const char *str, uint32_t len) { + for (int i = 0; i < len; i++) { + uint timeout = 200; + while (UserTxBufPtrIn + 1 == UserTxBufPtrOut) { + if (timeout-- == 0) { + break; + } + HAL_Delay(1); + } + UserTxBuffer[UserTxBufPtrIn] = str[i]; + UserTxBufPtrIn = (UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1); + } +} + +int USBD_CDC_RxNum(void) { + return UserRxBufLen - UserRxBufCur; +} + +int USBD_CDC_RxGet(void) { + // wait for buffer to have at least 1 character in it + while (USBD_CDC_RxNum() == 0) { + __WFI(); + } + + // get next character + int c = UserRxBuffer[UserRxBufCur++]; + if (UserRxBufCur >= UserRxBufLen) { + // initiate next USB packet transfer now that UserRxBuffer has been drained + USBD_CDC_ReceivePacket(&hUSBDDevice); + } + return c; +} + +/** + * @brief TIM_Config: Configure TIMx timer + * @param None. + * @retval None. + */ +static void TIM_Config(void) +{ + /* Set TIMx instance */ + USBD_CDC_TimHandle.Instance = USBD_CDC_TIMx; + + /* Initialize TIM3 peripheral as follow: + + Period = 10000 - 1 + + Prescaler = ((SystemCoreClock/2)/10000) - 1 + + ClockDivision = 0 + + Counter direction = Up + */ + USBD_CDC_TimHandle.Init.Period = (USBD_CDC_POLLING_INTERVAL*1000) - 1; + USBD_CDC_TimHandle.Init.Prescaler = 84-1; + USBD_CDC_TimHandle.Init.ClockDivision = 0; + USBD_CDC_TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; + if(HAL_TIM_Base_Init(&USBD_CDC_TimHandle) != HAL_OK) + { + /* Initialization Error */ + } +}