Add temporary Circle patches to fix USB MS on Pi 3

Temporary for for rsta2/circle#211 until a new version is made
available.
This commit is contained in:
Dale Whinham committed 2021-03-19 23:53:26 +00:00
1 parent b390fd59e3
commit 669284f3d7
3 files changed
+309

No files matched your search

+4
View File
@@ -18,6 +18,8 @@ $(CIRCLE_STDLIB_CONFIG) $(CIRCLE_CONFIG)&:
# Apply patches
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-minimal-usb-drivers.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-pi4-usb-fix.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-usb-fix-hard-errors.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-usb-retry-bulk-transfer.patch
ifeq ($(strip $(GC_SECTIONS)),1)
# Enable function/data sections for circle-stdlib
@@ -117,6 +119,8 @@ clean:
#
veryclean: clean
# Reverse patches
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-usb-retry-bulk-transfer.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-usb-fix-hard-errors.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-pi4-usb-fix.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-minimal-usb-drivers.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.1.7-circle.patch
@@ -0,0 +1,158 @@
From 17e015181d02e4b676204e201a9fb4b8e34f730b Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Mon, 15 Mar 2021 18:20:06 +0100
Subject: [PATCH] usb/usbmassdevice: Fix hard errors in reset recovery
The recovery function did not work at all, because it was never used
before. Now on the RPi 3A+, Zero and probably A+ it is necessary and
has been corrected. Unfortunately this does not solve all problems
with USB flash drive access on these RPi models. Reads or writes may
still fail, but not as often.
Issue #211
---
include/circle/usb/usb.h | 6 ++++-
lib/usb/usbmassdevice.cpp | 50 ++++++++++++++++++++++++++++++++-------
2 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/include/circle/usb/usb.h b/include/circle/usb/usb.h
index 06dfdc9d..4fb61a98 100644
--- a/include/circle/usb/usb.h
+++ b/include/circle/usb/usb.h
@@ -2,7 +2,7 @@
// usb.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2014-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2014-2021 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -84,6 +84,7 @@ PACKED;
#define REQUEST_TO_DEVICE 0
#define REQUEST_TO_INTERFACE 1
+#define REQUEST_TO_ENDPOINT 2
#define REQUEST_TO_OTHER 3
// Standard Request Codes
@@ -95,6 +96,9 @@ PACKED;
#define SET_CONFIGURATION 9
#define SET_INTERFACE 11
+// Standard Feature Selectors
+#define ENDPOINT_HALT 0
+
// Descriptor Types
#define DESCRIPTOR_DEVICE 1
#define DESCRIPTOR_CONFIGURATION 2
diff --git a/lib/usb/usbmassdevice.cpp b/lib/usb/usbmassdevice.cpp
index da631e18..10de3f14 100644
--- a/lib/usb/usbmassdevice.cpp
+++ b/lib/usb/usbmassdevice.cpp
@@ -2,7 +2,7 @@
// usbmassdevice.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2014-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2014-2021 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -28,8 +28,14 @@
#include <circle/new.h>
#include <assert.h>
+#define MAX_TRIES 8 // max. read / write attempts
+
// USB Mass Storage Bulk-Only Transport
+// Class-specific requests
+#define GET_MAX_LUN 0xFE
+#define BULK_ONLY_MASS_STORAGE_RESET 0xFF
+
// Command Block Wrapper
struct TCBW
{
@@ -418,7 +424,7 @@ boolean CUSBBulkOnlyMassStorageDevice::Configure (void)
int CUSBBulkOnlyMassStorageDevice::Read (void *pBuffer, size_t nCount)
{
- unsigned nTries = 4;
+ unsigned nTries = MAX_TRIES;
int nResult;
@@ -443,7 +449,7 @@ int CUSBBulkOnlyMassStorageDevice::Read (void *pBuffer, size_t nCount)
int CUSBBulkOnlyMassStorageDevice::Write (const void *pBuffer, size_t nCount)
{
- unsigned nTries = 4;
+ unsigned nTries = MAX_TRIES;
int nResult;
@@ -629,7 +635,25 @@ int CUSBBulkOnlyMassStorageDevice::Command (void *pCmdBlk, size_t nCmdBlkLen,
{
CLogger::Get ()->Write (FromUmsd, LogError, "CSW transfer failed");
- return -1;
+ if (pHost->ControlMessage (GetEndpoint0 (),
+ REQUEST_TO_ENDPOINT | REQUEST_OUT, CLEAR_FEATURE,
+ ENDPOINT_HALT, m_pEndpointIn->GetNumber () | 0x80,
+ 0, 0) < 0)
+ {
+ CLogger::Get ()->Write (FromUmsd, LogDebug,
+ "Cannot clear halt on endpoint IN");
+
+ return -1;
+ }
+
+ m_pEndpointIn->ResetPID ();
+
+ if (pHost->Transfer (m_pEndpointIn, pCSW, sizeof *pCSW) != (int) sizeof *pCSW)
+ {
+ CLogger::Get ()->Write (FromUmsd, LogError, "CSW transfer failed twice");
+
+ return -1;
+ }
}
if (pCSW->dCSWSignature != CSWSIGNATURE)
@@ -666,23 +690,31 @@ int CUSBBulkOnlyMassStorageDevice::Reset (void)
CUSBHostController *pHost = GetHost ();
assert (pHost != 0);
- if (pHost->ControlMessage (GetEndpoint0 (), 0x21, 0xFF, 0, 0x00, 0, 0) < 0)
+ if (pHost->ControlMessage (GetEndpoint0 (),
+ REQUEST_CLASS | REQUEST_TO_INTERFACE | REQUEST_OUT,
+ BULK_ONLY_MASS_STORAGE_RESET, 0, GetInterfaceNumber (), 0, 0) < 0)
{
CLogger::Get ()->Write (FromUmsd, LogDebug, "Cannot reset device");
return -1;
}
- if (pHost->ControlMessage (GetEndpoint0 (), 0x02, 1, 0, 1, 0, 0) < 0)
+ CTimer::Get ()->MsDelay (100);
+
+ if (pHost->ControlMessage (GetEndpoint0 (),
+ REQUEST_TO_ENDPOINT | REQUEST_OUT, CLEAR_FEATURE,
+ ENDPOINT_HALT, m_pEndpointIn->GetNumber () | 0x80, 0, 0) < 0)
{
- CLogger::Get ()->Write (FromUmsd, LogDebug, "Cannot clear halt on endpoint 1");
+ CLogger::Get ()->Write (FromUmsd, LogDebug, "Cannot clear halt on endpoint IN");
return -1;
}
- if (pHost->ControlMessage (GetEndpoint0 (), 0x02, 1, 0, 2, 0, 0) < 0)
+ if (pHost->ControlMessage (GetEndpoint0 (),
+ REQUEST_TO_ENDPOINT | REQUEST_OUT, CLEAR_FEATURE,
+ ENDPOINT_HALT, m_pEndpointOut->GetNumber (), 0, 0) < 0)
{
- CLogger::Get ()->Write (FromUmsd, LogDebug, "Cannot clear halt on endpoint 2");
+ CLogger::Get ()->Write (FromUmsd, LogDebug, "Cannot clear halt on endpoint OUT");
return -1;
}
@@ -0,0 +1,147 @@
From 88240494fa02a09cbebd94a3ce35d87303cd0a0e Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Thu, 18 Mar 2021 13:12:06 +0100
Subject: [PATCH] usb/dwhcidevice: Retry bulk transfers on xact error
The access to some (especially USB 3.0) flash drives on RPi 3A+ and
Zero was not reliable before, because xact errors occurred from time
to time. Now transfers will be automatically retried several times,
if such an error occurs on a bulk endpoint.
Issue #211
---
include/circle/usb/dwhcixferstagedata.h | 4 +++-
lib/usb/dwhcidevice.cpp | 17 ++++++++++++++++-
lib/usb/dwhcixferstagedata.cpp | 25 +++++++++++++++++++++++--
3 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/include/circle/usb/dwhcixferstagedata.h b/include/circle/usb/dwhcixferstagedata.h
index 5300c74c..8890cdfb 100644
--- a/include/circle/usb/dwhcixferstagedata.h
+++ b/include/circle/usb/dwhcixferstagedata.h
@@ -2,7 +2,7 @@
// dwhcixferstagedata.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2014-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2014-2021 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -80,6 +80,7 @@ class CDWHCITransferStageData
boolean IsStageComplete (void) const;
u32 GetResultLen (void) const;
boolean IsTimeout (void) const;
+ boolean IsRetryOK (void) const;
CUSBRequest *GetURB (void) const;
CUSBDevice *GetDevice (void) const;
@@ -109,6 +110,7 @@ class CDWHCITransferStageData
unsigned m_nState;
unsigned m_nSubState;
u32 m_nTransactionStatus;
+ unsigned m_nErrorCount;
u32 *m_pTempBuffer;
void *m_pBufferPointer;
diff --git a/lib/usb/dwhcidevice.cpp b/lib/usb/dwhcidevice.cpp
index c59c5fab..79b22268 100644
--- a/lib/usb/dwhcidevice.cpp
+++ b/lib/usb/dwhcidevice.cpp
@@ -1064,7 +1064,22 @@ void CDWHCIDevice::ChannelInterruptHandler (unsigned nChannel)
{
case StageStateNoSplitTransfer:
nStatus = pStageData->GetTransactionStatus ();
- if (nStatus & DWHCI_HOST_CHAN_INT_ERROR_MASK)
+ if ( (nStatus & DWHCI_HOST_CHAN_INT_XACT_ERROR)
+ && pURB->GetEndpoint ()->GetType () == EndpointTypeBulk
+ && pStageData->IsRetryOK ())
+ {
+#ifndef USE_USB_SOF_INTR
+ StartTransaction (pStageData);
+#else
+ m_pStageData[nChannel] = 0;
+ FreeChannel (nChannel);
+
+ QueueTransaction (pStageData);
+#endif
+
+ break;
+ }
+ else if (nStatus & DWHCI_HOST_CHAN_INT_ERROR_MASK)
{
CLogger::Get ()->Write (FromDWHCI, LogError,
"Transaction failed (status 0x%X)", nStatus);
diff --git a/lib/usb/dwhcixferstagedata.cpp b/lib/usb/dwhcixferstagedata.cpp
index 63cf64eb..32f3f356 100644
--- a/lib/usb/dwhcixferstagedata.cpp
+++ b/lib/usb/dwhcixferstagedata.cpp
@@ -2,7 +2,7 @@
// dwhcixferstagedata.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2014-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2014-2021 R. Stange <rsta2@o2online.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -27,6 +27,8 @@
#include <circle/timer.h>
#include <assert.h>
+#define MAX_BULK_TRIES 8
+
CDWHCITransferStageData::CDWHCITransferStageData (unsigned nChannel,
CUSBRequest *pURB,
boolean bIn,
@@ -42,6 +44,7 @@ CDWHCITransferStageData::CDWHCITransferStageData (unsigned nChannel,
m_nState (0),
m_nSubState (0),
m_nTransactionStatus (0),
+ m_nErrorCount (0),
m_pTempBuffer (0),
m_nStartTicksHZ (0),
m_pFrameScheduler (0)
@@ -186,9 +189,17 @@ void CDWHCITransferStageData::TransactionComplete (u32 nStatus, u32 nPacketsLeft
assert (m_bIn);
m_nPackets = 0; // no data is available, complete transfer
+
+ return;
}
- return;
+ // bulk transfers with xact error will be retried, return otherwise
+ if ( !(nStatus & DWHCI_HOST_CHAN_INT_XACT_ERROR)
+ || m_pEndpoint->GetType () != EndpointTypeBulk
+ || ++m_nErrorCount > MAX_BULK_TRIES)
+ {
+ return;
+ }
}
u32 nPacketsTransfered = m_nPacketsPerTransaction - nPacketsLeft;
@@ -214,6 +225,11 @@ void CDWHCITransferStageData::TransactionComplete (u32 nStatus, u32 nPacketsLeft
assert (nPacketsTransfered <= m_nPackets);
m_nPackets -= nPacketsTransfered;
+ if (!m_bSplitTransaction)
+ {
+ m_nPacketsPerTransaction = m_nPackets;
+ }
+
// if (m_nTotalBytesTransfered > m_nTransferSize) this will be false:
if (m_nTransferSize - m_nTotalBytesTransfered < m_nBytesPerTransaction)
{
@@ -490,6 +506,11 @@ boolean CDWHCITransferStageData::IsTimeout (void) const
return CTimer::Get ()->GetTicks ()-m_nStartTicksHZ >= m_nTimeoutHZ ? TRUE : FALSE;
}
+boolean CDWHCITransferStageData::IsRetryOK (void) const
+{
+ return m_nErrorCount <= MAX_BULK_TRIES;
+}
+
CUSBRequest *CDWHCITransferStageData::GetURB (void) const
{
assert (m_pURB != 0);