Skip to content

Commit 3672be0

Browse files
committed
Initial version
1 parent 782ede3 commit 3672be0

File tree

3 files changed

+130
-5
lines changed

3 files changed

+130
-5
lines changed

Diff for: src/USBHost/USBHostConf.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
#ifndef USBHOST_CONF_H
1818
#define USBHOST_CONF_H
1919

20-
#define ARC_USB_FULL_SIZE (1)
20+
#define ARC_USB_FULL_SIZE (0)
21+
#define ARC_FS_OVER_HS (1)
2122

2223
#include "mbed_config.h"
2324
#include "Callback.h"

Diff for: src/targets/TARGET_STM/USBEndpoint_STM.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,28 @@ USB_TYPE USBEndpoint::queueTransfer()
178178
}
179179
ep_queue.get(0);
180180
MBED_ASSERT(*addr == 0);
181-
#if ARC_USB_FULL_SIZE
181+
182+
#if ARC_FS_OVER_HS
183+
//
184+
// In the underlying HAL code there are the following issues when running FS using the HS interface:
185+
// This effects the GIGA as it has no external PHY which is required in order to run at HS.
186+
//
187+
// 1. Transmitting length larger then packetsize can cause future issues reading, the NAK nightmare.
188+
// 2. Receiving multiple seperate packets can lead to lost data and the need to retry.
189+
//
190+
// So for transmitting we split the data into sizes of <= packet size, we initially set of a single transfer here
191+
// and HAL_HCD_HC_NotifyURBChange_Callback() will then handle subsequent transfers if needed.
192+
//
193+
// For receiving we receive all the data.
194+
//
195+
if(dir == OUT)
196+
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
197+
else
198+
transfer_len = td_current->size;
199+
#elif ARC_USB_FULL_SIZE
182200
transfer_len = td_current->size;
183201
#else
184-
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
202+
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
185203
#endif
186204

187205
buf_start = (uint8_t *)td_current->currBufPtr;

Diff for: src/targets/TARGET_STM/USBHALHost_STM.cpp

