@@ -91,6 +91,98 @@ uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chnum)
91
91
// - URB_NOTREADY = a NAK, NYET, or not more than a couple of repeats of some of the errors that will
92
92
// become URB_ERROR if they repeat several times in a row
93
93
//
94
+ #if ARC_USB_FULL_SIZE
95
+ void HAL_HCD_HC_NotifyURBChange_Callback (HCD_HandleTypeDef *pHcd, uint8_t uChannel, HCD_URBStateTypeDef urbState)
96
+ {
97
+ USBHALHost_Private_t *pPriv = (USBHALHost_Private_t *)(pHcd->pData );
98
+
99
+ HCTD *pTransferDescriptor = (HCTD *)pPriv->addr [uChannel];
100
+
101
+
102
+
103
+ if (pTransferDescriptor)
104
+ {
105
+ constexpr uint32_t uRetryCount = 10 ;
106
+
107
+ uint32_t endpointType = pHcd->hc [uChannel].ep_type ;
108
+
109
+ if ((endpointType == EP_TYPE_INTR))
110
+ {
111
+ // Disable the channel interupt and retransfer below
112
+ pTransferDescriptor->state = USB_TYPE_IDLE ;
113
+ HAL_HCD_DisableInt (pHcd, uChannel);
114
+ }
115
+ else if ((endpointType == EP_TYPE_BULK) || (endpointType == EP_TYPE_CTRL))
116
+ {
117
+ switch (urbState)
118
+ {
119
+ case URB_NOTREADY:
120
+ {
121
+ // If we have transfered any data then disable retries
122
+ if (pHcd->hc [uChannel].xfer_count > 0 )
123
+ pTransferDescriptor->retry = 0xffffffff ; // Disable retries
124
+ else
125
+ {
126
+ // if the retry count is 0 then initialise downward counting retry
127
+ // otherwise decrement retry count
128
+ if (pTransferDescriptor->retry == 0 )
129
+ pTransferDescriptor->retry = uRetryCount;
130
+ else
131
+ pTransferDescriptor->retry --;
132
+ }
133
+
134
+ // If our retry count has got down to 0 or we are an Ack then submit request again
135
+ if ((pTransferDescriptor->retry == 0 ) || (pTransferDescriptor->size ==0 ))
136
+ {
137
+ // initialise downward counting retry
138
+ pTransferDescriptor->retry = uRetryCount;
139
+
140
+ // resubmit the request.
141
+ HAL_HCD_HC_SubmitRequest (pHcd, uChannel, pHcd->hc [uChannel].ep_is_in , endpointType, !pTransferDescriptor->setup , (uint8_t *) pTransferDescriptor->currBufPtr , pTransferDescriptor->size , 0 );
142
+ HAL_HCD_EnableInt (pHcd, uChannel);
143
+ }
144
+ }
145
+ break ;
146
+
147
+ case URB_DONE:
148
+ {
149
+ // this will be handled below for USB_TYPE_IDLE
150
+ pTransferDescriptor->state = USB_TYPE_IDLE;
151
+ }
152
+ break ;
153
+
154
+ case URB_ERROR:
155
+ {
156
+ // While USB_TYPE_ERROR in the endpoint state is used to activate error recovery, this value is actually never used.
157
+ // Going here will lead to a timeout at a higher layer, because of ep_queue.get() timeout, which will activate error
158
+ // recovery indirectly.
159
+ pTransferDescriptor->state = USB_TYPE_ERROR;
160
+ }
161
+ break ;
162
+
163
+ default :
164
+ {
165
+ pTransferDescriptor->state = USB_TYPE_PROCESSING;
166
+ }
167
+ break ;
168
+ }
169
+ }
170
+
171
+ if (pTransferDescriptor->state == USB_TYPE_IDLE)
172
+ {
173
+ // Disable retrues
174
+ pTransferDescriptor->retry = 0xffffffff ; // Disable retries
175
+
176
+ // Update transfer descriptor buffer pointer
177
+ pTransferDescriptor->currBufPtr += HAL_HCD_HC_GetXferCount (pHcd, uChannel);
178
+
179
+ // Call transferCompleted on correct object
180
+ void (USBHALHost::*func)(volatile uint32_t addr) = pPriv->transferCompleted ;
181
+ (pPriv->inst ->*func)(reinterpret_cast <std::uintptr_t >(pTransferDescriptor));
182
+ }
183
+ }
184
+ }
185
+ #else
94
186
void HAL_HCD_HC_NotifyURBChange_Callback (HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
95
187
{
96
188
USBHALHost_Private_t *priv = (USBHALHost_Private_t *)(hhcd->pData );
@@ -168,6 +260,7 @@ void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum,
168
260
}
169
261
}
170
262
}
263
+ #endif
171
264
172
265
USBHALHost *USBHALHost::instHost;
173
266
@@ -348,6 +441,41 @@ void USBHALHost::_usbisr(void)
348
441
349
442
void USBHALHost::UsbIrqhandler ()
350
443
{
351
- HAL_HCD_IRQHandler ((HCD_HandleTypeDef *)usb_hcca);
352
- }
444
+ #if ARC_USB_FULL_SIZE
445
+ // fix from Lix Paulian : https://community.st.com/t5/stm32-mcus-products/stm32f4-stm32f7-usb-host-core-interrupt-flood/td-p/436225/page/4
446
+
447
+ // Enable USB_OTG_HCINT_NAK interupts for CTRL and BULK on USB_OTG_GINTSTS_SOF (1ms)
448
+ uint32_t ch_num;
449
+ HCD_HandleTypeDef* hhcd = (HCD_HandleTypeDef *)usb_hcca;
450
+
451
+ if (__HAL_HCD_GET_FLAG (hhcd, USB_OTG_GINTSTS_SOF) && hhcd->Init .dma_enable == 0 )
452
+ {
453
+ for (ch_num = 0 ; ch_num < hhcd->Init .Host_channels ; ch_num++)
454
+ {
455
+ // workaround the interrupts flood issue: re-enable NAK interrupt
456
+ USBx_HC (ch_num)->HCINTMSK |= USB_OTG_HCINT_NAK;
457
+ }
458
+ }
459
+
460
+ HAL_HCD_IRQHandler ((HCD_HandleTypeDef *)usb_hcca);
461
+
462
+ // Disable USB_OTG_HCINT_NAK interupts for CTRL and BULK on USB_OTG_GINTSTS_HCINT
463
+ if (__HAL_HCD_GET_FLAG (hhcd, USB_OTG_GINTSTS_HCINT) && hhcd->Init .dma_enable == 0 )
464
+ {
465
+ for (ch_num = 0 ; ch_num < hhcd->Init .Host_channels ; ch_num++)
466
+ {
467
+ if (USBx_HC (ch_num)->HCINT & USB_OTG_HCINT_NAK)
468
+ {
469
+ if ((hhcd->hc [ch_num].ep_type == EP_TYPE_CTRL) || (hhcd->hc [ch_num].ep_type == EP_TYPE_BULK))
470
+ {
471
+ // workaround the interrupts flood issue: disable NAK interrupt
472
+ USBx_HC (ch_num)->HCINTMSK &= ~USB_OTG_HCINT_NAK;
473
+ }
474
+ }
475
+ }
476
+ }
477
+ #else
478
+ HAL_HCD_IRQHandler ((HCD_HandleTypeDef *)usb_hcca);
353
479
#endif
480
+ }
481
+ #endif
0 commit comments