1 /******************************************************************************************************************************************
2 * 文件名称: SWM341_usbd.c
3 * 功能说明: SWM341单片机的USB设备功能驱动库
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2020年11月3日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include <string.h>
22 #include "SWM341.h"
23 #include "SWM341_usbd.h"
24 
25 
26 USBD_Info_t USBD_Info;
27 
28 
29 static uint8_t *CtrlIn_Ptr = 0;
30 static uint8_t *CtrlOut_Ptr = 0;
31 static volatile uint32_t CtrlIn_Size = 0;
32 static volatile uint32_t CtrlOut_Size = 0;
33 static volatile uint32_t CtrlOut_Limit = 0;
34 
35 
36 /******************************************************************************************************************************************
37 * 函数名称: USBD_Init()
38 * 功能说明: USB Device 初始化
39 * 输    入: 无
40 * 输    出: 无
41 * 注意事项: 无
42 ******************************************************************************************************************************************/
USBD_Init(void)43 void USBD_Init(void)
44 {
45     uint8_t  ep_reg = 0, ep_nbr, ep_dir, ep_type, cfg, intf, alt;
46     uint16_t ep_pksz;
47     uint8_t  *pCfg = USBD_Info.DescConfig;
48     uint32_t total_len = pCfg[2] + (pCfg[3] << 8);
49     uint32_t epie = 0x00010001;
50 
51     SYS->USBCR = 0;
52     for(int i = 0; i < CyclesPerUs; i++) __NOP();
53     SYS->USBCR |= (1 << SYS_USBCR_RST48M_Pos); __DSB();
54     SYS->USBCR |= (1 << SYS_USBCR_RST12M_Pos); __DSB();
55     SYS->USBCR |= (1 << SYS_USBCR_RSTPLL_Pos); __DSB();
56 
57     SYS->USBCR &= ~SYS_USBCR_ROLE_Msk;
58     SYS->USBCR |= (USBD_Info.Mode << SYS_USBCR_ROLE_Pos);
59 
60     SYS->USBCR |= (1 << SYS_USBCR_VBUS_Pos);
61 
62     SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_USB_Pos);
63 
64     USBD_EPConfig(ep_reg++, 0, USB_EP_IN,  USB_EP_CTRL, USBD_Info.CtrlPkSiz, 0, 0, 0);  // Control In
65     USBD_EPConfig(ep_reg++, 0, USB_EP_OUT, USB_EP_CTRL, USBD_Info.CtrlPkSiz, 0, 0, 0);  // Control Out
66 
67     while(pCfg < (USBD_Info.DescConfig + total_len))
68     {
69         switch(pCfg[1])
70         {
71         case USB_DESC_CONFIG:
72             cfg  = pCfg[5];
73             break;
74 
75         case USB_DESC_INTERFACE:
76             intf = pCfg[2];
77             alt  = pCfg[3];
78             break;
79 
80         case USB_DESC_ENDPOINT:
81             ep_nbr  = pCfg[2] & 0x0F;
82             ep_dir  = pCfg[2] & USB_EP_IN;
83             ep_type = pCfg[3] & 0x03;
84             ep_pksz = pCfg[4] + (pCfg[5] << 8);
85 
86             USBD_EPConfig(ep_reg++, ep_nbr, ep_dir, ep_type, ep_pksz, cfg, intf, alt);
87 
88             epie |= (1 << ep_nbr) << (ep_dir ? 0 : 16);
89             break;
90         }
91 
92         pCfg += pCfg[0];
93     }
94 
95     USBD->FFTHR = (0xFFF << 16) | (0x000 << 0);  // 无用
96 
97     USBD->DEVCR = (USBD_Info.Speed << USBD_DEVCR_SPEED_Pos)  |
98                   (1               << USBD_DEVCR_DEVICE_Pos) |
99                   (1               << USBD_DEVCR_CSRDONE_Pos);
100 
101     USBD->DEVIE = (1 << USBD_DEVIE_RST_Pos)   |
102                   (1 << USBD_DEVIE_SETUP_Pos) |
103                   (1 << USBD_DEVIE_SETCFG_Pos);
104 
105     USBD->EPIE = epie;
106 
107     SYS->USBPHYCR &= ~SYS_USBPHYCR_OPMODE_Msk;
108     SYS->USBPHYCR |= (0 << SYS_USBPHYCR_OPMODE_Pos);    //Normal Operation
109 }
110 
111 
112 /******************************************************************************************************************************************
113 * 函数名称: USBD_EPConfig()
114 * 功能说明: USB Device Endpoint Configure
115 * 输    入: uint8_t ep_reg        Endpoint Register
116 *           uint8_t ep_nbr      Endpoint Number used by host
117 *           uint8_t ep_dir      Endpoint Direction, 0 Out  1 In
118 *           uint8_t ep_type     Endpoint Type,      0 Control   1  Isochronous   2 Bulk   3 Interrupt
119 *           uint16_t ep_pksz    Maximum packet size in byte
120 *           uint8_t cfg         Configuration number to which this endpoint belongs
121 *           uint8_t intf        Interface number to which this endpoint belongs
122 *           uint8_t alt         Alternate setting to which this endpoint belongs
123 * 输    出: 无
124 * 注意事项: 无
125 ******************************************************************************************************************************************/
USBD_EPConfig(uint8_t ep_reg,uint8_t ep_nbr,uint8_t ep_dir,uint8_t ep_type,uint16_t ep_pksz,uint8_t cfg,uint8_t intf,uint8_t alt)126 void USBD_EPConfig(uint8_t ep_reg, uint8_t ep_nbr, uint8_t ep_dir, uint8_t ep_type, uint16_t ep_pksz, uint8_t cfg, uint8_t intf, uint8_t alt)
127 {
128     ep_dir = ep_dir ? 1 : 0;    // for USB_EP_IN、USB_EP_OUT
129 
130     USBD->EPCFG[ep_reg] = (ep_nbr  << USBD_EPCFG_EPNR_Pos) |
131                           (ep_dir  << USBD_EPCFG_DIR_Pos)  |
132                           (ep_type << USBD_EPCFG_TYPE_Pos) |
133                           (cfg     << USBD_EPCFG_CFG_Pos)  |
134                           (intf    << USBD_EPCFG_INTF_Pos) |
135                           (alt     << USBD_EPCFG_ALT_Pos)  |
136                           (ep_pksz << USBD_EPCFG_PKSZ_Pos);
137 
138     if(ep_dir == USB_EP_OUT)
139     {
140         USBD->OUTEP[ep_nbr].RXCR = 0;
141         USBD->OUTEP[ep_nbr].RXCR = USBD_RXCR_FLUSHFF_Msk;
142     }
143     else
144     {
145         USBD->INEP[ep_nbr].TXCR = 0;
146         USBD->INEP[ep_nbr].TXCR = USBD_TXCR_FLUSHFF_Msk;
147     }
148 }
149 
150 
151 /******************************************************************************************************************************************
152 * 函数名称: USBD_Open()
153 * 功能说明: USB Device 打开
154 * 输    入: 无
155 * 输    出: 无
156 * 注意事项: 无
157 ******************************************************************************************************************************************/
USBD_Open(void)158 void USBD_Open(void)
159 {
160     NVIC_EnableIRQ(USB_IRQn);
161 }
162 
163 /******************************************************************************************************************************************
164 * 函数名称: USBD_Close()
165 * 功能说明: USB Device 关闭
166 * 输    入: 无
167 * 输    出: 无
168 * 注意事项: 无
169 ******************************************************************************************************************************************/
USBD_Close(void)170 void USBD_Close(void)
171 {
172     NVIC_DisableIRQ(USB_IRQn);
173 }
174 
175 
176 void USBD_StandardRequest(USB_Setup_Packet_t * pSetup);
177 void USBD_GetDescriptor(USB_Setup_Packet_t * pSetup);
178 
179 static USB_Setup_Packet_t Setup_Packet;
180 USB_Setup_Packet_t * pUSB_Setup = &Setup_Packet;
181 /******************************************************************************************************************************************
182 * 函数名称: USBD_ProcessSetupPacket()
183 * 功能说明: 处理Setup包
184 * 输    入: 无
185 * 输    出: 无
186 * 注意事项: 无
187 ******************************************************************************************************************************************/
USBD_ProcessSetupPacket(void)188 void USBD_ProcessSetupPacket(void)
189 {
190     ((volatile uint32_t *)pUSB_Setup)[0] = USBD->SETUPD1;
191     ((volatile uint32_t *)pUSB_Setup)[1] = USBD->SETUPD2;
192 
193     switch(pUSB_Setup->bRequestType & 0x60)
194     {
195     case USB_REQ_STANDARD:
196         USBD_StandardRequest(pUSB_Setup);
197         break;
198 
199     case USB_REQ_CLASS:
200         if(USBD_Info.pClassRequest_Callback != NULL)
201         {
202             USBD_Info.pClassRequest_Callback(pUSB_Setup);
203         }
204         break;
205 
206     case USB_REQ_VENDOR:
207         if(USBD_Info.pVendorRequest_Callback != NULL)
208         {
209             USBD_Info.pVendorRequest_Callback(pUSB_Setup);
210         }
211         break;
212 
213     default:
214         /* Setup error, stall the device */
215         USBD_Stall0();
216         break;
217     }
218 }
219 
220 /******************************************************************************************************************************************
221 * 函数名称: USBD_StandardRequest()
222 * 功能说明: 处理标准请求
223 * 输    入: 无
224 * 输    出: 无
225 * 注意事项: GetDescriptor、SetDescriptor、SyncFrame之外的标准命令USB模块自动处理,无需用户代码参与
226 ******************************************************************************************************************************************/
USBD_StandardRequest(USB_Setup_Packet_t * pSetup)227 void USBD_StandardRequest(USB_Setup_Packet_t * pSetup)
228 {
229     if(pSetup->bRequestType & 0x80)     // Device to host
230     {
231         switch(pSetup->bRequest)
232         {
233         case USB_GET_DESCRIPTOR:
234             USBD_GetDescriptor(pSetup);
235 
236             /* Status stage */
237             USBD_RxReady(0);
238             break;
239 
240         default:
241             /* Setup error, stall the device */
242             USBD_Stall0();
243             break;
244         }
245     }
246     else                                // Host to device
247     {
248         switch(pSetup->bRequest)
249         {
250         default:
251             /* Setup error, stall the device */
252             USBD_Stall0();
253             break;
254         }
255     }
256 }
257 
258 /******************************************************************************************************************************************
259 * 函数名称: USBD_GetDescriptor()
260 * 功能说明: 处理标准请求GetDescriptor
261 * 输    入: 无
262 * 输    出: 无
263 * 注意事项: 无
264 ******************************************************************************************************************************************/
USBD_GetDescriptor(USB_Setup_Packet_t * pSetup)265 void USBD_GetDescriptor(USB_Setup_Packet_t * pSetup)
266 {
267 #define min(a, b)   ((a)<(b) ? (a) : (b))
268 
269     switch(pSetup->wValue >> 8)
270     {
271     case USB_DESC_DEVICE:
272         USBD_PrepareCtrlIn(USBD_Info.DescDevice, min(pSetup->wLength, USBD_Info.DescDevice[0]));
273         break;
274 
275     case USB_DESC_CONFIG:
276     {
277         uint16_t total_len = USBD_Info.DescConfig[2] + (USBD_Info.DescConfig[3] << 8);
278         USBD_PrepareCtrlIn(USBD_Info.DescConfig, min(pSetup->wLength, total_len));
279         break;
280     }
281 
282     case USB_DESC_STRING:
283     {
284         uint8_t index = pSetup->wValue & 0xFF;
285         if(index < 6)
286         {
287             USBD_PrepareCtrlIn(USBD_Info.DescString[index], min(pSetup->wLength, USBD_Info.DescString[index][0]));
288         }
289         else if((index == 0xEE) && USBD_Info.DescOSString)
290         {
291             USBD_PrepareCtrlIn(USBD_Info.DescOSString, min(pSetup->wLength, USBD_Info.DescOSString[0]));
292         }
293         else
294         {
295             /* Not support. Reply STALL. */
296             USBD_Stall0();
297         }
298         break;
299     }
300 
301     case USB_DESC_BOS:
302     {
303         uint16_t total_len = USBD_Info.DescBOS[2] + (USBD_Info.DescBOS[3] << 8);
304         USBD_PrepareCtrlIn(USBD_Info.DescBOS, min(pSetup->wLength, total_len));
305         break;
306     }
307 
308     case USB_DESC_HID:
309     {
310         uint8_t  index   = pSetup->wIndex & 0xFF;
311         uint16_t offset  = USBD_Info.DescHIDOffset[index];
312         uint8_t *descHID = &USBD_Info.DescConfig[offset];
313         USBD_PrepareCtrlIn(descHID, min(pSetup->wLength, descHID[0]));
314         break;
315     }
316 
317     case USB_DESC_HID_RPT:
318     {
319         uint8_t  index   = pSetup->wIndex & 0xFF;
320         uint16_t offset  = USBD_Info.DescHIDOffset[index];
321         uint8_t *descHID = &USBD_Info.DescConfig[offset];
322         uint16_t report_len = descHID[7] + (descHID[8] << 8);
323         USBD_PrepareCtrlIn(USBD_Info.DescHIDReport[index], min(pSetup->wLength, report_len));
324         break;
325     }
326 
327     default:
328         /* Not support. Reply STALL.*/
329         USBD_Stall0();
330         break;
331     }
332 }
333 
334 /******************************************************************************************************************************************
335 * 函数名称: USBD_PrepareCtrlIn()
336 * 功能说明: Prepare the first Control IN pipe
337 * 输    入: 无
338 * 输    出: 无
339 * 注意事项: 无
340 ******************************************************************************************************************************************/
USBD_PrepareCtrlIn(uint8_t buf[],uint32_t size)341 void USBD_PrepareCtrlIn(uint8_t buf[], uint32_t size)
342 {
343     CtrlIn_Ptr = buf;
344     CtrlIn_Size = size;
345 
346     USBD_CtrlIn();
347 }
348 
349 /******************************************************************************************************************************************
350 * 函数名称: USBD_CtrlIn()
351 * 功能说明: Repeat Control IN pipe. This function processes the remained data of Control IN transfer
352 * 输    入: 无
353 * 输    出: 无
354 * 注意事项: 无
355 ******************************************************************************************************************************************/
USBD_CtrlIn(void)356 void USBD_CtrlIn(void)
357 {
358     static uint8_t ZeroLenPk = 0;
359 
360     if(CtrlIn_Size)
361     {
362         /* Process remained data */
363         if(CtrlIn_Size > USBD_Info.CtrlPkSiz)
364         {
365             USBD_TxWrite(0, CtrlIn_Ptr, USBD_Info.CtrlPkSiz);
366 
367             CtrlIn_Ptr += USBD_Info.CtrlPkSiz;
368             CtrlIn_Size -= USBD_Info.CtrlPkSiz;
369         }
370         else
371         {
372             USBD_TxWrite(0, CtrlIn_Ptr, CtrlIn_Size);
373 
374             if(CtrlIn_Size == USBD_Info.CtrlPkSiz)
375             {
376                 ZeroLenPk = 1;
377             }
378 
379             CtrlIn_Ptr = 0;
380             CtrlIn_Size = 0;
381         }
382     }
383     else
384     {
385         /* For the case of data size is integral times maximum packet size */
386         if(ZeroLenPk)
387         {
388             ZeroLenPk = 0;
389             USBD_TxWrite(0, 0, 0);
390         }
391     }
392 }
393 
394 /******************************************************************************************************************************************
395 * 函数名称: USBD_PrepareCtrlOut()
396 * 功能说明: Prepare the first Control OUT pipe
397 * 输    入: 无
398 * 输    出: 无
399 * 注意事项: 无
400 ******************************************************************************************************************************************/
USBD_PrepareCtrlOut(uint8_t * buf,uint32_t size)401 void USBD_PrepareCtrlOut(uint8_t *buf, uint32_t size)
402 {
403     CtrlOut_Ptr = buf;
404     CtrlOut_Size = 0u;
405     CtrlOut_Limit = size;
406 
407     USBD_RxReady(0);
408 }
409 
410 /******************************************************************************************************************************************
411 * 函数名称: USBD_CtrlOut()
412 * 功能说明: Repeat Control OUT pipe. This function processes the successive Control OUT transfer
413 * 输    入: 无
414 * 输    出: 无
415 * 注意事项: 无
416 ******************************************************************************************************************************************/
USBD_CtrlOut(void)417 void USBD_CtrlOut(void)
418 {
419     if(CtrlOut_Size < CtrlOut_Limit)
420     {
421         uint16_t size = USBD_RxRead(CtrlOut_Ptr, CtrlOut_Limit - CtrlOut_Size);
422 
423         CtrlOut_Ptr += size;
424         CtrlOut_Size += size;
425 
426         if(CtrlOut_Size < CtrlOut_Limit)
427         {
428             USBD_RxReady(0);
429         }
430     }
431 }
432 
433 
434 /******************************************************************************************************************************************
435 * 函数名称: USBD_TxWrite()
436 * 功能说明: 将要发送到主机的数据写入端点的FIFO
437 * 输    入: uint8_t  epnr         endpoint number
438 *           uint8_t *data           要写入FIFO的数据
439 *           uint16_t size           要写入数据的个数
440 * 输    出: 无
441 * 注意事项: 无
442 ******************************************************************************************************************************************/
USBD_TxWrite(uint8_t epnr,uint8_t * data,uint16_t size)443 void USBD_TxWrite(uint8_t epnr, uint8_t *data, uint16_t size)
444 {
445     __disable_irq();
446 
447     USBD->INEP[epnr].TXCR = (1 << USBD_TXCR_FLUSHFF_Pos);
448 
449     USBD->INEP[epnr].TXTRSZ = size;
450     if(size) USBD_memcpy((uint8_t *)USBD->TXBUF[epnr], data, size);
451     USBD->INEP[epnr].TXCR = (1 << USBD_TXCR_FFRDY_Pos);
452 
453     __enable_irq();
454 }
455 
456 /******************************************************************************************************************************************
457 * 函数名称: USBD_RxRead()
458 * 功能说明: 读取接收到的数据
459 * 输    入: uint8_t *buff         读取到的数据存入buff
460 *           uint16_t size           buff大小
461 * 输    出: uint16_t              实际读取到数据的个数
462 * 注意事项: 无
463 ******************************************************************************************************************************************/
USBD_RxRead(uint8_t * buff,uint16_t size)464 uint16_t USBD_RxRead(uint8_t *buff, uint16_t size)
465 {
466     __disable_irq();
467 
468     uint16_t real_size = (USBD->RXSR & USBD_RXSR_TRSZ_Msk) >> USBD_RXSR_TRSZ_Pos;
469 
470     if(size > real_size)
471         size = real_size;
472 
473     USBD_memcpy(buff, (uint8_t *)USBD->RXBUF, size);
474 
475     __enable_irq();
476 
477     return size;
478 }
479 
480 /******************************************************************************************************************************************
481 * 函数名称: USBD_memcpy()
482 * 功能说明: 访问 USB Buffer 的 memcpy
483 * 输    入: void *destin          目的地址
484 *           void *source            源地址
485 *           uint32_t nByte          拷贝字节数
486 * 输    出: 无
487 * 注意事项: 访问 USB Buffer 必须使用 USBD_memcpy,不能使用库函数 memcpy
488 ******************************************************************************************************************************************/
USBD_memcpy(uint8_t * destin,uint8_t * source,uint32_t nByte)489 void USBD_memcpy(uint8_t *destin, uint8_t *source, uint32_t nByte)
490 {
491     while(nByte > 3)
492     {
493         *((uint32_t *)destin) = *((uint32_t *)source);
494         destin += 4;
495         source += 4;
496         nByte  -= 4;
497     }
498 
499     while(nByte > 1)
500     {
501         *((uint16_t *)destin) = *((uint16_t *)source);
502         destin += 2;
503         source += 2;
504         nByte  -= 2;
505     }
506 
507     while(nByte > 0)
508     {
509         *destin = *source;
510         destin += 1;
511         source += 1;
512         nByte  -= 1;
513     }
514 }
515