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