Skip to content

Commit 3ce8026

Browse files
committed
[USB] CDC interface
Signed-off-by: Frederic.Pillon <[email protected]>
1 parent ecc259f commit 3ce8026

File tree

2 files changed

+209
-57
lines changed

2 files changed

+209
-57
lines changed

Diff for: cores/arduino/stm32/usb/cdc/usbd_cdc_if.c

+192-55
Original file line numberDiff line numberDiff line change
@@ -23,49 +23,47 @@
2323
/* Includes ------------------------------------------------------------------*/
2424
#include "usbd_cdc_if.h"
2525

26-
/** @addtogroup STM32_USB_DEVICE_LIBRARY
27-
* @{
28-
*/
26+
/* USBD_CDC Private Variables */
2927

28+
/* Create buffer for reception and transmission */
29+
/* It's up to user to redefine and/or remove those define */
30+
extern USBD_HandleTypeDef hUSBD_Device_CDC;
31+
/* Received Data over USB are stored in this buffer */
32+
__IO uint8_t UserRxBuffer[APP_RX_DATA_SIZE];
33+
__IO uint8_t StackRxBuffer[APP_RX_DATA_SIZE];
3034

31-
/** @defgroup USBD_CDC
32-
* @brief usbd core module
33-
* @{
34-
*/
35+
/* Send Data over USB CDC are stored in this buffer */
36+
__IO uint8_t UserTxBuffer[APP_TX_DATA_SIZE];
37+
__IO uint8_t StackTxBuffer[APP_TX_DATA_SIZE];
3538

36-
/** @defgroup USBD_CDC_Private_TypesDefinitions
37-
* @{
38-
*/
39-
/**
40-
* @}
41-
*/
39+
__IO uint32_t UserTxBufPtrIn = 0; /* Increment this pointer or roll it back to
40+
start address when data are received over write call */
41+
__IO uint32_t UserTxBufPtrOut = 0; /* Increment this pointer or roll it back to
42+
start address when data are sent over USB */
4243

44+
__IO uint32_t UserRxBufPtrIn = 0; /* Increment this pointer or roll it back to
45+
start address when data are received over USB */
46+
__IO uint32_t UserRxBufPtrOut = 0; /* Increment this pointer or roll it back to
47+
start address when data are sent over read call */
4348

44-
/** @defgroup USBD_CDC_Private_Defines
45-
* @{
46-
*/
47-
/**
48-
* @}
49-
*/
49+
__IO uint32_t SLP;
50+
__IO uint32_t GetRxCount;
51+
__IO uint32_t lineState = 0;
52+
uint8_t cptlineState = 0;
53+
volatile uint32_t USB_received = 0;
54+
uint8_t USBBuffer[64];
55+
uint8_t USBPackSize;
5056

57+
stimer_t CDC_TimHandle;
5158

52-
/** @defgroup USBD_CDC_Private_Macros
53-
* @{
54-
*/
55-
56-
/**
57-
* @}
58-
*/
59-
60-
61-
/** @defgroup USBD_CDC_Private_FunctionPrototypes
62-
* @{
63-
*/
59+
/** USBD_CDC Private Function Prototypes */
6460

6561
static int8_t USBD_CDC_Init (void);
6662
static int8_t USBD_CDC_DeInit (void);
6763
static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length);
6864
static int8_t USBD_CDC_Receive (uint8_t* pbuf, uint32_t *Len);
65+
static void CDC_TIM_Config(void);
66+
void CDC_TIM_PeriodElapsedCallback(stimer_t *htim);
6967

7068
USBD_CDC_ItfTypeDef USBD_CDC_fops =
7169
{
@@ -93,10 +91,14 @@ USBD_CDC_LineCodingTypeDef linecoding =
9391
*/
9492
static int8_t USBD_CDC_Init(void)
9593
{
96-
/*
97-
Add your initialization code here
98-
*/
99-
return (0);
94+
/* Configure and start the TIM Base generation */
95+
CDC_TIM_Config();
96+
97+
/* Set Application Buffers */
98+
USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t *)UserTxBuffer, 1);
99+
USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, (uint8_t *)StackRxBuffer);
100+
101+
return (USBD_OK);
100102
}
101103

