Skip to content

Fs over hs #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/USBHost/USBHostConf.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
#ifndef USBHOST_CONF_H
#define USBHOST_CONF_H

#define ARC_USB_FULL_SIZE (1)
#define ARC_USB_FULL_SIZE (0)
#define ARC_FS_OVER_HS (1)
#define ARC_NO_RESUBMITREQUEST (0)

#include "mbed_config.h"
#include "Callback.h"
Expand Down
22 changes: 20 additions & 2 deletions src/targets/TARGET_STM/USBEndpoint_STM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,28 @@ USB_TYPE USBEndpoint::queueTransfer()
}
ep_queue.get(0);
MBED_ASSERT(*addr == 0);
#if ARC_USB_FULL_SIZE

#if ARC_FS_OVER_HS
//
// In the underlying HAL code there are the following issues when running FS using the HS interface:
// This effects the GIGA as it has no external PHY which is required in order to run at HS.
//
// 1. Transmitting length larger then packetsize can cause future issues reading, the NAK nightmare.
// 2. Receiving multiple seperate packets can lead to lost data and the need to retry.
//
// So for transmitting we split the data into sizes of <= packet size, we initially set of a single transfer here
Comment on lines +185 to +190
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// This effects the GIGA as it has no external PHY which is required in order to run at HS.
//
// 1. Transmitting length larger then packetsize can cause future issues reading, the NAK nightmare.
// 2. Receiving multiple seperate packets can lead to lost data and the need to retry.
//
// So for transmitting we split the data into sizes of <= packet size, we initially set of a single transfer here
// This affects the GIGA as it has no external PHY which is required in order to run at HS.
//
// 1. Transmitting length larger than packetsize can cause future issues reading, the NAK nightmare.
// 2. Receiving multiple separate packets can lead to lost data and the need to retry.
//
// So for transmitting we split the data into sizes of <= packet size, we initially set off a single transfer here

Fix typos in comment

// and HAL_HCD_HC_NotifyURBChange_Callback() will then handle subsequent transfers if needed.
//
// For receiving we receive all the data.
//
if(dir == OUT)
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
else
transfer_len = td_current->size;
#elif ARC_USB_FULL_SIZE
transfer_len = td_current->size;
#else
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
#endif

buf_start = (uint8_t *)td_current->currBufPtr;
Expand Down
119 changes: 117 additions & 2 deletions src/targets/TARGET_STM/USBHALHost_STM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,122 @@ uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chnum)
// - URB_NOTREADY = a NAK, NYET, or not more than a couple of repeats of some of the errors that will
// become URB_ERROR if they repeat several times in a row
//
#if ARC_USB_FULL_SIZE
#if ARC_FS_OVER_HS
//
// In the underlying HAL code there are the following issues when running FS using the HS interface:
// This effects the GIGA as it has no external PHY which is required in order to run at HS.
//
// 1. Transmitting length larger then packetsize can cause future issues reading, the NAK nightmare.
// 2. Receiving multiple seperate packets can lead to lost data and the need to retry.
//
// 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.
// For receiving we receive all the data and call pPriv->transferCompleted().
//
// 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.
Comment on lines +97 to +105
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// This effects the GIGA as it has no external PHY which is required in order to run at HS.
//
// 1. Transmitting length larger then packetsize can cause future issues reading, the NAK nightmare.
// 2. Receiving multiple seperate packets can lead to lost data and the need to retry.
//
// 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.
// For receiving we receive all the data and call pPriv->transferCompleted().
//
// 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.
// This affects the GIGA as it has no external PHY which is required in order to run at HS.
//
// 1. Transmitting length larger than packetsize can cause future issues reading, the NAK nightmare.
// 2. Receiving multiple separate packets can lead to lost data and the need to retry.
//
// 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.
// For receiving we receive all the data and call pPriv->transferCompleted().
//
// If we get NAKS on the control OUT EPs we make sure that USB_OTG_HCCHAR_CHDIS and USB_OTG_HCCHAR_CHENA are reset to the correct values.

