21
21
#ifdef USBD_USE_CDC
22
22
23
23
/* Includes ------------------------------------------------------------------*/
24
+ #include "usbd_desc.h"
24
25
#include "usbd_cdc_if.h"
25
26
26
27
#ifdef USE_USB_HS
32
33
#endif
33
34
34
35
/* USBD_CDC Private Variables */
36
+ /* USB Device Core CDC handle declaration */
37
+ USBD_HandleTypeDef hUSBD_Device_CDC ;
35
38
36
- /* Create buffer for reception and transmission */
37
- /* It's up to user to redefine and/or remove those define */
38
- extern USBD_HandleTypeDef hUSBD_Device_CDC ;
39
39
/* Received Data over USB are stored in this buffer */
40
- __IO uint8_t UserRxBuffer [APP_RX_DATA_SIZE ];
41
- __IO uint8_t StackRxBuffer [CDC_MAX_PACKET_SIZE ];
42
-
43
- /* Send Data over USB CDC are stored in this buffer */
44
- __IO uint8_t UserTxBuffer [APP_TX_DATA_SIZE ];
45
- __IO uint8_t StackTxBuffer [APP_TX_DATA_SIZE ];
46
-
47
- __IO uint32_t UserTxBufPtrIn = 0 ; /* Increment this pointer or roll it back to
48
- start address when data are received over write call */
49
- __IO uint32_t UserTxBufPtrOut = 0 ; /* Increment this pointer or roll it back to
50
- start address when data are sent over USB */
51
-
52
- __IO uint32_t UserRxBufPtrIn = 0 ; /* Increment this pointer or roll it back to
53
- start address when data are received over USB */
54
- __IO uint32_t UserRxBufPtrOut = 0 ; /* Increment this pointer or roll it back to
55
- start address when data are sent over read call */
56
-
40
+ CDC_TransmitQueue_TypeDef TransmitQueue ;
41
+ CDC_ReceiveQueue_TypeDef ReceiveQueue ;
57
42
__IO uint32_t lineState = 0 ;
58
- __IO bool receiveSuspended = false;
59
- __IO bool sendZLP = false;
43
+ __IO bool receivePended = false;
60
44
61
- stimer_t CDC_TimHandle ;
62
45
63
46
/** USBD_CDC Private Function Prototypes */
64
47
65
48
static int8_t USBD_CDC_Init (void );
66
49
static int8_t USBD_CDC_DeInit (void );
67
50
static int8_t USBD_CDC_Control (uint8_t cmd , uint8_t * pbuf , uint16_t length );
68
51
static int8_t USBD_CDC_Receive (uint8_t * pbuf , uint32_t * Len );
69
- static void CDC_TIM_Config (void );
70
- void CDC_TIM_PeriodElapsedCallback (stimer_t * htim );
52
+ static int8_t USBD_CDC_Transferred (void );
71
53
72
54
USBD_CDC_ItfTypeDef USBD_CDC_fops =
73
55
{
74
56
USBD_CDC_Init ,
75
57
USBD_CDC_DeInit ,
76
58
USBD_CDC_Control ,
77
- USBD_CDC_Receive
59
+ USBD_CDC_Receive ,
60
+ USBD_CDC_Transferred
78
61
};
79
62
80
63
USBD_CDC_LineCodingTypeDef linecoding =
@@ -95,12 +78,11 @@ USBD_CDC_LineCodingTypeDef linecoding =
95
78
*/
96
79
static int8_t USBD_CDC_Init (void )
97
80
{
98
- /* Configure and start the TIM Base generation */
99
- CDC_TIM_Config ();
100
-
101
81
/* Set Application Buffers */
102
- USBD_CDC_SetTxBuffer (& hUSBD_Device_CDC , (uint8_t * )UserTxBuffer , 1 );
103
- USBD_CDC_SetRxBuffer (& hUSBD_Device_CDC , (uint8_t * )StackRxBuffer );
82
+ CDC_TransmitQueue_Init (& TransmitQueue );
83
+ CDC_ReceiveQueue_Init (& ReceiveQueue );
84
+ receivePended = true;
85
+ USBD_CDC_SetRxBuffer (& hUSBD_Device_CDC , CDC_ReceiveQueue_ReserveBlock (& ReceiveQueue ));
104
86
105
87
return (USBD_OK );
106
88
}
@@ -217,155 +199,80 @@ static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
217
199
* @param Len: Number of data received (in bytes)
218
200
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
219
201
*/
220
- static int8_t USBD_CDC_Receive (uint8_t * Buf , uint32_t * Len )
221
- {
222
- uint32_t packetSize = * Len ;
223
-
224
- if (packetSize > 0 ) {
225
- if (UserRxBufPtrIn + packetSize > APP_RX_DATA_SIZE ) {
226
- memcpy (((uint8_t * )UserRxBuffer + UserRxBufPtrIn ), & Buf [0 ],
227
- (APP_RX_DATA_SIZE - UserRxBufPtrIn ));
228
- memcpy ((uint8_t * )UserRxBuffer ,
229
- & Buf [(APP_RX_DATA_SIZE - UserRxBufPtrIn )],
230
- (packetSize - (APP_RX_DATA_SIZE - UserRxBufPtrIn )));
231
- UserRxBufPtrIn = ((UserRxBufPtrIn + packetSize ) % APP_RX_DATA_SIZE );
232
- } else {
233
- memcpy (((uint8_t * )UserRxBuffer + UserRxBufPtrIn ), Buf , packetSize );
234
- UserRxBufPtrIn = ((UserRxBufPtrIn + packetSize ) % APP_RX_DATA_SIZE );
235
- }
236
- }
237
-
238
- if ((UserRxBufPtrOut + APP_RX_DATA_SIZE - UserRxBufPtrIn - 1 ) %
239
- APP_RX_DATA_SIZE + 1 >= CDC_MAX_PACKET_SIZE ) {
240
- USBD_CDC_ReceivePacket (
241
- & hUSBD_Device_CDC ); // Initiate next USB packet transfer once a packet
242
- // is received and there is enouch space in the
243
- // buffer
244
- } else {
245
- receiveSuspended = true;
246
- }
247
- return (USBD_OK );
202
+ static int8_t USBD_CDC_Receive (uint8_t * Buf , uint32_t * Len ) {
203
+ UNUSED (Buf );
204
+ /* It always contains required amount of free space for writing */
205
+ CDC_ReceiveQueue_CommitBlock (& ReceiveQueue , (uint16_t )(* Len ));
206
+ receivePended = false;
207
+ /* If enough space in the queue for a full buffer then continue receive */
208
+ CDC_resume_receive ();
209
+ return USBD_OK ;
248
210
}
249
211
250
- void CDC_flush (void )
251
- {
252
- uint8_t status ;
253
-
254
- if (UserTxBufPtrOut != UserTxBufPtrIn )
255
- {
256
- if (UserTxBufPtrOut > UserTxBufPtrIn ) /* Roll-back */
257
- {
258
- memcpy ((uint8_t * )& StackTxBuffer [0 ],
259
- (uint8_t * )& UserTxBuffer [UserTxBufPtrOut ],
260
- (APP_TX_DATA_SIZE - UserTxBufPtrOut ));
261
- memcpy ((uint8_t * )& StackTxBuffer [APP_TX_DATA_SIZE - UserTxBufPtrOut ],
262
- (uint8_t * )& UserTxBuffer [0 ], UserTxBufPtrIn );
263
-
264
- USBD_CDC_SetTxBuffer (
265
- & hUSBD_Device_CDC , (uint8_t * )& StackTxBuffer [0 ],
266
- (APP_TX_DATA_SIZE - UserTxBufPtrOut + UserTxBufPtrIn ));
267
- } else {
268
- USBD_CDC_SetTxBuffer (& hUSBD_Device_CDC ,
269
- (uint8_t * )& UserTxBuffer [UserTxBufPtrOut ],
270
- (UserTxBufPtrIn - UserTxBufPtrOut ));
271
- }
272
-
273
- do {
274
- if (lineState == 0 ) { // Device disconnected
275
- status = USBD_OK ;
276
- } else {
277
- status = USBD_CDC_TransmitPacket (& hUSBD_Device_CDC );
278
- }
279
- } while (status == USBD_BUSY );
280
212
281
- if (status == USBD_OK ) {
282
- UserTxBufPtrOut = UserTxBufPtrIn ;
283
- }
284
- }
213
+ static int8_t USBD_CDC_Transferred (void ) {
214
+ CDC_continue_transmit ();
215
+ return (USBD_OK );
285
216
}
286
217
287
- void CDC_resume_receive (void ) {
288
- if (receiveSuspended ) {
289
- if ((UserRxBufPtrOut + APP_RX_DATA_SIZE - UserRxBufPtrIn - 1 ) %
290
- APP_RX_DATA_SIZE + 1 >= CDC_MAX_PACKET_SIZE ) {
291
- USBD_CDC_ReceivePacket (
292
- & hUSBD_Device_CDC ); // Initiate next USB packet transfer once a packet
293
- // is received and there is enouch space in the
294
- // buffer
295
- receiveSuspended = false;
218
+ void CDC_init (void ) {
219
+ /* Init Device Library */
220
+ if (USBD_Init (& hUSBD_Device_CDC , & CDC_Desc , 0 ) == USBD_OK ) {
221
+ /* Add Supported Class */
222
+ if (USBD_RegisterClass (& hUSBD_Device_CDC , USBD_CDC_CLASS ) == USBD_OK ) {
223
+ /* Add CDC Interface Class */
224
+ if (USBD_CDC_RegisterInterface (& hUSBD_Device_CDC , & USBD_CDC_fops ) == USBD_OK ) {
225
+ /* Start Device Process */
226
+ USBD_Start (& hUSBD_Device_CDC );
227
+ }
296
228
}
297
229
}
298
230
}
299
231
300
- void CDC_disable_TIM_Interrupt (void )
301
- {
302
- HAL_NVIC_DisableIRQ (CDC_TIM_IRQn );
303
- }
304
-
305
- void CDC_enable_TIM_Interrupt (void )
306
- {
307
- HAL_NVIC_EnableIRQ (CDC_TIM_IRQn );
232
+ void CDC_deInit (void ) {
233
+ USBD_Stop (& hUSBD_Device_CDC );
234
+ USBD_CDC_DeInit ();
235
+ USBD_DeInit (& hUSBD_Device_CDC );
308
236
}
309
237
310
- static void CDC_TIM_Config (void )
311
- {
312
- /* Set TIMx instance */
313
- CDC_TimHandle .timer = CDC_TIM ;
314
- /* Initialize CDC_TIM peripheral as follow:
315
- + Period = 10000 - 1
316
- + Prescaler = ((SystemCoreClock/2)/10000) - 1
317
- + ClockDivision = 0
318
- + Counter direction = Up
319
- */
320
- TimerHandleInit (& CDC_TimHandle , (uint16_t )((CDC_POLLING_INTERVAL * 1000 ) - 1 ), ((uint32_t )(getTimerClkFreq (CDC_TIM ) / (1000000 )) - 1 ));
321
- HAL_NVIC_SetPriority (CDC_TIM_IRQn , 6 , 0 );
322
-
323
- attachIntHandle (& CDC_TimHandle , CDC_TIM_PeriodElapsedCallback );
324
- }
325
-
326
- void CDC_TIM_PeriodElapsedCallback (stimer_t * htim )
327
- {
328
- UNUSED (htim );
329
- if (UserTxBufPtrOut == UserTxBufPtrIn &&
330
- sendZLP == false) // Nothing to do, return immediately
331
- return ;
332
-
333
- uint8_t status ;
334
- uint16_t packetLength ;
335
-
336
- if (UserTxBufPtrOut > UserTxBufPtrIn ) { /* Roll-back */
337
- memcpy ((uint8_t * )& StackTxBuffer [0 ],
338
- (uint8_t * )& UserTxBuffer [UserTxBufPtrOut ],
339
- (APP_TX_DATA_SIZE - UserTxBufPtrOut ));
340
- memcpy ((uint8_t * )& StackTxBuffer [APP_TX_DATA_SIZE - UserTxBufPtrOut ],
341
- (uint8_t * )& UserTxBuffer [0 ], UserTxBufPtrIn );
342
-
343
- packetLength = (APP_TX_DATA_SIZE - UserTxBufPtrOut + UserTxBufPtrIn );
344
-
345
- USBD_CDC_SetTxBuffer (& hUSBD_Device_CDC , (uint8_t * )& StackTxBuffer [0 ],
346
- packetLength );
347
- } else if (UserTxBufPtrOut != UserTxBufPtrIn ) {
348
- packetLength = (UserTxBufPtrIn - UserTxBufPtrOut );
349
-
350
- USBD_CDC_SetTxBuffer (& hUSBD_Device_CDC ,
351
- (uint8_t * )& UserTxBuffer [UserTxBufPtrOut ],
352
- packetLength );
353
- } else {
354
- packetLength = 0 ;
355
-
356
- USBD_CDC_SetTxBuffer (& hUSBD_Device_CDC , NULL , 0 ); // Send Zero Length Packet
357
- }
358
-
359
- if (lineState == 0 ) { // Device disconnected
360
- status = USBD_OK ;
361
- } else {
362
- status = USBD_CDC_TransmitPacket (& hUSBD_Device_CDC );
238
+ void CDC_continue_transmit (void ) {
239
+ uint16_t size ;
240
+ uint8_t * buffer ;
241
+ USBD_CDC_HandleTypeDef * hcdc = (USBD_CDC_HandleTypeDef * ) hUSBD_Device_CDC .pClassData ;
242
+ /*
243
+ * TS: This method can be called both in the main thread
244
+ * (via USBSerial::write) and in the IRQ stream (via USBD_CDC_Transferred),
245
+ * BUT the main thread cannot pass this condition while waiting for a IRQ!
246
+ * This is not possible because TxState is not zero while waiting for data
247
+ * transfer ending! The IRQ thread is uninterrupted, since its priority
248
+ * is higher than that of the main thread. So this method is thread safe.
249
+ */
250
+ if (hcdc -> TxState == 0U ) {
251
+ buffer = CDC_TransmitQueue_ReadBlock (& TransmitQueue , & size );
252
+ if (size > 0 ) {
253
+ USBD_CDC_SetTxBuffer (& hUSBD_Device_CDC , buffer , size );
254
+ /*
255
+ * size never exceed PMA buffer and USBD_CDC_TransmitPacket make full
256
+ * copy of block in PMA, so no need to worry about buffer damage
257
+ */
258
+ USBD_CDC_TransmitPacket (& hUSBD_Device_CDC );
259
+ }
363
260
}
261
+ }
364
262
365
- if (status == USBD_OK ) {
366
- UserTxBufPtrOut = UserTxBufPtrIn ;
367
-
368
- sendZLP = packetLength % CDC_MAX_PACKET_SIZE == 0 ;
263
+ void CDC_resume_receive (void ) {
264
+ /*
265
+ * TS: main and IRQ threads can't pass it at same time, because
266
+ * IRQ may occur only if receivePended is true. So it is thread-safe!
267
+ */
268
+ if (!receivePended ) {
269
+ uint8_t * block = CDC_ReceiveQueue_ReserveBlock (& ReceiveQueue );
270
+ if (block != NULL ) {
271
+ receivePended = true;
272
+ /* Set new buffer */
273
+ USBD_CDC_SetRxBuffer (& hUSBD_Device_CDC , block );
274
+ USBD_CDC_ReceivePacket (& hUSBD_Device_CDC );
275
+ }
369
276
}
370
277
}
371
278
0 commit comments