1 /*
2 * SPDX-FileCopyrightText: 2016 STMicroelectronics
3 * SPDX-FileCopyrightText: 2019-2025 SiFli Technologies(Nanjing) Co., Ltd
4 *
5 * SPDX-License-Identifier: BSD-3-Clause AND Apache-2.0
6 */
7
8 #include "bf0_hal.h"
9 #include "bf0_hal_usb_common.h"
10
11
12 /** @addtogroup BF0_HAL_Driver
13 * @{
14 */
15
16 #if defined(HAL_PCD_MODULE_ENABLED)||defined(_SIFLI_DOXYGEN_)
17
18 #ifndef SF32LB55X
19 #define USB_TX_DMA_ENABLED 1
20 #define USB_RX_DMA_ENABLED 1
21 #endif
22
23 /** @defgroup PCD USB Device
24 * @brief PCD HAL module driver
25 * @{
26 */
27
28 /* Private typedef -----------------------------------------------------------*/
29 /* Private define ------------------------------------------------------------*/
30 /* Private macro -------------------------------------------------------------*/
31 /* Private variables ---------------------------------------------------------*/
32 /* Private function prototypes -----------------------------------------------*/
33 /** @defgroup PCD_Private_Functions PCD Private Functions
34 * @{
35 */
36 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
37 static const char *ep0_state_str(uint8_t state);
38 static uint8_t tx_packet_max = 0;
39
40 #define ep0_state_change(hpcd,new_state) \
41 { \
42 HAL_DBG_printf("EP0 State %s -> %s, line %d\r\n", ep0_state_str(hpcd->ep0_state), ep0_state_str(new_state), __LINE__); \
43 hpcd->ep0_state = new_state; \
44 }
45
46 /**
47 * @}
48 */
49
50 /* Exported functions --------------------------------------------------------*/
51 /** @defgroup PCD_Exported_Functions PCD Exported Functions
52 * @{
53 */
54
55 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
56 * @brief Initialization and Configuration functions
57 *
58 @verbatim
59 ===============================================================================
60 ##### Initialization and de-initialization functions #####
61 ===============================================================================
62 [..] This section provides functions allowing to:
63
64 @endverbatim
65 * @{
66 */
67
68 /**
69 * @brief Initializes the PCD according to the specified
70 * parameters in the PCD_InitTypeDef and create the associated handle.
71 * @param hpcd PCD handle
72 * @retval HAL status
73 */
74
HAL_PCD_Init(PCD_HandleTypeDef * hpcd)75 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
76 {
77 uint32_t i = 0U;
78
79
80 /* Check the PCD handle allocation */
81 if (hpcd == NULL)
82 {
83 return HAL_ERROR;
84 }
85
86 if (hpcd->State == HAL_PCD_STATE_RESET)
87 {
88 /* Allocate lock resource and initialize it */
89 hpcd->Lock = HAL_UNLOCKED;
90
91 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
92 HAL_PCD_MspInit(hpcd);
93 }
94
95 hpcd->State = HAL_PCD_STATE_BUSY;
96
97 /* Init endpoints structures */
98 for (i = 0U; i < hpcd->Init.dev_endpoints ; i++)
99 {
100 /* Init ep structure */
101 hpcd->IN_ep[i].is_in = 1U;
102 hpcd->IN_ep[i].num = i;
103 /* Control until ep is actvated */
104 hpcd->IN_ep[i].type = PCD_EP_TYPE_CTRL;
105 hpcd->IN_ep[i].maxpacket = 0U;
106 hpcd->IN_ep[i].xfer_buff = 0U;
107 hpcd->IN_ep[i].xfer_len = 0U;
108 }
109
110 for (i = 0U; i < hpcd->Init.dev_endpoints ; i++)
111 {
112 hpcd->OUT_ep[i].is_in = 0U;
113 hpcd->OUT_ep[i].num = i;
114 /* Control until ep is activated */
115 hpcd->OUT_ep[i].type = PCD_EP_TYPE_CTRL;
116 hpcd->OUT_ep[i].maxpacket = 0U;
117 hpcd->OUT_ep[i].xfer_buff = 0U;
118 hpcd->OUT_ep[i].xfer_len = 0U;
119 }
120
121 /* Init Device, Clear session*/
122 // hpcd->Instance->devctl |= USB_DEVCTL_SESSION;
123
124 // TODO: Turn on PHY???
125
126 /* , start software connection */
127 {
128 uint8_t power = hpcd->Instance->power;
129 //power &= ~USB_POWER_HSENAB;
130 power |= USB_POWER_SOFTCONN;
131 hpcd->Instance->power = power;
132 }
133
134
135 hpcd->USB_Address = 0U;
136 hpcd->State = HAL_PCD_STATE_READY;
137 ep0_state_change(hpcd, HAL_PCD_EP0_SETUP);
138 hpcd->phy_state = OTG_STATE_B_PERIPHERALS;
139
140 return HAL_OK;
141 }
142
143 /**
144 * @brief DeInitializes the PCD peripheral
145 * @param hpcd PCD handle
146 * @retval HAL status
147 */
HAL_PCD_DeInit(PCD_HandleTypeDef * hpcd)148 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
149 {
150 /* Check the PCD handle allocation */
151 if (hpcd == NULL)
152 {
153 return HAL_ERROR;
154 }
155
156 hpcd->State = HAL_PCD_STATE_BUSY;
157
158 /* Stop Device */
159 HAL_PCD_Stop(hpcd);
160
161 /* DeInit the low level hardware */
162 HAL_PCD_MspDeInit(hpcd);
163
164 hpcd->State = HAL_PCD_STATE_RESET;
165
166 return HAL_OK;
167 }
168
169 /**
170 * @brief Initializes the PCD MSP.
171 * @param hpcd PCD handle
172 * @retval None
173 */
HAL_PCD_MspInit(PCD_HandleTypeDef * hpcd)174 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
175 {
176 HAL_RCC_EnableModule(RCC_MOD_USBC);
177
178 #ifdef SF32LB58X
179 //hwp_usbc->utmicfg12 = hwp_usbc->utmicfg12 | 0x3; //set xo_clk_sel
180 hwp_usbc->utmicfg23 = 0xd8;
181 hwp_usbc->ldo25 = hwp_usbc->ldo25 | 0xa; //set psw_en and ldo25_en
182 HAL_Delay(1);
183 hwp_usbc->swcntl3 = 0x1; //set utmi_en for USB2.0
184 hwp_usbc->usbcfg = hwp_usbc->usbcfg | 0x40; //enable usb PLL.
185 #elif defined(SF32LB56X)||defined(SF32LB52X)
186 hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN;
187 #elif defined(SF32LB55X)
188 hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN;
189 #endif
190 }
191
192 /**
193 * @brief DeInitializes PCD MSP.
194 * @param hpcd PCD handle
195 * @retval None
196 */
HAL_PCD_MspDeInit(PCD_HandleTypeDef * hpcd)197 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
198 {
199 #ifdef SF32LB58X
200 hwp_usbc->usbcfg &= ~0x40; // Disable usb PLL.
201 hwp_usbc->swcntl3 = 0x0;
202 hwp_usbc->ldo25 &= ~0xa; // Disable psw_en and ldo25_en
203 #elif defined(SF32LB56X)||defined(SF32LB52X)
204 hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN);
205 #elif defined(SF32LB55X)
206 hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN);
207 #endif
208 /* reset USB to make DP change to PULLDOWN state */
209 hwp_hpsys_rcc->RSTR2 |= HPSYS_RCC_RSTR2_USBC;
210 HAL_Delay_us(100);
211 hwp_hpsys_rcc->RSTR2 &= ~HPSYS_RCC_RSTR2_USBC;
212 HAL_RCC_DisableModule(RCC_MOD_USBC);
213 }
214
215 /**
216 * @}
217 */
218
219 /** @defgroup PCD_Exported_Functions_Group2 IO operation functions
220 * @brief Data transfers functions
221 *
222 @verbatim
223 ===============================================================================
224 ##### IO operation functions #####
225 ===============================================================================
226 [..]
227 This subsection provides a set of functions allowing to manage the PCD data
228 transfers.
229
230 @endverbatim
231 * @{
232 */
233
234 /**
235 * @brief Start the USB device.
236 * @param hpcd PCD handle
237 * @retval HAL status
238 */
HAL_PCD_Start(PCD_HandleTypeDef * hpcd)239 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
240 {
241 /* Enabling DP Pull-Down bit to Connect internal pull-up on USB DP line */
242 /* TODO: ?????*/
243 HAL_PCD_EP_Open(hpcd, 0x00, 0x40, EP_TYPE_CTRL);
244 HAL_PCD_EP_Open(hpcd, 0x80, 0x40, EP_TYPE_CTRL);
245 HAL_DBG_printf("Enable IRQ %d\n", USBC_IRQn);
246 NVIC_EnableIRQ(USBC_IRQn);
247 __HAL_SYSCFG_Enable_USB();
248
249 return HAL_OK;
250 }
251
252 /**
253 * @brief Stop the USB device.
254 * @param hpcd PCD handle
255 * @retval HAL status
256 */
HAL_PCD_Stop(PCD_HandleTypeDef * hpcd)257 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
258 {
259 __HAL_LOCK(hpcd);
260
261 NVIC_DisableIRQ(USBC_IRQn);
262 HAL_PCD_EP_Close(hpcd, 0x00);
263 HAL_PCD_EP_Close(hpcd, 0x80);
264
265 __HAL_UNLOCK(hpcd);
266 return HAL_OK;
267 }
HAL_PCD_Get_RxbuffControl(uint8_t ep_num)268 __weak uint8_t HAL_PCD_Get_RxbuffControl(uint8_t ep_num)
269 {
270 return 0;
271 }
HAL_PCD_Set_RxbuffControl(uint8_t ep_num,uint8_t flag)272 __weak void HAL_PCD_Set_RxbuffControl(uint8_t ep_num, uint8_t flag)
273 {
274 }
HAL_PCD_Set_RxscrACK(uint8_t epnum)275 __weak void HAL_PCD_Set_RxscrACK(uint8_t epnum)
276 {
277 }
278 /**
279 * @brief This function handles PCD interrupt request.
280 * @param hpcd PCD handle
281 * @retval HAL status
282 */
HAL_PCD_IRQHandler(PCD_HandleTypeDef * hpcd)283 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
284 {
285 /* servicing of the endpoint correct transfer interrupt */
286 /* clear of the CTR flag into the sub */
287 PCD_EP_ISR_Handler(hpcd);
288 // TODO: Other interrupt such as wake/suspend/stall etc not implemented yet
289 }
290
291 /**
292 * @brief Data out stage callbacks
293 * @param hpcd PCD handle
294 * @param epnum endpoint number
295 * @retval None
296 */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)297 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
298 {
299 /* Prevent unused argument(s) compilation warning */
300 UNUSED(hpcd);
301 UNUSED(epnum);
302
303 /* NOTE : This function Should not be modified, when the callback is needed,
304 the HAL_PCD_DataOutStageCallback could be implemented in the user file
305 */
306 }
307
308 /**
309 * @brief Data IN stage callbacks
310 * @param hpcd PCD handle
311 * @param epnum endpoint number
312 * @retval None
313 */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)314 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
315 {
316 /* Prevent unused argument(s) compilation warning */
317 UNUSED(hpcd);
318 UNUSED(epnum);
319
320 /* NOTE : This function Should not be modified, when the callback is needed,
321 the HAL_PCD_DataInStageCallback could be implemented in the user file
322 */
323 }
324
325 /**
326 * @brief Setup stage callback
327 * @param hpcd PCD handle
328 * @retval None
329 */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)330 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
331 {
332 /* Prevent unused argument(s) compilation warning */
333 UNUSED(hpcd);
334
335 /* NOTE : This function Should not be modified, when the callback is needed,
336 the HAL_PCD_SetupStageCallback could be implemented in the user file
337 */
338 }
339
340 /**
341 * @brief USB Start Of Frame callbacks
342 * @param hpcd PCD handle
343 * @retval None
344 */
HAL_PCD_SOFCallback(PCD_HandleTypeDef * hpcd)345 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
346 {
347 /* Prevent unused argument(s) compilation warning */
348 UNUSED(hpcd);
349
350 /* NOTE : This function Should not be modified, when the callback is needed,
351 the HAL_PCD_SOFCallback could be implemented in the user file
352 */
353 }
354
355 /**
356 * @brief USB Reset callbacks
357 * @param hpcd PCD handle
358 * @retval None
359 */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)360 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
361 {
362 /* Prevent unused argument(s) compilation warning */
363 UNUSED(hpcd);
364
365 /* NOTE : This function Should not be modified, when the callback is needed,
366 the HAL_PCD_ResetCallback could be implemented in the user file
367 */
368 }
369
370 /**
371 * @brief Suspend event callbacks
372 * @param hpcd PCD handle
373 * @retval None
374 */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)375 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
376 {
377 /* Prevent unused argument(s) compilation warning */
378 UNUSED(hpcd);
379
380 /* NOTE : This function Should not be modified, when the callback is needed,
381 the HAL_PCD_SuspendCallback could be implemented in the user file
382 */
383 }
384
385 /**
386 * @brief Resume event callbacks
387 * @param hpcd PCD handle
388 * @retval None
389 */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)390 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
391 {
392 /* Prevent unused argument(s) compilation warning */
393 UNUSED(hpcd);
394
395 /* NOTE : This function Should not be modified, when the callback is needed,
396 the HAL_PCD_ResumeCallback could be implemented in the user file
397 */
398 }
399
400 /**
401 * @brief Incomplete ISO OUT callbacks
402 * @param hpcd PCD handle
403 * @param epnum endpoint number
404 * @retval None
405 */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)406 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
407 {
408 /* Prevent unused argument(s) compilation warning */
409 UNUSED(hpcd);
410 UNUSED(epnum);
411
412 /* NOTE : This function Should not be modified, when the callback is needed,
413 the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
414 */
415 }
416
417 /**
418 * @brief Incomplete ISO IN callbacks
419 * @param hpcd PCD handle
420 * @param epnum endpoint number
421 * @retval None
422 */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)423 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
424 {
425 /* Prevent unused argument(s) compilation warning */
426 UNUSED(hpcd);
427 UNUSED(epnum);
428
429 /* NOTE : This function Should not be modified, when the callback is needed,
430 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
431 */
432 }
433
434 /**
435 * @brief Connection event callbacks
436 * @param hpcd PCD handle
437 * @retval None
438 */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)439 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
440 {
441 /* Prevent unused argument(s) compilation warning */
442 UNUSED(hpcd);
443
444 /* NOTE : This function Should not be modified, when the callback is needed,
445 the HAL_PCD_ConnectCallback could be implemented in the user file
446 */
447 }
448
449 /**
450 * @brief Disconnection event callbacks
451 * @param hpcd PCD handle
452 * @retval None
453 */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)454 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
455 {
456 /* Prevent unused argument(s) compilation warning */
457 UNUSED(hpcd);
458
459 /* NOTE : This function Should not be modified, when the callback is needed,
460 the HAL_PCD_DisconnectCallback could be implemented in the user file
461 */
462 }
463 /**
464 * @}
465 */
466
467 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
468 * @brief management functions
469 *
470 @verbatim
471 ===============================================================================
472 ##### Peripheral Control functions #####
473 ===============================================================================
474 [..]
475 This subsection provides a set of functions allowing to control the PCD data
476 transfers.
477
478 @endverbatim
479 * @{
480 */
481
482 /**
483 * @brief Set the USB Device address
484 * @param hpcd PCD handle
485 * @param address new device address
486 * @retval HAL status
487 */
HAL_PCD_SetAddress(PCD_HandleTypeDef * hpcd,uint8_t address)488 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
489 {
490 __HAL_LOCK(hpcd);
491
492 /* set device address and enable function */
493 hpcd->Instance->faddr = address;
494 hpcd->USB_Address = address;
495 __HAL_UNLOCK(hpcd);
496 return HAL_OK;
497 }
498 /**
499 * @brief Open and configure an endpoint
500 * @param hpcd PCD handle
501 * @param ep_addr endpoint address
502 * @param ep_mps endpoint max packert size
503 * @param ep_type endpoint type
504 * @retval HAL status
505 */
HAL_PCD_EP_Open(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint16_t ep_mps,uint8_t ep_type)506 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
507 {
508 HAL_StatusTypeDef ret = HAL_OK;
509 PCD_EPTypeDef *ep;
510 uint16_t csr;
511
512 if ((ep_addr & 0x80U) == 0x80U)
513 {
514 ep = &hpcd->IN_ep[ep_addr & 0x7FU];
515 }
516 else
517 {
518 ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
519 }
520 ep->num = ep_addr & 0x7FU;
521 ep->is_in = (0x80U & ep_addr) != 0U;
522 ep->maxpacket = ep_mps;
523 ep->type = ep_type;
524
525 HAL_DBG_printf("ep_addr=%x, num=%d, is_in=%d\n", ep_addr, ep->num, ep->is_in);
526 __HAL_LOCK(hpcd);
527 NVIC_DisableIRQ(USBC_IRQn);
528 if (ep->num)
529 {
530 hpcd->Instance->index = ep->num;
531 if (ep->is_in)
532 {
533 hpcd->Instance->intrtx |= (1 << ep->num);
534 hpcd->Instance->txmaxp = ep_mps;
535 csr = USB_TXCSR_MODE | USB_TXCSR_CLRDATATOG;
536 if (hpcd->Instance->csr0_txcsr & USB_TXCSR_FIFONOTEMPTY)
537 csr |= USB_TXCSR_FLUSHFIFO;
538 hpcd->Instance->csr0_txcsr = csr;
539 }
540 else
541 {
542 hpcd->Instance->intrrx |= (1 << ep->num);
543 hpcd->Instance->rxmaxp = ep_mps;
544 csr = USB_RXCSR_FLUSHFIFO | USB_RXCSR_CLRDATATOG ;
545 // USB_RXCSR_AUTOCLEAR
546
547 if (ep->type == PCD_EP_TYPE_INTR)
548 csr |= USB_RXCSR_DISNYET;
549 // Set twice in case of double buffering.
550 hpcd->Instance->rxcsr = csr;
551 hpcd->Instance->rxcsr = csr;
552 }
553 }
554 NVIC_EnableIRQ(USBC_IRQn);
555 __HAL_UNLOCK(hpcd);
556 return ret;
557 }
558
559
560 /**
561 * @brief Deactivate an endpoint
562 * @param hpcd PCD handle
563 * @param ep_addr endpoint address
564 * @retval HAL status
565 */
HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)566 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
567 {
568 PCD_EPTypeDef *ep;
569
570 if ((ep_addr & 0x80U) == 0x80U)
571 {
572 ep = &hpcd->IN_ep[ep_addr & 0x7FU];
573 }
574 else
575 {
576 ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
577 }
578 ep->num = ep_addr & 0x7FU;
579
580 ep->is_in = (0x80U & ep_addr) != 0U;
581
582 __HAL_LOCK(hpcd);
583 NVIC_DisableIRQ(USBC_IRQn);
584
585 if (ep->num)
586 {
587 hpcd->Instance->index = ep->num;
588 if (ep->is_in)
589 {
590 hpcd->Instance->intrtx &= ~(1 << ep->num);
591 hpcd->Instance->txmaxp = 0;
592 // The programming guide says that we must not clear the DMAMODE bit before DMAENAB,
593 // so we only clear it in the sconed write...
594 hpcd->Instance->csr0_txcsr = (USB_TXCSR_DMAMODE | USB_TXCSR_FLUSHFIFO);
595 hpcd->Instance->csr0_txcsr = USB_TXCSR_FLUSHFIFO;
596 }
597 else
598 {
599 hpcd->Instance->intrrx &= ~(1 << ep->num);
600 hpcd->Instance->rxmaxp = 0;
601 hpcd->Instance->rxcsr = USB_RXCSR_FLUSHFIFO;
602 hpcd->Instance->rxcsr = USB_RXCSR_FLUSHFIFO; // Why twice ???
603 }
604 }
605 NVIC_EnableIRQ(USBC_IRQn);
606 __HAL_UNLOCK(hpcd);
607 return HAL_OK;
608 }
609
610
611 /**
612 * @brief Receive an amount of data
613 * @param hpcd PCD handle
614 * @param ep_addr endpoint address
615 * @param pBuf pointer to the reception buffer
616 * @retval received packet size.
617 */
HAL_PCD_EP_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf)618 uint32_t HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf)
619 {
620 PCD_EPTypeDef *ep;
621 uint32_t r = 0;
622
623 ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
624
625 if (ep->num)
626 {
627 __IO struct musb_epN_regs *epn;
628 uint16_t csr;
629
630 epn = &(hpcd->Instance->ep[ep->num].epN);
631 csr = epn->rxcsr;
632 if (csr & USB_RXCSR_P_SENDSTALL)
633 {
634 HAL_DBG_printf("ep stalling, rxcsr %03x\n", csr);
635 }
636 else
637 {
638 r = ep->xfer_count;
639 //HAL_DBG_printf("EP %d Rx: %p, %d, csr=%x\r\n", ep->num, pBuf, r, csr);
640 //HAL_DBG_print_data((char *)pBuf, 0, r);
641 if (csr & USB_RXCSR_RXPKTRDY)
642 {
643 #if !defined(USB_RX_DMA_ENABLED)
644 __IO uint8_t *fifox = (__IO uint8_t *) & (hpcd->Instance->fifox[ep->num]);
645 int i;
646 r = epn->rxcount;
647 for (i = 0; i < r; i++)
648 *(pBuf + i) = *fifox;
649 epn->rxcsr = 0;
650 #endif
651
652 #if defined(SF32LB58X) || defined(SF32LB55X)
653 /* 58 Because it is 480MHz, it is necessary to clear USB-RXCSR-RXPKTRDY here.*/
654 if (HAL_PCD_Get_RxbuffControl(ep->num)) //Control the receiving data flow of the channel 1:Control the receiving data flow of the channel;0 Stop receiving
655 epn->rxcsr = 0;
656 #endif
657 }
658 ep->xfer_count = 0;
659 }
660 }
661 else
662 {
663 __IO struct musb_ep0_regs *ep0;
664 int i;
665 uint16_t csr;
666 __IO uint8_t *fifox = (__IO uint8_t *) & (hpcd->Instance->fifox[ep->num]);
667
668 ep0 = &(hpcd->Instance->ep[ep->num].ep0);
669 r = ep0->count0;
670 if (r > ep->xfer_len)
671 r = ep->xfer_len;
672 for (i = 0; i < (int)r; i++)
673 *(pBuf + i) = *fifox;
674 csr = USB_CSR0_P_SVDRXPKTRDY;
675 if (r < ep->maxpacket)
676 {
677 ep0_state_change(hpcd, HAL_PCD_EP0_STATUSIN);
678 csr |= USB_CSR0_P_DATAEND;
679 }
680 ep0->csr0 = csr;
681 HAL_DBG_printf("EP0 Rx:%d\r\n", r);
682 //HAL_DBG_print_data((char *)pBuf, 0, r);
683 }
684
685 return r;
686 }
687
688 /**
689 * @brief Receive an amount of data
690 * @param hpcd PCD handle
691 * @param ep_addr endpoint address
692 * @param pBuf pointer to the reception buffer
693 * @param len amount of data to be received
694 * @retval HAL status
695 */
HAL_PCD_EP_Prepare_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)696 HAL_StatusTypeDef HAL_PCD_EP_Prepare_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
697 {
698
699 PCD_EPTypeDef *ep;
700 uint16_t csr;
701
702 ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
703
704 /*setup and start the Xfer */
705 ep->xfer_buff = pBuf;
706 ep->xfer_len = len;
707 ep->is_in = 0U;
708 ep->num = ep_addr & 0x7FU;
709
710 if (ep->num)
711 {
712 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep->num].epN);
713
714 HAL_DBG_printf("Prepare_read on pipe %d:%p,len %d, is_in=%d\n", ep->num, pBuf, len, ep->is_in);
715 csr = epn->rxcsr;
716 }
717 else
718 ep0_state_change(hpcd, HAL_PCD_EP0_RX);
719
720 return HAL_OK;
721 }
722
723 /**
724 * @brief Get Received Data Size
725 * @param hpcd PCD handle
726 * @param ep_addr endpoint address
727 * @retval Data Size
728 */
HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)729 uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
730 {
731 uint16_t r = 0;
732
733 NVIC_DisableIRQ(USBC_IRQn);
734 hpcd->Instance->index = ep_addr & 0x7FU;
735 r = hpcd->Instance->rxcount;
736 NVIC_EnableIRQ(USBC_IRQn);
737 return r;
738 }
739
740 /**
741 * @brief Send an amount of data
742 * @param hpcd PCD handle
743 * @param ep_addr endpoint address
744 * @param pBuf pointer to the transmission buffer
745 * @param len amount of data to be sent
746 * @retval HAL status
747 */
HAL_PCD_EP_Transmit(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)748 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
749 {
750 PCD_EPTypeDef *ep;
751
752 ep = &hpcd->IN_ep[ep_addr & 0x7FU];
753
754 /*setup and start the Xfer */
755 ep->xfer_buff = pBuf;
756 ep->xfer_len = len;
757 ep->is_in = 1U;
758 ep->num = ep_addr & 0x7FU;
759 ep->xfer_count = len;
760
761 if (ep->num)
762 {
763 uint16_t csr;
764 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep->num].epN);
765
766 csr = epn->txcsr;
767 HAL_DBG_printf("tx ep %d: csr=0x%x, %d\n", ep->num, csr, len);
768 #if USB_TX_DMA_ENABLED
769 if (IS_DCACHED_RAM((uint32_t)pBuf))
770 mpu_dcache_clean((void *)pBuf, len);
771
772
773 struct musb_dma_regs *dma = (struct musb_dma_regs *) & (hpcd->Instance->dma[ep->num]);
774 dma->addr = (REG32)pBuf;
775 dma->count = len;
776 dma->cntl = //(1 << USB_DMACTRL_ENABLE_SHIFT) |
777 (1 << USB_DMACTRL_TRANSMIT_SHIFT) |
778 //(0 << USB_DMACTRL_MODE1_SHIFT) |
779 (ep->num << USB_DMACTRL_ENDPOINT_SHIFT) |
780 (1 << USB_DMACTRL_IRQENABLE_SHIFT);
781 if ((len / ep->maxpacket) > 1)
782 {
783 dma->cntl |= (1 << USB_DMACTRL_ENABLE_SHIFT) | (1 << USB_DMACTRL_MODE1_SHIFT);
784 csr |= USB_TXCSR_DMAENAB | USB_TXCSR_AUTOSET;
785 tx_packet_max = 1;
786 }
787 else
788 {
789 dma->cntl |= (1 << USB_DMACTRL_ENABLE_SHIFT) | (0 << USB_DMACTRL_MODE1_SHIFT);
790 tx_packet_max = 0;
791 }
792 epn->txcsr = csr;
793
794 #else
795 __IO uint8_t *fifox = (__IO uint8_t *) & (hpcd->Instance->fifox[ep->num]);
796
797 if (csr & USB_TXCSR_TXPKTRDY)
798 {
799 //LOG_W("old packet still ready, txcsr %03x\n", csr);
800 }
801 if (csr & USB_TXCSR_P_SENDSTALL)
802 {
803 //LOG_W("ep stalling, txcsr %03x\n", csr);
804 }
805 for (int i = 0; i < len; i++) // REVISIT: Use 16bits/32bits FIFO to speed up
806 *fifox = *(pBuf + i);
807 csr &= ~USB_TXCSR_P_UNDERRUN;
808 csr |= USB_TXCSR_AUTOSET;
809 if (len <= ep->maxpacket)
810 csr |= USB_TXCSR_TXPKTRDY;
811
812 epn->txcsr = csr;
813 #endif
814 //HAL_DBG_print_data((char *)pBuf, 0, len);
815 }
816 else
817 {
818 int i;
819 uint16_t csr;
820 __IO uint8_t *fifox = (__IO uint8_t *) & (hpcd->Instance->fifox[ep->num]);
821 __IO struct musb_ep0_regs *ep0 = &(hpcd->Instance->ep[ep->num].ep0);
822
823 for (i = 0; i < (int)len; i++) // REVISIT: Use 16bits/32bits FIFO to speed up
824 *fifox = *(pBuf + i);
825 csr = USB_CSR0_TXPKTRDY;
826
827 HAL_DBG_printf("tx ep0: csr=0x%x, %d\n", csr, len);
828 //HAL_DBG_print_data((char *)pBuf, 0, len);
829
830 if (len && len < ep->maxpacket)
831 {
832 csr |= USB_CSR0_P_DATAEND;
833 ep0_state_change(hpcd, HAL_PCD_EP0_STATUSOUT);
834 }
835 ep0->csr0 = csr;
836
837 }
838 return HAL_OK;
839 }
840
musb_stall(__IO struct musb_epN_regs * epn,int value,int is_in)841 static void musb_stall(__IO struct musb_epN_regs *epn, int value, int is_in)
842 {
843 uint16_t csr;
844
845 if (is_in)
846 {
847 csr = epn->txcsr;
848 csr |= USB_TXCSR_P_WZC_BITS | USB_TXCSR_CLRDATATOG;
849 if (value)
850 csr |= USB_TXCSR_P_SENDSTALL;
851 else
852 csr &= ~(USB_TXCSR_P_SENDSTALL | USB_TXCSR_P_SENTSTALL);
853 csr &= ~USB_TXCSR_TXPKTRDY;
854 epn->txcsr = csr;
855 }
856 else
857 {
858 csr = epn->rxcsr;
859 csr |= USB_RXCSR_P_WZC_BITS | USB_RXCSR_FLUSHFIFO | USB_RXCSR_CLRDATATOG;
860 if (value)
861 csr |= USB_RXCSR_P_SENDSTALL;
862 else
863 csr &= ~(USB_RXCSR_P_SENDSTALL | USB_RXCSR_P_SENTSTALL);
864 epn->rxcsr = csr;
865 }
866
867 }
868 /**
869 * @brief Set a STALL condition over an endpoint
870 * @param hpcd PCD handle
871 * @param ep_addr endpoint address
872 * @retval HAL status
873 */
HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)874 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
875 {
876 PCD_EPTypeDef *ep;
877
878 if ((0x80U & ep_addr) == 0x80U)
879 ep = &hpcd->IN_ep[ep_addr & 0x7FU];
880 else
881 ep = &hpcd->OUT_ep[ep_addr];
882
883 ep->is_stall = 1;
884 ep->num = ep_addr & 0x7FU;
885 ep->is_in = ((ep_addr & 0x80U) == 0x80U);
886
887 __HAL_LOCK(hpcd);
888 if (ep->num)
889 {
890 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep->num].epN);
891 musb_stall(epn, 1, ep->is_in);
892 }
893 else
894 {
895 __IO struct musb_ep0_regs *ep0 = &(hpcd->Instance->ep[ep->num].ep0);
896 ep0->csr0 |= USB_CSR0_P_SENDSTALL;
897 }
898 __HAL_UNLOCK(hpcd);
899 //ep->is_stall = 0;
900
901 return HAL_OK;
902 }
903
904 /**
905 * @brief Clear a STALL condition over in an endpoint
906 * @param hpcd PCD handle
907 * @param ep_addr endpoint address
908 * @retval HAL status
909 */
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)910 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
911 {
912 PCD_EPTypeDef *ep;
913
914 if ((0x80U & ep_addr) == 0x80U)
915 ep = &hpcd->IN_ep[ep_addr & 0x7FU];
916 else
917 ep = &hpcd->OUT_ep[ep_addr];
918
919 ep->is_stall = 0U;
920 ep->num = ep_addr & 0x7FU;
921 ep->is_in = ((ep_addr & 0x80U) == 0x80U);
922
923 __HAL_LOCK(hpcd);
924 if (ep->num)
925 {
926 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep->num].epN);
927 musb_stall(epn, 0, ep->is_in);
928 }
929 else
930 {
931 __IO struct musb_ep0_regs *ep0 = &(hpcd->Instance->ep[ep->num].ep0);
932 ep0->csr0 &= ~USB_CSR0_P_SENDSTALL;
933 }
934 __HAL_UNLOCK(hpcd);
935
936 return HAL_OK;
937 }
938
939 /**
940 * @brief Flush an endpoint
941 * @param hpcd PCD handle
942 * @param ep_addr endpoint address
943 * @retval HAL status
944 */
HAL_PCD_EP_Flush(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)945 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
946 {
947 PCD_EPTypeDef *ep;
948 uint16_t csr;
949
950 if ((0x80U & ep_addr) == 0x80U)
951 ep = &hpcd->IN_ep[ep_addr & 0x7FU];
952 else
953 ep = &hpcd->OUT_ep[ep_addr];
954 __HAL_LOCK(hpcd);
955 if (ep->num)
956 {
957 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep->num].epN);
958 hpcd->Instance->intrtx &= ~(1 << ep->num);
959 if (ep->is_in)
960 {
961 csr = epn->txcsr;
962 if (csr & USB_TXCSR_FIFONOTEMPTY)
963 {
964 csr |= USB_TXCSR_FLUSHFIFO | USB_TXCSR_P_WZC_BITS;
965 csr &= ~USB_TXCSR_TXPKTRDY;
966 /*
967 Setting both TXPKTRDY and FLUSHFIFO makes controller
968 to interrupt current FIFP loading, but not flushing the already loaded ones.
969 */
970 epn->txcsr = csr;
971 /* REVISIT: may be inapproperiate w/o FIFONOTEMPTY... */
972 epn->txcsr = csr;
973 }
974 }
975 else
976 {
977 csr = epn->rxcsr;
978 csr |= USB_RXCSR_P_WZC_BITS | USB_RXCSR_FLUSHFIFO;
979 epn->rxcsr = csr;
980 epn->rxcsr = csr;
981 }
982 hpcd->Instance->intrtx |= ~(1 << ep->num);
983 }
984 __HAL_UNLOCK(hpcd);
985
986 return HAL_OK;
987 }
988
989
990 /**
991 * @}
992 */
993
994 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
995 * @brief Peripheral State functions
996 *
997 @verbatim
998 ===============================================================================
999 ##### Peripheral State functions #####
1000 ===============================================================================
1001 [..]
1002 This subsection permits to get in run-time the status of the peripheral
1003 and the data flow.
1004
1005 @endverbatim
1006 * @{
1007 */
1008
1009 /**
1010 * @brief Return the PCD state
1011 * @param hpcd PCD handle
1012 * @retval HAL state
1013 */
HAL_PCD_GetState(PCD_HandleTypeDef * hpcd)1014 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1015 {
1016 return hpcd->State;
1017 }
1018
HAL_PCD_TestMode(PCD_HandleTypeDef * hpcd,uint16_t tm,uint8_t * data,uint8_t len)1019 HAL_StatusTypeDef HAL_PCD_TestMode(PCD_HandleTypeDef *hpcd, uint16_t tm, uint8_t *data, uint8_t len)
1020 {
1021 tm >>= 8; // The most significant byte is the test mode
1022
1023 switch (tm)
1024 {
1025 case 1: // Test_J
1026 hpcd->Instance->testmode = USB_TEST_J;
1027 break;
1028 case 2: // Test_K
1029 hpcd->Instance->testmode = USB_TEST_K;
1030 break;
1031 case 3: // Test_SE0_NAK
1032 hpcd->Instance->testmode = USB_TEST_SE0_NAK;
1033 break;
1034 case 4: // Test_Packet
1035 {
1036 __IO uint8_t *fifo = (__IO uint8_t *) & (hpcd->Instance->fifox[0]);
1037 __IO struct musb_ep0_regs *ep0 = &(hpcd->Instance->ep[0].ep0);
1038 int i;
1039
1040 for (i = 0; i < len; i++) // REVISIT: Use 16bits/32bits FIFO to speed up
1041 *fifo = *(data + i);
1042 hpcd->Instance->testmode = USB_TEST_PACKET;
1043 ep0->csr0 |= USB_CSR0_TXPKTRDY;
1044 break;
1045 }
1046 case 5: // Test_Force_Enable.
1047 hpcd->Instance->testmode = USB_TEST_FORCE_FS;
1048 break;
1049 default: // Reserved
1050 ;
1051 }
1052 return HAL_OK;
1053 }
1054
1055 /**
1056 * @}
1057 */
1058
1059 /**
1060 * @}
1061 */
1062
1063 /** @addtogroup PCD_Private_Functions
1064 * @{
1065 */
1066
ep0_state_str(uint8_t state)1067 static const char *ep0_state_str(uint8_t state)
1068 {
1069 static const char *states_str[] =
1070 {
1071 "IDLE",
1072 "SETUP",
1073 "TX",
1074 "RX",
1075 "STATUSIN",
1076 "STATUSOUT",
1077 "ACKWAIT",
1078 };
1079 return states_str[state];
1080 }
1081
1082
1083 /*
1084 * Handle all control requests with no DATA stage, including standard
1085 * requests such as:
1086 * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized
1087 * always delegated to the gadget driver
1088 * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE
1089 * always handled here, except for class/vendor/... features
1090 *
1091 * Context: caller holds controller lock
1092 */
1093 static int
service_zero_data_request(PCD_HandleTypeDef * hpcd,struct urequest * req)1094 service_zero_data_request(PCD_HandleTypeDef *hpcd, struct urequest *req)
1095 {
1096 int handled = -1;
1097 const uint8_t recip = req->request_type & USB_REQ_TYPE_RECIPIENT_MASK;
1098
1099 /* the gadget driver handles everything except what we MUST handle */
1100 if ((req->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD)
1101 {
1102 switch (req->bRequest)
1103 {
1104 case USB_REQ_SET_ADDRESS:
1105 case USB_REQ_SET_CONFIGURATION:
1106 /* change it after the status stage */
1107 handled = 1;
1108 break;
1109
1110 case USB_REQ_CLEAR_FEATURE:
1111 switch (recip)
1112 {
1113 case USB_REQ_TYPE_DEVICE:
1114 if (req->wValue != USB_REMOTE_WAKEUP)
1115 break;
1116 handled = 1;
1117 break;
1118 case USB_REQ_TYPE_INTERFACE:
1119 break;
1120 case USB_REQ_TYPE_ENDPOINT:
1121 {
1122 const uint8_t epnum = req->wIndex & 0x0f;
1123 uint16_t csr;
1124 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[epnum].epN);
1125
1126 if (epnum == 0 || req->wValue != USB_FEATURE_ENDPOINT_HALT)
1127 break;
1128 handled = 1;
1129
1130 if (req->wIndex & USB_DIR_IN)
1131 {
1132 csr = epn->txcsr;
1133 csr |= USB_TXCSR_CLRDATATOG | USB_TXCSR_P_WZC_BITS;
1134 csr &= ~(USB_TXCSR_P_SENDSTALL | USB_TXCSR_P_SENTSTALL | USB_TXCSR_TXPKTRDY);
1135 epn->txcsr = csr;
1136 }
1137 else
1138 {
1139 csr = epn->rxcsr;
1140 csr |= USB_RXCSR_CLRDATATOG | USB_RXCSR_P_WZC_BITS;
1141 csr &= ~(USB_RXCSR_P_SENDSTALL | USB_RXCSR_P_SENTSTALL);
1142 epn->rxcsr = csr;
1143 }
1144 break;
1145 }
1146 default:
1147 /* class, vendor, etc ... delegate */
1148 handled = 0;
1149 break;
1150 }
1151 break;
1152
1153 case USB_REQ_SET_FEATURE:
1154 switch (recip)
1155 {
1156 case USB_REQ_TYPE_DEVICE:
1157 handled = 1;
1158 switch (req->wValue)
1159 {
1160 case USB_REMOTE_WAKEUP:
1161 //musb->may_wakeup = 1;
1162 break;
1163 default:
1164 handled = -1;
1165 break;
1166 }
1167 break;
1168 case USB_REQ_TYPE_INTERFACE:
1169 break;
1170
1171 case USB_REQ_TYPE_ENDPOINT:
1172 {
1173 const uint8_t epnum = req->wIndex & 0x0f;
1174 uint16_t csr;
1175 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[epnum].epN);
1176
1177 if (epnum == 0 || req->wValue != USB_FEATURE_ENDPOINT_HALT)
1178 break;
1179
1180 if (req->wIndex & USB_DIR_IN)
1181 {
1182 csr = epn->txcsr;
1183 if (csr & USB_TXCSR_FIFONOTEMPTY)
1184 csr |= USB_TXCSR_FLUSHFIFO;
1185 csr |= (USB_TXCSR_P_SENDSTALL | USB_TXCSR_CLRDATATOG | USB_TXCSR_P_WZC_BITS);
1186 epn->txcsr = csr;
1187 }
1188 else
1189 {
1190 csr = epn->rxcsr;
1191 csr |= (USB_RXCSR_P_SENDSTALL | USB_RXCSR_FLUSHFIFO | USB_RXCSR_CLRDATATOG | USB_RXCSR_P_WZC_BITS);
1192 epn->rxcsr = csr;
1193 }
1194 handled = 1;
1195 }
1196 break;
1197
1198 default:
1199 /* class, vendor, etc ... delegate */
1200 handled = 0;
1201 break;
1202 }
1203 break;
1204 handled = 1;
1205 break;
1206 default:
1207 handled = 0;
1208 }
1209 }
1210 else
1211 handled = 0;
1212 return handled;
1213 }
1214
1215 /**
1216 * @brief This function handles PCD Endpoint 0 interrupt request.
1217 * @param hpcd PCD handle
1218 * @retval HAL status
1219 */
PCD_EP0_ISR_Handler(PCD_HandleTypeDef * hpcd)1220 static HAL_StatusTypeDef PCD_EP0_ISR_Handler(PCD_HandleTypeDef *hpcd)
1221 {
1222 uint16_t csr;
1223 uint16_t len;
1224
1225 __IO struct musb_ep0_regs *ep0 = &(hpcd->Instance->ep[0].ep0);
1226 __IO uint8_t *fifox = (__IO uint8_t *) & (hpcd->Instance->fifox[0]);
1227
1228 csr = ep0->csr0;
1229 len = ep0->count0;
1230
1231 HAL_DBG_printf("ep0 ISR: %s, csr=0x%x\r\n", ep0_state_str(hpcd->ep0_state), csr);
1232 /*
1233 if DATAEND is set, we should not call the callback,
1234 hence the status stage is not complete.
1235 */
1236 if (csr & USB_CSR0_P_DATAEND)
1237 {
1238 csr |= (~USB_CSR0_P_DATAEND);
1239 //return HAL_OK;//Will cause the failure of sending character descriptors
1240 }
1241
1242 /*
1243 I sent a stall, need to acknowledge it now..
1244 */
1245 if (csr & USB_CSR0_P_SENTSTALL)
1246 {
1247 ep0->csr0 = (csr & (~USB_CSR0_P_SENTSTALL));
1248 ep0_state_change(hpcd, HAL_PCD_EP0_IDLE);
1249 csr = ep0->csr0;
1250 }
1251
1252 /* Request ended "early". */
1253 if (csr & USB_CSR0_P_SETUPEND)
1254 {
1255 ep0->csr0 = USB_CSR0_P_SETUPEND;
1256 switch (hpcd->ep0_state)
1257 {
1258 case HAL_PCD_EP0_TX:
1259 ep0_state_change(hpcd, HAL_PCD_EP0_STATUSOUT);
1260 break;
1261 case HAL_PCD_EP0_RX:
1262 ep0_state_change(hpcd, HAL_PCD_EP0_STATUSIN);
1263 case HAL_PCD_EP0_IDLE:
1264 break;
1265 default:
1266 HAL_DBG_printf("SetupEnd case in wrong state %s\r\n", ep0_state_str(hpcd->ep0_state));
1267 break;
1268 }
1269 csr = ep0->csr0;
1270 }
1271
1272 /*
1273 Docs from Mentor only describe tx,rx, and idle/setup states.
1274 We need to handle nuances around status stage, and also the
1275 case where status and setup stages come back-to-back..
1276 */
1277 switch (hpcd->ep0_state)
1278 {
1279 case HAL_PCD_EP0_TX:
1280 /*ireq on clearing txpktrdy*/
1281 if ((csr & USB_CSR0_TXPKTRDY) == 0)
1282 HAL_PCD_DataInStageCallback(hpcd, 0);
1283 break;
1284 case HAL_PCD_EP0_RX:
1285 /* irq on set rxpktrdy*/
1286 if (csr & USB_CSR0_RXPKTRDY)
1287 HAL_PCD_DataOutStageCallback(hpcd, 0);
1288 break;
1289 case HAL_PCD_EP0_STATUSIN:
1290 // Set USB address ???
1291 case HAL_PCD_EP0_STATUSOUT:
1292 case HAL_PCD_EP0_ACKWAIT:
1293 if (csr & USB_CSR0_RXPKTRDY)
1294 goto setup;
1295 ep0_state_change(hpcd, HAL_PCD_EP0_IDLE);
1296 break;
1297
1298 case HAL_PCD_EP0_IDLE:
1299 ep0_state_change(hpcd, HAL_PCD_EP0_SETUP);
1300 /*FALL THROUGH*/
1301 case HAL_PCD_EP0_SETUP:
1302 setup:
1303 if (csr & USB_CSR0_RXPKTRDY)
1304 {
1305 uint8_t *p = (uint8_t *)hpcd->Setup;
1306 struct urequest *req = (struct urequest *)p;
1307 int i;
1308
1309 HAL_ASSERT(len <= 12 * sizeof(uint32_t));
1310 for (i = 0; i < len; i++)
1311 *(p + i) = *fifox;
1312 HAL_DBG_printf("Setup rx:%d", len);
1313 //HAL_DBG_print_data((char *)p, 0, len);
1314 if (len)
1315 {
1316 ep0->csr0 = USB_CSR0_P_SVDSETUPEND;
1317 while ((ep0->csr0 & USB_CSR0_P_SETUPEND) != 0);
1318 hpcd->ackpend = USB_CSR0_P_SVDRXPKTRDY;
1319 if (req->wLength == 0)
1320 {
1321 if (req->request_type & USB_REQ_TYPE_DIR_IN)
1322 hpcd->ackpend |= USB_CSR0_TXPKTRDY;
1323 ep0_state_change(hpcd, HAL_PCD_EP0_ACKWAIT);
1324 }
1325 else if (req->request_type & USB_REQ_TYPE_DIR_IN)
1326 {
1327 ep0_state_change(hpcd, HAL_PCD_EP0_TX);
1328 ep0->csr0 = USB_CSR0_P_SVDRXPKTRDY;
1329 while ((ep0->csr0 & USB_CSR0_RXPKTRDY) != 0);
1330 hpcd->ackpend = 0;
1331 }
1332 else
1333 ep0_state_change(hpcd, HAL_PCD_EP0_RX);
1334 switch (hpcd->ep0_state)
1335 {
1336 case HAL_PCD_EP0_ACKWAIT:
1337 {
1338 int handled = service_zero_data_request(hpcd, req);
1339 hpcd->ackpend |= USB_CSR0_P_DATAEND;
1340
1341 HAL_DBG_printf("Zero data handled %d\r\n", handled);
1342 if (handled > 0)
1343 {
1344 ep0_state_change(hpcd, HAL_PCD_EP0_STATUSIN);
1345 }
1346 break;
1347 }
1348 case HAL_PCD_EP0_TX:
1349 {
1350 /*TODO: validate this*/
1351 break;
1352 }
1353 default:
1354 break;
1355 }
1356 ep0->csr0 = hpcd->ackpend;
1357 hpcd->ackpend = 0;
1358 HAL_PCD_SetupStageCallback(hpcd);
1359 }
1360 }
1361 break;
1362 default:
1363 break;
1364 }
1365 return HAL_OK;
1366 }
1367
musbd_stage0_irq(PCD_HandleTypeDef * hpcd,uint8_t int_usb)1368 static int musbd_stage0_irq(PCD_HandleTypeDef *hpcd, uint8_t int_usb)
1369 {
1370 uint8_t devctl = hpcd->Instance->devctl;
1371 int r = 0;
1372
1373 if (devctl & USB_DEVCTL_HM) // No host mode supported yet.
1374 HAL_ASSERT(0);
1375
1376 if (int_usb & USB_INTR_RESUME)
1377 {
1378 switch (hpcd->phy_state)
1379 {
1380 case OTG_STATE_B_WAIT_ACON:
1381 case OTG_STATE_B_PERIPHERALS:
1382 if ((devctl & USB_DEVCTL_VBUS) != (3 << USB_DEVCTL_VBUS_SHIFT))
1383 {
1384 hpcd->Instance->intrusb |= USB_INTR_DISCONNECT;
1385 hpcd->Instance->intrusb &= ~USB_INTR_SUSPEND;
1386 }
1387 // REVISIT: Resume???
1388 break;
1389 case OTG_STATE_B_IDLE:
1390 hpcd->Instance->intrusb &= ~USB_INTR_SUSPEND;
1391 break;
1392 default:
1393 HAL_ASSERT(0); // Incorrect resume.
1394 }
1395 }
1396
1397 if (int_usb & USB_INTR_SESSREQ)
1398 {
1399 if (((devctl & USB_DEVCTL_VBUS) == USB_DEVCTL_VBUS) && (devctl & USB_DEVCTL_BDEVICE))
1400 return 1;
1401
1402 // REVISIT: A device ONLY????
1403 hpcd->Instance->devctl = USB_DEVCTL_SESSION;
1404 ep0_state_change(hpcd, HAL_PCD_EP0_IDLE);
1405 r = 1;
1406 }
1407
1408 if (int_usb & USB_INTR_VBUSERROR) // This is for A device only.
1409 {
1410 HAL_ASSERT(0);
1411 r = 1;
1412 }
1413
1414 if (int_usb & USB_INTR_SUSPEND)
1415 {
1416 r = 1;
1417 switch (hpcd->phy_state)
1418 {
1419 case OTG_STATE_B_PERIPHERALS:
1420 // Go suspend;
1421 hpcd->phy_state = OTG_STATE_B_WAIT_ACON;
1422 break;
1423 case OTG_STATE_B_IDLE:
1424 break;
1425 default:
1426 HAL_DBG_printf("phy_state=%d\r\n", hpcd->phy_state);
1427 HAL_ASSERT(0); // Should not happen
1428 break;
1429 }
1430 }
1431 if (int_usb & USB_INTR_CONNECT)
1432 {
1433 r = 1;
1434 ep0_state_change(hpcd, HAL_PCD_EP0_IDLE);
1435 HAL_PCD_ConnectCallback(hpcd);
1436 if (int_usb & USB_INTR_SUSPEND)
1437 int_usb &= ~USB_INTR_SUSPEND;
1438 }
1439 if (int_usb & USB_INTR_DISCONNECT)
1440 {
1441 r = 1;
1442 HAL_PCD_DisconnectCallback(hpcd);
1443 hpcd->Instance->devctl = USB_DEVCTL_SESSION;
1444 hpcd->phy_state = OTG_STATE_B_IDLE;
1445 }
1446 if (int_usb & USB_INTR_RESET)
1447 {
1448 r = 1;
1449 switch (hpcd->phy_state)
1450 {
1451 case OTG_STATE_B_WAIT_ACON:
1452 case OTG_STATE_B_PERIPHERALS:
1453 case OTG_STATE_B_IDLE:
1454 hpcd->phy_state = OTG_STATE_B_PERIPHERALS;
1455 ep0_state_change(hpcd, HAL_PCD_EP0_IDLE);
1456 HAL_PCD_ResetCallback(hpcd);
1457 break;
1458 default:
1459 HAL_ASSERT(0);
1460 }
1461 }
1462
1463 return r;
1464 }
1465
1466 /**
1467 * @brief This function handles PCD Endpoint interrupt request.
1468 * @param hpcd PCD handle
1469 * @retval HAL status
1470 */
PCD_EP_ISR_Handler(PCD_HandleTypeDef * hpcd)1471 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1472 {
1473 uint32_t reg;
1474 int ep_num;
1475 uint8_t int_usb = hpcd->Instance->intrusb;
1476 uint16_t int_tx = hpcd->Instance->intrtx;
1477 uint16_t int_rx = hpcd->Instance->intrrx;
1478 uint32_t dmaintr = hpcd->Instance->dmaintr;
1479
1480 HAL_DBG_printf("USB interrupt usb=%x, tx=%d, rx=%d, usbe=%x, dma_intr=%x\r\n", int_usb, int_tx, int_rx, hpcd->Instance->intrusbe, dmaintr);
1481
1482 if (int_usb)
1483 musbd_stage0_irq(hpcd, int_usb);
1484
1485 if (int_tx && (int_tx & 1))
1486 PCD_EP0_ISR_Handler(hpcd);
1487
1488 #if defined(USB_TX_DMA_ENABLED)||defined(USB_RX_DMA_ENABLED)
1489 reg = (dmaintr >> 1);
1490 ep_num = 1;
1491 while (reg)
1492 {
1493 if (reg & 1)
1494 {
1495 PCD_EPTypeDef *ep;
1496 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep_num].epN);
1497
1498 if (hpcd->IN_ep[ep_num].maxpacket)
1499 ep = &hpcd->IN_ep[ep_num];
1500 else
1501 ep = &hpcd->OUT_ep[ep_num];
1502
1503 HAL_DBG_printf("DMA Done on EP: %d, is_in=%d, dmaintr=%x\n", ep->num, ep->is_in, dmaintr);
1504
1505 if (ep->is_in)
1506 {
1507 //TX
1508 if (0 == tx_packet_max)
1509 {
1510 uint16_t csr = epn->txcsr;
1511 csr &= ~USB_TXCSR_P_UNDERRUN;
1512 csr |= USB_TXCSR_AUTOSET;
1513 if (ep->xfer_len <= ep->maxpacket)
1514 csr |= USB_TXCSR_TXPKTRDY;
1515 epn->txcsr = csr;
1516 }
1517 else
1518 {
1519 HAL_PCD_DataInStageCallback(hpcd, ep_num);
1520 }
1521 }
1522 else
1523 {
1524 #ifndef SF32LB58X
1525 /*Clear RXPKTRDY and send an ACK to the host. 58 cannot be cleared here because there is no time to react.
1526 52/56 can be cleared here to increase the rate*/
1527 if (HAL_PCD_Get_RxbuffControl(ep->num)) //Control the receiving data flow of the channel 1:Control the receiving data flow of the channel;0 Stop receiving
1528 epn->rxcsr = 0;
1529 #endif
1530 HAL_PCD_DataOutStageCallback(hpcd, ep_num); //RX
1531 }
1532
1533 }
1534 ep_num++;
1535 reg >>= 1;
1536 }
1537 #endif
1538
1539 reg = (int_rx >> 1);
1540 ep_num = 1;
1541 while (reg)
1542 {
1543 if (reg & 1)
1544 {
1545 #if USB_RX_DMA_ENABLED
1546 PCD_EPTypeDef *ep = &hpcd->OUT_ep[ep_num];
1547 struct musb_dma_regs *dma = (struct musb_dma_regs *) & (hpcd->Instance->dma[ep->num]);
1548 __IO struct musb_epN_regs *epn = &(hpcd->Instance->ep[ep->num].epN);
1549
1550 HAL_DBG_printf("DMA RX pipe=%d, len=%d\n", ep->num, epn->rxcount);
1551 if (epn->rxcount)
1552 {
1553 if (IS_DCACHED_RAM(ep->xfer_buff))
1554 SCB_InvalidateDCache_by_Addr(ep->xfer_buff, epn->rxcount);
1555 dma->addr = (REG32)ep->xfer_buff;
1556 dma->count = epn->rxcount;
1557 ep->xfer_count = dma->count;
1558 epn->rxcount = 0;
1559 dma->cntl = (1 << USB_DMACTRL_ENABLE_SHIFT) |
1560 (0 << USB_DMACTRL_TRANSMIT_SHIFT) |
1561 (0 << USB_DMACTRL_MODE1_SHIFT) |
1562 (ep->num << USB_DMACTRL_ENDPOINT_SHIFT) |
1563 (1 << USB_DMACTRL_IRQENABLE_SHIFT);
1564 }
1565 #else
1566 HAL_PCD_DataOutStageCallback(hpcd, ep_num);
1567 #endif
1568
1569 }
1570 ep_num++;
1571 reg >>= 1;
1572 }
1573
1574
1575 reg = (int_tx >> 1);
1576 ep_num = 1;
1577 while (reg)
1578 {
1579 if ((reg & 1) && (0 == tx_packet_max))
1580 HAL_PCD_DataInStageCallback(hpcd, ep_num);
1581 ep_num++;
1582 reg >>= 1;
1583 }
1584 __DSB();
1585 return HAL_OK;
1586 }
1587
1588
1589 /**
1590 * @}
1591 */
1592
1593 /**
1594 * @}
1595 */
1596
1597 #endif /* HAL_PCD_MODULE_ENABLED */
1598
1599 /**
1600 * @}
1601 */