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