NANO100_BSP V3.04.002
The Board Support Package for Nano100BN Series
usbd.c
Go to the documentation of this file.
1/**************************************************************************/
13#include <string.h>
14#include "Nano100Series.h"
15
16/*--------------------------------------------------------------------------*/
17/* Global variables for Control Pipe */
18uint8_t g_usbd_SetupPacket[8] = {0};
19volatile uint8_t g_usbd_RemoteWakeupEn = 0;
24static volatile uint8_t *g_usbd_CtrlInPointer = 0;
25static volatile uint32_t g_usbd_CtrlInSize = 0;
26static volatile uint8_t *g_usbd_CtrlOutPointer = 0;
27static volatile uint32_t g_usbd_CtrlOutSize = 0;
28static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0;
29static volatile uint32_t g_usbd_UsbAddr = 0;
30static volatile uint32_t g_usbd_CtrlMaxPktSize = 8;
31static volatile uint32_t g_usbd_UsbAltInterface = 0;
32static volatile uint32_t g_usbd_CtrlOutToggle = 0;
33static volatile uint8_t g_usbd_CtrlInZeroFlag = 0ul;
34volatile uint32_t g_usbd_UsbConfig = 0;
40
45uint32_t g_u32EpStallLock = 0;
54void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
55{
56 g_usbd_sInfo = param;
57 g_usbd_pfnClassRequest = pfnClassReq;
58 g_usbd_pfnSetInterface = pfnSetInterface;
59
60 /* get EP0 maximum packet size */
61 g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7];
62
63 /* Initial USB engine */
64 USBD->CTL = 0x29f;
66 /* Force SE0, and then clear it to connect*/
68}
69
79void USBD_Start(void)
80{
81 /* Enable USB-related interrupts. */
83 CLK_SysTickDelay(100000);
85}
86
96void USBD_GetSetupPacket(uint8_t *buf)
97{
99}
100
111{
112 g_usbd_CtrlOutToggle = 0;
113 // Setup packet process
115
116 switch (g_usbd_SetupPacket[0] & 0x60) /* request type */
117 {
118 case REQ_STANDARD: // Standard
119 {
121 break;
122 }
123 case REQ_CLASS: // Class
124 {
126 {
128 }
129 break;
130 }
131 case REQ_VENDOR: // Vendor
132 {
134 {
136 }
137 break;
138 }
139 default: // reserved
140 {
141 /* Setup error, stall the device */
144 break;
145 }
146 }
147}
148
159{
160 uint32_t u32Len;
161
162 g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
163 u32Len = 0;
164 u32Len = g_usbd_SetupPacket[7];
165 u32Len <<= 8;
166 u32Len += g_usbd_SetupPacket[6];
167
168 switch (g_usbd_SetupPacket[3])
169 {
170 // Get Device Descriptor
171 case DESC_DEVICE:
172 {
173 u32Len = Minimum(u32Len, LEN_DEVICE);
174 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
176 break;
177 }
178 // Get Configuration Descriptor
179 case DESC_CONFIG:
180 {
181 uint32_t u32TotalLen;
182
183 u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
184 u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
185
186 if (u32Len > u32TotalLen)
187 {
188 u32Len = u32TotalLen;
189 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
190 {
191 g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
192 }
193 }
194 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);
196 break;
197 }
198 // Get HID Descriptor
199 case DESC_HID:
200 {
201 /* CV3.0 HID Class Descriptor Test,
202 Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */
203 uint32_t u32ConfigDescOffset; // u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index)
204 u32Len = Minimum(u32Len, LEN_HID);
205 u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]];
206 USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len);
208 break;
209 }
210 // Get Report Descriptor
211 case DESC_HID_RPT:
212 {
214 {
216 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
217 {
218 g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
219 }
220 }
223 break;
224 }
225 // Get String Descriptor
226 case DESC_STRING:
227 {
228 // Get String Descriptor
229 if(g_usbd_SetupPacket[2] < 4)
230 {
231 if (u32Len > g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0])
232 {
234 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
235 {
236 g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
237 }
238 }
241 }
242 else
243 {
244 // Not support. Reply STALL.
247 }
248 break;
249 }
250 default:
251 // Not support. Reply STALL.
254 break;
255 }
256}
257
268{
269 /* clear global variables for new request */
270 g_usbd_CtrlInPointer = 0;
271 g_usbd_CtrlInSize = 0;
272
273 if (g_usbd_SetupPacket[0] & 0x80) /* request data transfer direction */
274 {
275 // Device to host
276 switch (g_usbd_SetupPacket[1])
277 {
278 case GET_CONFIGURATION:
279 {
280 // Return current configuration setting
281 /* Data stage */
282 M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbConfig;
285 /* Status stage */
287 break;
288 }
289 case GET_DESCRIPTOR:
290 {
292 break;
293 }
294 case GET_INTERFACE:
295 {
296 // Return current interface setting
297 /* Data stage */
298 M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbAltInterface;
301 /* Status stage */
303 break;
304 }
305 case GET_STATUS:
306 {
307 // Device
308 if(g_usbd_SetupPacket[0] == 0x80)
309 {
310 uint8_t u8Tmp;
311
312 u8Tmp = 0;
313 if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x40) u8Tmp |= 1; // Self-Powered/Bus-Powered.
314 if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x20) u8Tmp |= (g_usbd_RemoteWakeupEn << 1); // Remote wake up
315
317 }
318 // Interface
319 else if (g_usbd_SetupPacket[0] == 0x81)
321 // Endpoint
322 else if (g_usbd_SetupPacket[0] == 0x82)
323 {
324 uint8_t ep = g_usbd_SetupPacket[4] & 0xF;
326 }
327
329 /* Data stage */
332 /* Status stage */
334 break;
335 }
336 default:
337 {
338 /* Setup error, stall the device */
341 break;
342 }
343 }
344 }
345 else
346 {
347 // Host to device
348 switch (g_usbd_SetupPacket[1])
349 {
350 case CLEAR_FEATURE:
351 {
352 if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
353 {
354
355 int32_t epNum, i;
356
357 /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
358 a flag: g_u32EpStallLock is added to support it */
359 epNum = g_usbd_SetupPacket[4] & 0xF;
360 for(i = 0; i < USBD_MAX_EP; i++)
361 {
362 if(((USBD->EP[i].CFG & 0xF) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0))
364 }
365 }
366 else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
368 /* Status stage */
371 break;
372 }
373 case SET_ADDRESS:
374 {
375 g_usbd_UsbAddr = g_usbd_SetupPacket[2];
376
377 // DATA IN for end of setup
378 /* Status Stage */
381 break;
382 }
383 case SET_CONFIGURATION:
384 {
385 g_usbd_UsbConfig = g_usbd_SetupPacket[2];
386
389
390 if (g_usbd_UsbConfig == 0)
391 {
392 int volatile i;
393
394 /* Reset PID DATA0 */
395 for (i = 2; i < USBD_MAX_EP; i++)
396 USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
397 }
398
399 // DATA IN for end of setup
400 /* Status stage */
403 break;
404 }
405
406 case SET_FEATURE:
407 {
408 if (g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
410 else if (g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
412
413 /* Status stage */
416 break;
417 }
418
419 case SET_INTERFACE:
420 {
421 g_usbd_UsbAltInterface = g_usbd_SetupPacket[2];
422
424 g_usbd_pfnSetInterface(g_usbd_UsbAltInterface);
425
426 /* Status stage */
429 break;
430 }
431
432 default:
433 {
434 /* Setup error, stall the device */
437 break;
438 }
439 }
440 }
441}
442
453void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
454{
455 if(u32Size > g_usbd_CtrlMaxPktSize)
456 {
457 // Data size > MXPLD
458 g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize;
459 g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
461 USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, g_usbd_CtrlMaxPktSize);
462 USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
463 }
464 else
465 {
466 // Data size <= MXPLD
467 g_usbd_CtrlInPointer = 0;
468 g_usbd_CtrlInSize = 0;
470 USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, u32Size);
471 USBD_SET_PAYLOAD_LEN(EP0, u32Size);
472 }
473}
474
484void USBD_CtrlIn(void)
485{
486 if(g_usbd_CtrlInSize)
487 {
488 // Process remained data
489 if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize)
490 {
491 // Data size > MXPLD
492 USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
493 USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
494 g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
495 g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
496 }
497 else
498 {
499 // Data size <= MXPLD
500 USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
501 USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize);
502 g_usbd_CtrlInPointer = 0;
503 g_usbd_CtrlInSize = 0;
504 }
505 }
506 else
507 {
508 // In ACK for Set address
509 if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS))
510 {
511 if((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0))
512 {
513 USBD_SET_ADDR(g_usbd_UsbAddr);
514 }
515 }
516
517 /* For the case of data size is integral times maximum packet size */
518 if(g_usbd_CtrlInZeroFlag)
519 {
521 g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
522 }
523 }
524}
525
536void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
537{
538 g_usbd_CtrlOutPointer = pu8Buf;
539 g_usbd_CtrlOutSize = 0;
540 g_usbd_CtrlOutSizeLimit = u32Size;
541 USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
542}
543
553void USBD_CtrlOut(void)
554{
555 uint32_t u32Size;
556
557 if (g_usbd_CtrlOutToggle != (USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk))
558 {
559 g_usbd_CtrlOutToggle = USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk;
560 if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
561 {
562 u32Size = USBD_GET_PAYLOAD_LEN(EP1);
563 USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1), u32Size);
564 g_usbd_CtrlOutPointer += u32Size;
565 g_usbd_CtrlOutSize += u32Size;
566 }
567 }
568 else
569 {
570 USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
571 }
572}
573
583void USBD_SwReset(void)
584{
585 int i;
586
587 // Reset all variables for protocol
588 g_usbd_CtrlInPointer = 0;
589 g_usbd_CtrlInSize = 0;
590 g_usbd_CtrlOutPointer = 0;
591 g_usbd_CtrlOutSize = 0;
592 g_usbd_CtrlOutSizeLimit = 0;
593 memset(g_usbd_SetupPacket, 0, 8);
594
595 /* Reset PID DATA0 */
596 for (i=0; i<USBD_MAX_EP; i++)
597 USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
598
599 // Reset USB device address
600 USBD_SET_ADDR(0);
601}
602
603
614{
615 g_usbd_pfnVendorRequest = pfnVendorReq;
616}
626void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
627{
628 g_usbd_pfnSetConfigCallback = pfnSetConfigCallback;
629}
630
631void USBD_LockEpStall(uint32_t u32EpBitmap)
632{
633 g_u32EpStallLock = u32EpBitmap;
634}
635
636
637
Nano100 series peripheral access layer header file. This file contains all the peripheral register's ...
#define USBD_EPSTS_EPSTS1_Msk
#define USBD_CFG_DSQ_SYNC_Msk
#define USBD_CFG_SSTALL_Msk
#define USBD_PDMA_BYTEM_Msk
int32_t CLK_SysTickDelay(uint32_t us)
This function execute delay function.
Definition: clk.c:560
#define M8(addr)
Get a 8-bit unsigned value from specified address.
#define USBD
Pointer to USBD register structure.
#define USBD_INT_FLDET
Definition: usbd.h:124
#define USBD_INT_WAKEUP
Definition: usbd.h:125
#define USBD_MAX_EP
Definition: usbd.h:47
#define USBD_BUF_BASE
Definition: usbd.h:45
#define USBD_INT_BUS
Definition: usbd.h:122
#define EP1
Definition: usbd.h:50
#define USBD_INT_USB
Definition: usbd.h:123
#define EP0
Definition: usbd.h:49
#define USBD_GET_EP_BUF_ADDR(ep)
Get buffer for USB endpoint.
Definition: usbd.h:342
void USBD_LockEpStall(uint32_t u32EpBitmap)
Definition: usbd.c:631
void USBD_StandardRequest(void)
Process USB standard request.
Definition: usbd.c:267
#define USBD_SET_SE0()
Force USB PHY Transceiver to Drive SE0.
Definition: usbd.h:220
#define USBD_GET_PAYLOAD_LEN(ep)
Get USB payload size (OUT data)
Definition: usbd.h:319
uint32_t * gu32ConfigHidDescIdx
Definition: usbd.h:33
void(* VENDOR_REQ)(void)
Definition: usbd.h:484
#define USBD_SET_DATA1(ep)
Set USB data1 token.
Definition: usbd.h:297
volatile uint8_t g_usbd_RemoteWakeupEn
Definition: usbd.c:19
void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
Prepare Control OUT transaction.
Definition: usbd.c:536
static __INLINE void USBD_SetStall(uint8_t epnum)
Set USB endpoint stall state.
Definition: usbd.h:408
#define USBD_GET_ADDR()
Get USBD address.
Definition: usbd.h:241
uint8_t ** gu8StringDesc
Definition: usbd.h:30
uint8_t ** gu8HidReportDesc
Definition: usbd.h:31
uint32_t * gu32HidReportSize
Definition: usbd.h:32
static __INLINE uint32_t USBD_GetStall(uint8_t epnum)
Get USB endpoint stall state.
Definition: usbd.h:463
#define USBD_SET_ADDR(addr)
Set USBD address.
Definition: usbd.h:234
void USBD_GetSetupPacket(uint8_t *buf)
Get Setup Packet.
Definition: usbd.c:96
void(* CLASS_REQ)(void)
Definition: usbd.h:486
#define USBD_CLR_SE0()
Release SE0.
Definition: usbd.h:227
void USBD_Start(void)
USBD Start.
Definition: usbd.c:79
void USBD_SwReset(void)
Clear all software flags.
Definition: usbd.c:583
void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
Prepare Control IN transaction.
Definition: usbd.c:453
uint8_t * gu8ConfigDesc
Definition: usbd.h:29
void USBD_CtrlIn(void)
Start Control IN transfer.
Definition: usbd.c:484
#define Minimum(a, b)
Compare two input numbers and return minimum one.
Definition: usbd.h:185
void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
The callback function which called when get SET CONFIGURATION request.
Definition: usbd.c:626
static __INLINE void USBD_MemCopy(uint8_t *dest, uint8_t *src, int32_t size)
To support byte access between USB SRAM and system SRAM.
Definition: usbd.h:394
#define USBD_SET_EP_STALL(ep)
Set USB endpoint stall state.
Definition: usbd.h:354
void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
USBD Set Vendor Request.
Definition: usbd.c:613
uint8_t * gu8DevDesc
Definition: usbd.h:28
void USBD_ProcessSetupPacket(void)
Process Setup Packet.
Definition: usbd.c:110
void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
USBD Initial, Enable clock and reset USB.
Definition: usbd.c:54
void(* SET_CONFIG_CB)(void)
Definition: usbd.h:489
void(* SET_INTERFACE_REQ)(uint32_t u32AltInterface)
Definition: usbd.h:488
void USBD_CtrlOut(void)
Start Control OUT transfer.
Definition: usbd.c:553
#define USBD_ENABLE_INT(intr)
Enable USBD interrupt.
Definition: usbd.h:248
#define USBD_SET_PAYLOAD_LEN(ep, size)
Set USB payload size (IN data)
Definition: usbd.h:312
#define NULL
NULL pointer.
S_USBD_INFO_T * g_usbd_sInfo
Definition: usbd.c:39
CLASS_REQ g_usbd_pfnClassRequest
Definition: usbd.c:42
void USBD_GetDescriptor(void)
Get Descriptor request.
Definition: usbd.c:158
SET_INTERFACE_REQ g_usbd_pfnSetInterface
Definition: usbd.c:43
uint32_t g_u32EpStallLock
Definition: usbd.c:45
uint8_t g_usbd_SetupPacket[8]
Definition: usbd.c:18
SET_CONFIG_CB g_usbd_pfnSetConfigCallback
Definition: usbd.c:44
VENDOR_REQ g_usbd_pfnVendorRequest
Definition: usbd.c:41