102104
/**
@@ -107,53 +109,66 @@ static int8_t USBD_CDC_Init(void)
107109
*/
108110
static int8_t USBD_CDC_DeInit(void)
109111
{
110-
/*
111-
Add your deinitialization code here
112-
*/
113-
return (0);
112+
return (USBD_OK);
114113
}
115114

116115

117116
/**
118117
* @brief USBD_CDC_Control
119118
* Manage the CDC class requests
120-
* @param Cmd: Command code
121-
* @param Buf: Buffer containing command data (request parameters)
122-
* @param Len: Number of data to be sent (in bytes)
119+
* @param cmd: Command code
120+
* @param pbuf: Buffer containing command data (request parameters)
121+
* @param length: Number of data to be sent (in bytes)
123122
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
124123
*/
125124
static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
126125
{
126+
UNUSED(length);
127127
switch (cmd)
128128
{
129129
case CDC_SEND_ENCAPSULATED_COMMAND:
130-
/* Add your code here */
130+
131131
break;
132132

133133
case CDC_GET_ENCAPSULATED_RESPONSE:
134-
/* Add your code here */
134+
135135
break;
136136

137137
case CDC_SET_COMM_FEATURE:
138-
/* Add your code here */
138+
139139
break;
140140

141141
case CDC_GET_COMM_FEATURE:
142-
/* Add your code here */
142+
143143
break;
144144

145145
case CDC_CLEAR_COMM_FEATURE:
146-
/* Add your code here */
146+
147147
break;
148148

149+
/*******************************************************************************/
150+
/* Line Coding Structure */
151+
/*-----------------------------------------------------------------------------*/
152+
/* Offset | Field | Size | Value | Description */
153+
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
154+
/* 4 | bCharFormat | 1 | Number | Stop bits */
155+
/* 0 - 1 Stop bit */
156+
/* 1 - 1.5 Stop bits */
157+
/* 2 - 2 Stop bits */
158+
/* 5 | bParityType | 1 | Number | Parity */
159+
/* 0 - None */
160+
/* 1 - Odd */
161+
/* 2 - Even */
162+
/* 3 - Mark */
163+
/* 4 - Space */
164+
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
165+
/*******************************************************************************/
149166
case CDC_SET_LINE_CODING:
150167
linecoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\
151168
(pbuf[2] << 16) | (pbuf[3] << 24));
152169
linecoding.format = pbuf[4];
153170
linecoding.paritytype = pbuf[5];
154171
linecoding.datatype = pbuf[6];
155-
156-
/* Add your code here */
157172
break;
158173

159174
case CDC_GET_LINE_CODING:
@@ -164,23 +179,23 @@ static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
164179
pbuf[4] = linecoding.format;
165180
pbuf[5] = linecoding.paritytype;
166181
pbuf[6] = linecoding.datatype;
167-
168-
/* Add your code here */
169182
break;
170183

171184
case CDC_SET_CONTROL_LINE_STATE:
172-
/* Add your code here */
185+
cptlineState++;
186+
if(cptlineState == 2)
187+
lineState = 1;
173188
break;
174189

175190
case CDC_SEND_BREAK:
176-
/* Add your code here */
191+
177192
break;
178193

179194
default:
180195
break;
181196
}
182197

183-
return (0);
198+
return (USBD_OK);
184199
}
185200

186201
/**
@@ -201,10 +216,132 @@ static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
201216
*/
202217
static int8_t USBD_CDC_Receive (uint8_t* Buf, uint32_t *Len)
203218
{
219+
/* Initiate next USB packet transfer once a packet is received */
220+
USBPackSize = *Len;
221+
memcpy(USBBuffer, Buf, USBPackSize);
204222

205-
return (0);
223+
USB_received = 1;
224+
return (USBD_OK);
206225
}
207226