+108-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,113 @@ uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chnum)
9191
// - URB_NOTREADY = a NAK, NYET, or not more than a couple of repeats of some of the errors that will
9292
// become URB_ERROR if they repeat several times in a row
9393
//
94-
#if ARC_USB_FULL_SIZE
94+
#if ARC_FS_OVER_HS
95+
//
96+
// In the underlying HAL code there are the following issues when running FS using the HS interface:
97+
// This effects the GIGA as it has no external PHY which is required in order to run at HS.
98+
//
99+
// 1. Transmitting length larger then packetsize can cause future issues reading, the NAK nightmare.
100+
// 2. Receiving multiple seperate packets can lead to lost data and the need to retry.
101+
//
102+
// So for transmitting we split the data into sizes of <= packet size and individually transfer them, only calling pPriv->transferCompleted() when all data is sent.
103+
// For receiving we receive all the data and call pPriv->transferCompleted().
104+
//
105+
// If we get NAKS on the control OUT EPs we make sure that USB_OTG_HCCHAR_CHDIS ans USB_OTG_HCCHAR_CHENA are reset to the correct values.
106+
//
107+
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *pHcd, uint8_t uChannel, HCD_URBStateTypeDef urbState)
108+
{
109+
USBHALHost_Private_t *pPriv = (USBHALHost_Private_t *)(pHcd->pData);
110+
111+
HCTD *pTransferDescriptor = (HCTD *)pPriv->addr[uChannel];
112+
113+
114+
if (pTransferDescriptor)
115+
{
116+
uint32_t endpointType = pHcd->hc[uChannel].ep_type;
117+
118+
if ((endpointType == EP_TYPE_INTR))
119+
{
120+
// Disable the channel interrupt and retransfer below
121+
// TOD: really this retransfer should be queued up and transfered on the SOF interupt based on interval from descriptor.
122+
pTransferDescriptor->state = USB_TYPE_IDLE ;
123+
HAL_HCD_DisableInt(pHcd, uChannel);
124+
}
125+
else if ((endpointType == EP_TYPE_BULK) || (endpointType == EP_TYPE_CTRL))
126+
{
127+
uint8_t uEpIsInput = pHcd->hc[uChannel].ep_is_in;
128+
129+
switch(urbState)
130+
{
131+
case URB_NOTREADY:
132+
{
133+
if(!uEpIsInput)
134+
{
135+
// make sure that USB_OTG_HCCHAR_CHDIS and USB_OTG_HCCHAR_CHENA are reset to the correct values
136+
uint32_t tmpreg;
137+
tmpreg = USBx_HC(uChannel)->HCCHAR;
138+
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
139+
tmpreg |= USB_OTG_HCCHAR_CHENA;
140+
USBx_HC(uChannel)->HCCHAR = tmpreg;
141+
}
142+
}
143+
break;
144+
145+
case URB_DONE:
146+
{
147+
// first calculate how much we transferred, HAL metrics aonly work for IN EPs
148+
uint16_t uPacketSize = pHcd->hc[uChannel].max_packet;
149+
uint16_t uTransferredCount;
150+
151+
if(uEpIsInput)
152+
uTransferredCount = HAL_HCD_HC_GetXferCount(pHcd, uChannel);
153+
else
154+
uTransferredCount = (pTransferDescriptor->size > uPacketSize) ? uPacketSize : pTransferDescriptor->size;
155+
156+
// update transfer descriptor
157+
pTransferDescriptor->size -= uTransferredCount;
158+
pTransferDescriptor->currBufPtr += uTransferredCount;
159+
160+
// if we are an OUT EP and there is still more data, send next packet
161+
if(!uEpIsInput && pTransferDescriptor->size )
162+
{
163+
uint16_t uTransferSize = (pTransferDescriptor->size > uPacketSize) ? uPacketSize : pTransferDescriptor->size;
164+
HAL_HCD_HC_SubmitRequest(pHcd, uChannel, uEpIsInput, endpointType, !pTransferDescriptor->setup, (uint8_t *) pTransferDescriptor->currBufPtr, uTransferSize, 0);
165+
HAL_HCD_EnableInt(pHcd, uChannel);
166+
}
167+
else
168+
{
169+
// this will be handled below for USB_TYPE_IDLE
170+
pTransferDescriptor->state = USB_TYPE_IDLE;
171+
}
172+
}
173+
break;
174+
175+
case URB_ERROR:
176+
{
177+
// While USB_TYPE_ERROR in the endpoint state is used to activate error recovery, this value is actually never used.
178+
// Going here will lead to a timeout at a higher layer, because of ep_queue.get() timeout, which will activate error
179+
// recovery indirectly.
180+
pTransferDescriptor->state = USB_TYPE_ERROR;
181+
}
182+
break;
183+
184+
default:
185+
{
186+
pTransferDescriptor->state = USB_TYPE_PROCESSING;
187+
}
188+
break;
189+
}
190+
}
191+
192+
if (pTransferDescriptor->state == USB_TYPE_IDLE)
193+
{
194+
// Call transferCompleted on correct object
195+
void (USBHALHost::*func)(volatile uint32_t addr) = pPriv->transferCompleted;
196+
(pPriv->inst->*func)(reinterpret_cast<std::uintptr_t>(pTransferDescriptor));
197+
}
198+
}
199+
}
200+
#elif ARC_USB_FULL_SIZE
95201
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *pHcd, uint8_t uChannel, HCD_URBStateTypeDef urbState)
96202
{
97203
USBHALHost_Private_t *pPriv = (USBHALHost_Private_t *)(pHcd->pData);
@@ -442,7 +548,7 @@ void USBHALHost::_usbisr(void)
442548

443549
void USBHALHost::UsbIrqhandler()
444550
{
445-
#if ARC_USB_FULL_SIZE
551+
#if ARC_USB_FULL_SIZE || ARC_FS_OVER_HS
446552
// fix from Lix Paulian : https://community.st.com/t5/stm32-mcus-products/stm32f4-stm32f7-usb-host-core-interrupt-flood/td-p/436225/page/4
447553
// Change to also stop flooding of channel halt interrupt
448554
uint32_t ch_num;

0 commit comments

Comments
 (0)