1 /*
2 * Copyright (c) 2022, sakumisu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "usbd_core.h"
7
8 #if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG)
9 #error "fsdev cannot enable USB_DBG_LOG"
10 #endif
11
12 #ifndef CONFIG_USBDEV_FSDEV_PMA_ACCESS
13 #error "please define CONFIG_USBDEV_FSDEV_PMA_ACCESS in usb_config.h"
14 #endif
15
16 #define PMA_ACCESS CONFIG_USBDEV_FSDEV_PMA_ACCESS
17 #include "usb_fsdev_reg.h"
18
19 #ifndef CONFIG_USB_FSDEV_RAM_SIZE
20 #define CONFIG_USB_FSDEV_RAM_SIZE 512
21 #endif
22
23 #undef CONFIG_USBDEV_EP_NUM
24 #define CONFIG_USBDEV_EP_NUM 8
25
26 #define USB ((USB_TypeDef *)g_usbdev_bus[0].reg_base)
27
28 #define USB_BTABLE_SIZE (8 * CONFIG_USBDEV_EP_NUM)
29
30 static void fsdev_write_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
31 static void fsdev_read_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
32
33 /* Endpoint state */
34 struct fsdev_ep_state {
35 uint16_t ep_mps; /* Endpoint max packet size */
36 uint8_t ep_type; /* Endpoint type */
37 uint8_t ep_stalled; /* Endpoint stall flag */
38 uint8_t ep_enable; /* Endpoint enable */
39 uint16_t ep_pma_buf_len; /* Previously allocated buffer size */
40 uint16_t ep_pma_addr; /* ep pmd allocated addr */
41 uint8_t *xfer_buf;
42 uint32_t xfer_len;
43 uint32_t actual_xfer_len;
44 };
45
46 /* Driver state */
47 struct fsdev_udc {
48 struct usb_setup_packet setup;
49 volatile uint8_t dev_addr; /*!< USB Address */
50 volatile uint32_t pma_offset; /*!< pma offset */
51 struct fsdev_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
52 struct fsdev_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
53 } g_fsdev_udc;
54
usb_dc_low_level_init(void)55 __WEAK void usb_dc_low_level_init(void)
56 {
57 }
58
usb_dc_low_level_deinit(void)59 __WEAK void usb_dc_low_level_deinit(void)
60 {
61 }
62
usb_dc_init(uint8_t busid)63 int usb_dc_init(uint8_t busid)
64 {
65 usb_dc_low_level_init();
66
67 /* Init Device */
68 /* CNTR_FRES = 1 */
69 USB->CNTR = (uint16_t)USB_CNTR_FRES;
70
71 /* CNTR_FRES = 0 */
72 USB->CNTR = 0U;
73
74 /* Clear pending interrupts */
75 USB->ISTR = 0U;
76
77 /*Set Btable Address*/
78 USB->BTABLE = BTABLE_ADDRESS;
79
80 uint32_t winterruptmask;
81
82 /* Set winterruptmask variable */
83 winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
84 USB_CNTR_SUSPM | USB_CNTR_ERRM |
85 USB_CNTR_ESOFM | USB_CNTR_RESETM;
86
87 #ifdef CONFIG_USBDEV_SOF_ENABLE
88 winterruptmask |= USB_CNTR_SOFM;
89 #endif
90
91 /* Set interrupt mask */
92 USB->CNTR = (uint16_t)winterruptmask;
93
94 /* Enabling DP Pull-UP bit to Connect internal PU resistor on USB DP line */
95 USB->BCDR |= (uint16_t)USB_BCDR_DPPU;
96
97 return 0;
98 }
99
usb_dc_deinit(uint8_t busid)100 int usb_dc_deinit(uint8_t busid)
101 {
102 /* disable all interrupts and force USB reset */
103 USB->CNTR = (uint16_t)USB_CNTR_FRES;
104
105 /* clear interrupt status register */
106 USB->ISTR = 0U;
107
108 /* switch-off device */
109 USB->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
110
111 usb_dc_low_level_deinit();
112 return 0;
113 }
114
usbd_set_address(uint8_t busid,const uint8_t addr)115 int usbd_set_address(uint8_t busid, const uint8_t addr)
116 {
117 if (addr == 0U) {
118 /* set device address and enable function */
119 USB->DADDR = (uint16_t)USB_DADDR_EF;
120 }
121
122 g_fsdev_udc.dev_addr = addr;
123 return 0;
124 }
125
usbd_set_remote_wakeup(uint8_t busid)126 int usbd_set_remote_wakeup(uint8_t busid)
127 {
128 return -1;
129 }
130
usbd_get_port_speed(uint8_t busid)131 uint8_t usbd_get_port_speed(uint8_t busid)
132 {
133 return USB_SPEED_FULL;
134 }
135
usbd_ep_open(uint8_t busid,const struct usb_endpoint_descriptor * ep)136 int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
137 {
138 uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
139
140 USB_ASSERT_MSG(ep_idx < CONFIG_USBDEV_EP_NUM, "Ep addr %02x overflow", ep->bEndpointAddress);
141 USB_ASSERT_MSG(USB_GET_ENDPOINT_TYPE(ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS, "iso endpoint not support in fsdev");
142
143 uint16_t wEpRegVal;
144
145 /* initialize Endpoint */
146 switch (USB_GET_ENDPOINT_TYPE(ep->bmAttributes)) {
147 case USB_ENDPOINT_TYPE_CONTROL:
148 wEpRegVal = USB_EP_CONTROL;
149 break;
150
151 case USB_ENDPOINT_TYPE_BULK:
152 wEpRegVal = USB_EP_BULK;
153 break;
154
155 case USB_ENDPOINT_TYPE_INTERRUPT:
156 wEpRegVal = USB_EP_INTERRUPT;
157 break;
158
159 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
160 wEpRegVal = USB_EP_ISOCHRONOUS;
161 break;
162
163 default:
164 return -1;
165 }
166
167 PCD_SET_EPTYPE(USB, ep_idx, wEpRegVal);
168
169 PCD_SET_EP_ADDRESS(USB, ep_idx, ep_idx);
170 if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
171 g_fsdev_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
172 g_fsdev_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
173 g_fsdev_udc.out_ep[ep_idx].ep_enable = true;
174 if (g_fsdev_udc.out_ep[ep_idx].ep_mps > g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len) {
175 USB_ASSERT_MSG((g_fsdev_udc.pma_offset + g_fsdev_udc.out_ep[ep_idx].ep_mps) <= CONFIG_USB_FSDEV_RAM_SIZE,
176 "Ep pma %02x overflow", ep->bEndpointAddress);
177
178 g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
179 g_fsdev_udc.out_ep[ep_idx].ep_pma_addr = g_fsdev_udc.pma_offset;
180 /*Set the endpoint Receive buffer address */
181 PCD_SET_EP_RX_ADDRESS(USB, ep_idx, g_fsdev_udc.pma_offset);
182 g_fsdev_udc.pma_offset += USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
183 }
184 /*Set the endpoint Receive buffer counter*/
185 PCD_SET_EP_RX_CNT(USB, ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
186 PCD_CLEAR_RX_DTOG(USB, ep_idx);
187 } else {
188 g_fsdev_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
189 g_fsdev_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
190 g_fsdev_udc.in_ep[ep_idx].ep_enable = true;
191 if (g_fsdev_udc.in_ep[ep_idx].ep_mps > g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len) {
192 USB_ASSERT_MSG((g_fsdev_udc.pma_offset + g_fsdev_udc.in_ep[ep_idx].ep_mps) <= CONFIG_USB_FSDEV_RAM_SIZE,
193 "Ep pma %02x overflow", ep->bEndpointAddress);
194
195 g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
196 g_fsdev_udc.in_ep[ep_idx].ep_pma_addr = g_fsdev_udc.pma_offset;
197 /*Set the endpoint Transmit buffer address */
198 PCD_SET_EP_TX_ADDRESS(USB, ep_idx, g_fsdev_udc.pma_offset);
199 g_fsdev_udc.pma_offset += USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
200 }
201
202 PCD_CLEAR_TX_DTOG(USB, ep_idx);
203 if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
204 /* Configure NAK status for the Endpoint */
205 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_NAK);
206 } else {
207 /* Configure TX Endpoint to disabled state */
208 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_DIS);
209 }
210 }
211 return 0;
212 }
213
usbd_ep_close(uint8_t busid,const uint8_t ep)214 int usbd_ep_close(uint8_t busid, const uint8_t ep)
215 {
216 uint8_t ep_idx = USB_EP_GET_IDX(ep);
217
218 if (USB_EP_DIR_IS_OUT(ep)) {
219 PCD_CLEAR_RX_DTOG(USB, ep_idx);
220
221 /* Configure DISABLE status for the Endpoint*/
222 PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_DIS);
223 } else {
224 PCD_CLEAR_TX_DTOG(USB, ep_idx);
225
226 /* Configure DISABLE status for the Endpoint*/
227 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_DIS);
228 }
229 return 0;
230 }
231
usbd_ep_set_stall(uint8_t busid,const uint8_t ep)232 int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
233 {
234 uint8_t ep_idx = USB_EP_GET_IDX(ep);
235
236 if (USB_EP_DIR_IS_OUT(ep)) {
237 PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_STALL);
238 } else {
239 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_STALL);
240 }
241 return 0;
242 }
243
usbd_ep_clear_stall(uint8_t busid,const uint8_t ep)244 int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
245 {
246 uint8_t ep_idx = USB_EP_GET_IDX(ep);
247
248 if (USB_EP_DIR_IS_OUT(ep)) {
249 PCD_CLEAR_RX_DTOG(USB, ep_idx);
250 /* Configure VALID status for the Endpoint */
251 PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_VALID);
252 } else {
253 PCD_CLEAR_TX_DTOG(USB, ep_idx);
254
255 if (g_fsdev_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
256 /* Configure NAK status for the Endpoint */
257 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_NAK);
258 }
259 }
260 return 0;
261 }
262
usbd_ep_is_stalled(uint8_t busid,const uint8_t ep,uint8_t * stalled)263 int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
264 {
265 uint8_t ep_idx = USB_EP_GET_IDX(ep);
266
267 if (USB_EP_DIR_IS_OUT(ep)) {
268 if (PCD_GET_EP_RX_STATUS(USB, ep_idx) & USB_EP_RX_STALL) {
269 *stalled = 1;
270 } else {
271 *stalled = 0;
272 }
273 } else {
274 if (PCD_GET_EP_TX_STATUS(USB, ep_idx) & USB_EP_TX_STALL) {
275 *stalled = 1;
276 } else {
277 *stalled = 0;
278 }
279 }
280 return 0;
281 }
282
usbd_ep_start_write(uint8_t busid,const uint8_t ep,const uint8_t * data,uint32_t data_len)283 int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
284 {
285 uint8_t ep_idx = USB_EP_GET_IDX(ep);
286
287 if (!data && data_len) {
288 return -1;
289 }
290
291 if (!g_fsdev_udc.in_ep[ep_idx].ep_enable) {
292 return -2;
293 }
294
295 g_fsdev_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
296 g_fsdev_udc.in_ep[ep_idx].xfer_len = data_len;
297 g_fsdev_udc.in_ep[ep_idx].actual_xfer_len = 0;
298
299 data_len = MIN(data_len, g_fsdev_udc.in_ep[ep_idx].ep_mps);
300
301 fsdev_write_pma(USB, (uint8_t *)data, g_fsdev_udc.in_ep[ep_idx].ep_pma_addr, (uint16_t)data_len);
302 PCD_SET_EP_TX_CNT(USB, ep_idx, (uint16_t)data_len);
303 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_VALID);
304
305 return 0;
306 }
307
usbd_ep_start_read(uint8_t busid,const uint8_t ep,uint8_t * data,uint32_t data_len)308 int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
309 {
310 uint8_t ep_idx = USB_EP_GET_IDX(ep);
311
312 if (!data && data_len) {
313 return -1;
314 }
315 if (!g_fsdev_udc.out_ep[ep_idx].ep_enable) {
316 return -2;
317 }
318
319 g_fsdev_udc.out_ep[ep_idx].xfer_buf = data;
320 g_fsdev_udc.out_ep[ep_idx].xfer_len = data_len;
321 g_fsdev_udc.out_ep[ep_idx].actual_xfer_len = 0;
322
323 PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_VALID);
324
325 return 0;
326 }
327
USBD_IRQHandler(uint8_t busid)328 void USBD_IRQHandler(uint8_t busid)
329 {
330 uint16_t wIstr, wEPVal;
331 uint8_t ep_idx;
332 uint8_t read_count;
333 uint16_t write_count;
334 uint16_t store_ep[8];
335
336 wIstr = USB->ISTR;
337 if (wIstr & USB_ISTR_CTR) {
338 while ((USB->ISTR & USB_ISTR_CTR) != 0U) {
339 wIstr = USB->ISTR;
340
341 /* extract highest priority endpoint number */
342 ep_idx = (uint8_t)(wIstr & USB_ISTR_EP_ID);
343
344 if (ep_idx == 0U) {
345 if ((wIstr & USB_ISTR_DIR) == 0U) {
346 PCD_CLEAR_TX_EP_CTR(USB, ep_idx);
347
348 write_count = PCD_GET_EP_TX_CNT(USB, ep_idx);
349
350 g_fsdev_udc.in_ep[ep_idx].xfer_buf += write_count;
351 g_fsdev_udc.in_ep[ep_idx].xfer_len -= write_count;
352 g_fsdev_udc.in_ep[ep_idx].actual_xfer_len += write_count;
353
354 usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_fsdev_udc.in_ep[ep_idx].actual_xfer_len);
355
356 if (g_fsdev_udc.setup.wLength == 0) {
357 /* In status, start reading setup */
358 usbd_ep_start_read(0, 0x00, NULL, 0);
359 } else if (g_fsdev_udc.setup.wLength && ((g_fsdev_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
360 /* In status, start reading setup */
361 usbd_ep_start_read(0, 0x00, NULL, 0);
362 }
363
364 if ((g_fsdev_udc.dev_addr > 0U) && (write_count == 0U)) {
365 USB->DADDR = ((uint16_t)g_fsdev_udc.dev_addr | USB_DADDR_EF);
366 g_fsdev_udc.dev_addr = 0U;
367 }
368
369 } else {
370 wEPVal = PCD_GET_ENDPOINT(USB, ep_idx);
371
372 if ((wEPVal & USB_EP_SETUP) != 0U) {
373 PCD_CLEAR_RX_EP_CTR(USB, ep_idx);
374
375 read_count = PCD_GET_EP_RX_CNT(USB, ep_idx);
376 fsdev_read_pma(USB, (uint8_t *)&g_fsdev_udc.setup, g_fsdev_udc.out_ep[ep_idx].ep_pma_addr, (uint16_t)read_count);
377
378 usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_fsdev_udc.setup);
379
380 } else if ((wEPVal & USB_EP_CTR_RX) != 0U) {
381 PCD_CLEAR_RX_EP_CTR(USB, ep_idx);
382
383 read_count = PCD_GET_EP_RX_CNT(USB, ep_idx);
384
385 fsdev_read_pma(USB, g_fsdev_udc.out_ep[ep_idx].xfer_buf, g_fsdev_udc.out_ep[ep_idx].ep_pma_addr, (uint16_t)read_count);
386
387 g_fsdev_udc.out_ep[ep_idx].xfer_buf += read_count;
388 g_fsdev_udc.out_ep[ep_idx].xfer_len -= read_count;
389 g_fsdev_udc.out_ep[ep_idx].actual_xfer_len += read_count;
390
391 usbd_event_ep_out_complete_handler(0, ep_idx, g_fsdev_udc.out_ep[ep_idx].actual_xfer_len);
392
393 if (read_count == 0) {
394 /* Out status, start reading setup */
395 usbd_ep_start_read(0, 0x00, NULL, 0);
396 }
397 }
398 }
399 } else {
400 wEPVal = PCD_GET_ENDPOINT(USB, ep_idx);
401
402 if ((wEPVal & USB_EP_CTR_RX) != 0U) {
403 PCD_CLEAR_RX_EP_CTR(USB, ep_idx);
404 read_count = PCD_GET_EP_RX_CNT(USB, ep_idx);
405 fsdev_read_pma(USB, g_fsdev_udc.out_ep[ep_idx].xfer_buf, g_fsdev_udc.out_ep[ep_idx].ep_pma_addr, (uint16_t)read_count);
406 g_fsdev_udc.out_ep[ep_idx].xfer_buf += read_count;
407 g_fsdev_udc.out_ep[ep_idx].xfer_len -= read_count;
408 g_fsdev_udc.out_ep[ep_idx].actual_xfer_len += read_count;
409
410 if ((read_count < g_fsdev_udc.out_ep[ep_idx].ep_mps) ||
411 (g_fsdev_udc.out_ep[ep_idx].xfer_len == 0)) {
412 usbd_event_ep_out_complete_handler(0, ep_idx, g_fsdev_udc.out_ep[ep_idx].actual_xfer_len);
413 } else {
414 PCD_SET_EP_RX_STATUS(USB, ep_idx, USB_EP_RX_VALID);
415 }
416 }
417
418 if ((wEPVal & USB_EP_CTR_TX) != 0U) {
419 PCD_CLEAR_TX_EP_CTR(USB, ep_idx);
420 write_count = PCD_GET_EP_TX_CNT(USB, ep_idx);
421
422 g_fsdev_udc.in_ep[ep_idx].xfer_buf += write_count;
423 g_fsdev_udc.in_ep[ep_idx].xfer_len -= write_count;
424 g_fsdev_udc.in_ep[ep_idx].actual_xfer_len += write_count;
425
426 if (g_fsdev_udc.in_ep[ep_idx].xfer_len == 0) {
427 usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_fsdev_udc.in_ep[ep_idx].actual_xfer_len);
428 } else {
429 write_count = MIN(g_fsdev_udc.in_ep[ep_idx].xfer_len, g_fsdev_udc.in_ep[ep_idx].ep_mps);
430 fsdev_write_pma(USB, g_fsdev_udc.in_ep[ep_idx].xfer_buf, g_fsdev_udc.in_ep[ep_idx].ep_pma_addr, (uint16_t)write_count);
431 PCD_SET_EP_TX_CNT(USB, ep_idx, write_count);
432 PCD_SET_EP_TX_STATUS(USB, ep_idx, USB_EP_TX_VALID);
433 }
434 }
435 }
436 }
437 }
438 if (wIstr & USB_ISTR_RESET) {
439 memset(&g_fsdev_udc, 0, sizeof(struct fsdev_udc));
440 g_fsdev_udc.pma_offset = USB_BTABLE_SIZE;
441 usbd_event_reset_handler(0);
442 /* start reading setup packet */
443 PCD_SET_EP_RX_STATUS(USB, 0, USB_EP_RX_VALID);
444 USB->ISTR &= (uint16_t)(~USB_ISTR_RESET);
445 }
446 if (wIstr & USB_ISTR_PMAOVR) {
447 USB->ISTR &= (uint16_t)(~USB_ISTR_PMAOVR);
448 }
449 if (wIstr & USB_ISTR_ERR) {
450 USB->ISTR &= (uint16_t)(~USB_ISTR_ERR);
451 }
452 if (wIstr & USB_ISTR_WKUP) {
453 USB->CNTR &= (uint16_t) ~(USB_CNTR_LP_MODE);
454 USB->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
455
456 USB->ISTR &= (uint16_t)(~USB_ISTR_WKUP);
457 }
458 if (wIstr & USB_ISTR_SUSP) {
459 /* WA: To Clear Wakeup flag if raised with suspend signal */
460
461 /* Store Endpoint register */
462 for (uint8_t i = 0U; i < 8U; i++) {
463 store_ep[i] = PCD_GET_ENDPOINT(USB, i);
464 }
465
466 /* FORCE RESET */
467 USB->CNTR |= (uint16_t)(USB_CNTR_FRES);
468
469 /* CLEAR RESET */
470 USB->CNTR &= (uint16_t)(~USB_CNTR_FRES);
471
472 /* wait for reset flag in ISTR */
473 while ((USB->ISTR & USB_ISTR_RESET) == 0U) {
474 }
475
476 /* Clear Reset Flag */
477 USB->ISTR &= (uint16_t)(~USB_ISTR_RESET);
478 /* Restore Registre */
479 for (uint8_t i = 0U; i < 8U; i++) {
480 PCD_SET_ENDPOINT(USB, i, store_ep[i]);
481 }
482
483 /* Force low-power mode in the macrocell */
484 USB->CNTR |= (uint16_t)USB_CNTR_FSUSP;
485
486 /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
487 USB->ISTR &= (uint16_t)(~USB_ISTR_SUSP);
488
489 USB->CNTR |= (uint16_t)USB_CNTR_LP_MODE;
490 }
491 #ifdef CONFIG_USBDEV_SOF_ENABLE
492 if (wIstr & USB_ISTR_SOF) {
493 USB->ISTR &= (uint16_t)(~USB_ISTR_SOF);
494 usbd_event_sof_handler(0);
495 }
496 #endif
497 if (wIstr & USB_ISTR_ESOF) {
498 USB->ISTR &= (uint16_t)(~USB_ISTR_ESOF);
499 }
500 }
501
fsdev_write_pma(USB_TypeDef * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)502 static void fsdev_write_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
503 {
504 uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
505 uint32_t BaseAddr = (uint32_t)USBx;
506 uint32_t i, temp1, temp2;
507 __IO uint16_t *pdwVal;
508 uint8_t *pBuf = pbUsrBuf;
509
510 pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
511
512 for (i = n; i != 0U; i--) {
513 temp1 = *pBuf;
514 pBuf++;
515 temp2 = temp1 | ((uint16_t)((uint16_t)*pBuf << 8));
516 *pdwVal = (uint16_t)temp2;
517 pdwVal++;
518
519 #if PMA_ACCESS > 1U
520 pdwVal++;
521 #endif
522
523 pBuf++;
524 }
525 }
526
527 /**
528 * @brief Copy data from packet memory area (PMA) to user memory buffer
529 * @param USBx USB peripheral instance register address.
530 * @param pbUsrBuf pointer to user memory area.
531 * @param wPMABufAddr address into PMA.
532 * @param wNBytes no. of bytes to be copied.
533 * @retval None
534 */
fsdev_read_pma(USB_TypeDef * USBx,uint8_t * pbUsrBuf,uint16_t wPMABufAddr,uint16_t wNBytes)535 static void fsdev_read_pma(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
536 {
537 uint32_t n = (uint32_t)wNBytes >> 1;
538 uint32_t BaseAddr = (uint32_t)USBx;
539 uint32_t i, temp;
540 __IO uint16_t *pdwVal;
541 uint8_t *pBuf = pbUsrBuf;
542
543 pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
544
545 for (i = n; i != 0U; i--) {
546 temp = *(__IO uint16_t *)pdwVal;
547 pdwVal++;
548 *pBuf = (uint8_t)((temp >> 0) & 0xFFU);
549 pBuf++;
550 *pBuf = (uint8_t)((temp >> 8) & 0xFFU);
551 pBuf++;
552
553 #if PMA_ACCESS > 1U
554 pdwVal++;
555 #endif
556 }
557
558 if ((wNBytes % 2U) != 0U) {
559 temp = *pdwVal;
560 *pBuf = (uint8_t)((temp >> 0) & 0xFFU);
561 }
562 }
563