227+
void CDC_flush(void)
228+
{
229+
uint8_t status;
230+
231+
if(UserTxBufPtrOut != UserTxBufPtrIn)
232+
{
233+
if(UserTxBufPtrOut > UserTxBufPtrIn) /* Roll-back */
234+
{
235+
memcpy((uint8_t*)&StackTxBuffer[0], (uint8_t*)&UserTxBuffer[UserTxBufPtrOut], (APP_TX_DATA_SIZE - UserTxBufPtrOut));
236+
237+
memcpy((uint8_t*)&StackTxBuffer[APP_TX_DATA_SIZE - UserTxBufPtrOut], (uint8_t*)&UserTxBuffer[0], UserTxBufPtrIn);
238+
239+
USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t*)&StackTxBuffer[0], (APP_TX_DATA_SIZE - UserTxBufPtrOut + UserTxBufPtrIn));
240+
241+
do {
242+
status = USBD_CDC_TransmitPacket(&hUSBD_Device_CDC);
243+
} while(status == USBD_BUSY);
244+
245+
if(status == USBD_OK)
246+
{
247+
UserTxBufPtrOut = UserTxBufPtrIn;
248+
}
249+
}
250+
else
251+
{
252+
USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t*)&UserTxBuffer[UserTxBufPtrOut], (UserTxBufPtrIn - UserTxBufPtrOut));
253+
254+
do {
255+
status = USBD_CDC_TransmitPacket(&hUSBD_Device_CDC);
256+
} while(status == USBD_BUSY);
257+
258+
if(status == USBD_OK)
259+
{
260+
UserTxBufPtrOut = UserTxBufPtrIn;
261+
}
262+
}
263+
}
264+
}
265+
266+
void CDC_disable_TIM_Interrupt(void)
267+
{
268+
HAL_NVIC_DisableIRQ(CDC_TIM_IRQn);
269+
}
270+
271+
void CDC_enable_TIM_Interrupt(void)
272+
{
273+
HAL_NVIC_EnableIRQ(CDC_TIM_IRQn);
274+
}
275+
276+
static void CDC_TIM_Config(void)
277+
{
278+
/* Set TIMx instance */
279+
CDC_TimHandle.timer = CDC_TIM;
280+
/* Initialize CDC_TIM peripheral as follow:
281+
+ Period = 10000 - 1
282+
+ Prescaler = ((SystemCoreClock/2)/10000) - 1
283+
+ ClockDivision = 0
284+
+ Counter direction = Up
285+
*/
286+
TimerHandleInit(&CDC_TimHandle, (uint16_t)((CDC_POLLING_INTERVAL*1000) - 1), ((uint32_t)(getTimerClkFreq(CDC_TIM) / (1000000)) - 1));
287+
HAL_NVIC_SetPriority(CDC_TIM_IRQn, 6, 0);
288+
289+
attachIntHandle(&CDC_TimHandle, CDC_TIM_PeriodElapsedCallback);
290+
}
291+
292+
void CDC_TIM_PeriodElapsedCallback(stimer_t *htim)
293+
{
294+
UNUSED(htim);
295+
uint8_t status;
296+
297+
if(USB_received) {
298+
USB_received = 0;
299+
300+
if((USBPackSize > 0)) {
301+
if(UserRxBufPtrIn + USBPackSize > APP_RX_DATA_SIZE) {
302+
memcpy(((uint8_t *)UserRxBuffer+UserRxBufPtrIn), &USBBuffer[0], (APP_RX_DATA_SIZE - UserRxBufPtrIn));
303+
memcpy((uint8_t *)UserRxBuffer, &USBBuffer[(APP_RX_DATA_SIZE - UserRxBufPtrIn)], (USBPackSize - (APP_RX_DATA_SIZE - UserRxBufPtrIn)));
304+
UserRxBufPtrIn = ((UserRxBufPtrIn + USBPackSize) % APP_RX_DATA_SIZE);
305+
} else {
306+
memcpy(((uint8_t *)UserRxBuffer+UserRxBufPtrIn), USBBuffer, USBPackSize);
307+
UserRxBufPtrIn = ((UserRxBufPtrIn + USBPackSize) % APP_RX_DATA_SIZE);
308+
}
309+
}
310+
311+
USBD_CDC_ReceivePacket(&hUSBD_Device_CDC);
312+
}
313+
314+
if(UserTxBufPtrOut != UserTxBufPtrIn) {
315+
if(UserTxBufPtrOut > UserTxBufPtrIn) { /* Roll-back */
316+
memcpy((uint8_t*)&StackTxBuffer[0], (uint8_t*)&UserTxBuffer[UserTxBufPtrOut], (APP_TX_DATA_SIZE - UserTxBufPtrOut));
317+
318+
memcpy((uint8_t*)&StackTxBuffer[APP_TX_DATA_SIZE - UserTxBufPtrOut], (uint8_t*)&UserTxBuffer[0], UserTxBufPtrIn);
319+
320+
USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t*)&StackTxBuffer[0], (APP_TX_DATA_SIZE - UserTxBufPtrOut + UserTxBufPtrIn));
321+
322+
do {
323+
status = USBD_CDC_TransmitPacket(&hUSBD_Device_CDC);
324+
} while(status == USBD_BUSY);
325+
326+
if(status == USBD_OK) {
327+
UserTxBufPtrOut = UserTxBufPtrIn;
328+
}
329+
}
330+
else {
331+
USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t*)&UserTxBuffer[UserTxBufPtrOut], (UserTxBufPtrIn - UserTxBufPtrOut));
332+
333+
do {
334+
status = USBD_CDC_TransmitPacket(&hUSBD_Device_CDC);
335+
} while(status == USBD_BUSY);
336+
337+
if(status == USBD_OK) {
338+
UserTxBufPtrOut = UserTxBufPtrIn;
339+
}
340+
}
341+
}
342+
}
343+
344+
208345
#endif /* USBD_USE_CDC */
209346
#endif /* USBCON */
210347
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Diff for: cores/arduino/stm32/usb/cdc/usbd_cdc_if.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,36 @@
3030