//
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *pHcd, uint8_t uChannel, HCD_URBStateTypeDef urbState)
{
USBHALHost_Private_t *pPriv = (USBHALHost_Private_t *)(pHcd->pData);

HCTD *pTransferDescriptor = (HCTD *)pPriv->addr[uChannel];


if (pTransferDescriptor)
{
uint32_t endpointType = pHcd->hc[uChannel].ep_type;

if ((endpointType == EP_TYPE_INTR))
{
// Disable the channel interrupt and retransfer below
// TOD: really this retransfer should be queued up and transfered on the SOF interupt based on interval from descriptor.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// TOD: really this retransfer should be queued up and transfered on the SOF interupt based on interval from descriptor.
// TOD: really this retransfer should be queued up and transferred on the SOF interrupt based on interval from descriptor.

pTransferDescriptor->state = USB_TYPE_IDLE ;
HAL_HCD_DisableInt(pHcd, uChannel);
pTransferDescriptor->currBufPtr += HAL_HCD_HC_GetXferCount(pHcd, uChannel);
}
else if ((endpointType == EP_TYPE_BULK) || (endpointType == EP_TYPE_CTRL))
{
uint8_t uEpIsInput = pHcd->hc[uChannel].ep_is_in;

switch(urbState)
{
case URB_NOTREADY:
{
if(!uEpIsInput)
{
#if ARC_NO_RESUBMITREQUEST
// make sure that USB_OTG_HCCHAR_CHDIS and USB_OTG_HCCHAR_CHENA are reset to the correct values
uint32_t tmpreg;
tmpreg = USBx_HC(uChannel)->HCCHAR;
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
tmpreg |= USB_OTG_HCCHAR_CHENA;
USBx_HC(uChannel)->HCCHAR = tmpreg;
Comment on lines +138 to +142
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uint32_t tmpreg;
tmpreg = USBx_HC(uChannel)->HCCHAR;
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
tmpreg |= USB_OTG_HCCHAR_CHENA;
USBx_HC(uChannel)->HCCHAR = tmpreg;
uint32_t tmpreg;
tmpreg = USBx_HC(uChannel)->HCCHAR;
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
tmpreg |= USB_OTG_HCCHAR_CHENA;
USBx_HC(uChannel)->HCCHAR = tmpreg;

Use spaces instead of tabs for indentation, as is done throughout the rest of the file.

#else
// Submit the same request again, because the device wasn't ready to accept the last one
uint16_t uPacketSize = pHcd->hc[uChannel].max_packet;
uint16_t uTransferSize = (pTransferDescriptor->size > uPacketSize) ? uPacketSize : pTransferDescriptor->size;
HAL_HCD_HC_SubmitRequest(pHcd, uChannel, uEpIsInput, endpointType, !pTransferDescriptor->setup, (uint8_t *) pTransferDescriptor->currBufPtr, uTransferSize, 0);
HAL_HCD_EnableInt(pHcd, uChannel);
#endif
}
}
break;

case URB_DONE:
{
// first calculate how much we transferred, HAL metrics aonly work for IN EPs
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// first calculate how much we transferred, HAL metrics aonly work for IN EPs
// first calculate how much we transferred, HAL metrics only work for IN EPs

uint16_t uPacketSize = pHcd->hc[uChannel].max_packet;
uint16_t uTransferredCount;

if(uEpIsInput)
uTransferredCount = HAL_HCD_HC_GetXferCount(pHcd, uChannel);
else
uTransferredCount = (pTransferDescriptor->size > uPacketSize) ? uPacketSize : pTransferDescriptor->size;

// update transfer descriptor
pTransferDescriptor->size -= uTransferredCount;
pTransferDescriptor->currBufPtr += uTransferredCount;

// if we are an OUT EP and there is still more data, send next packet
if(!uEpIsInput && pTransferDescriptor->size )
{
uint16_t uTransferSize = (pTransferDescriptor->size > uPacketSize) ? uPacketSize : pTransferDescriptor->size;
HAL_HCD_HC_SubmitRequest(pHcd, uChannel, uEpIsInput, endpointType, !pTransferDescriptor->setup, (uint8_t *) pTransferDescriptor->currBufPtr, uTransferSize, 0);
HAL_HCD_EnableInt(pHcd, uChannel);
}
else
{
// this will be handled below for USB_TYPE_IDLE
pTransferDescriptor->state = USB_TYPE_IDLE;
}
}
break;

case URB_ERROR:
{
// While USB_TYPE_ERROR in the endpoint state is used to activate error recovery, this value is actually never used.
// Going here will lead to a timeout at a higher layer, because of ep_queue.get() timeout, which will activate error
// recovery indirectly.
pTransferDescriptor->state = USB_TYPE_ERROR;
}
break;

default:
{
pTransferDescriptor->state = USB_TYPE_PROCESSING;
}
break;
}
}

if (pTransferDescriptor->state == USB_TYPE_IDLE)
{
// Call transferCompleted on correct object
void (USBHALHost::*func)(volatile uint32_t addr) = pPriv->transferCompleted;
(pPriv->inst->*func)(reinterpret_cast<std::uintptr_t>(pTransferDescriptor));
}
}
}
#elif ARC_USB_FULL_SIZE
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *pHcd, uint8_t uChannel, HCD_URBStateTypeDef urbState)
{
USBHALHost_Private_t *pPriv = (USBHALHost_Private_t *)(pHcd->pData);
Expand Down Expand Up @@ -442,7 +557,7 @@ void USBHALHost::_usbisr(void)

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