3131
/* Includes ------------------------------------------------------------------*/
3232
#include "usbd_cdc.h"
33+
#include "timer.h"
3334

3435
#ifndef APP_RX_DATA_SIZE
35-
#define APP_RX_DATA_SIZE 256
36+
#define APP_RX_DATA_SIZE 2048
3637
#endif
3738
#ifndef APP_TX_DATA_SIZE
38-
#define APP_TX_DATA_SIZE 256
39+
#define APP_TX_DATA_SIZE 2048
3940
#endif
4041

42+
#ifndef CDC_TIM
43+
#define CDC_TIM TIM6
44+
#endif
45+
#ifndef CDC_TIM_IRQn
46+
#define CDC_TIM_IRQn TIM6_IRQn
47+
#endif
48+
49+
/* Periodically, the state of the buffer "UserTxBuffer" is checked.
50+
The period depends on CDC_POLLING_INTERVAL */
51+
#define CDC_POLLING_INTERVAL 2 /* in ms. The max is 65 and the min is 1 */
52+
4153
/* Exported types ------------------------------------------------------------*/
4254
/* Exported constants --------------------------------------------------------*/
4355

4456
extern USBD_CDC_ItfTypeDef USBD_CDC_fops;
4557

4658
/* Exported macro ------------------------------------------------------------*/
4759
/* Exported functions ------------------------------------------------------- */
60+
void CDC_disable_TIM_Interrupt(void);
61+
void CDC_enable_TIM_Interrupt(void);
62+
void CDC_flush(void);
4863

4964
#ifdef __cplusplus
5065
}

0 commit comments

Comments
 (0)