Update to circle-stdlib v15.7/Circle Step 44

This commit is contained in:
Dale Whinham committed 2021-06-25 23:57:13 +01:00
1 parent 7a04338cd2
commit 25c5d654bc
13 files changed
+4 -2412

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Update to circle-stdlib v15.7/Circle Step 44.
- Update to libmt32emu v2.5.0.
- Update to FluidSynth v2.2.1.
- The activity LED no longer illuminates for System Common or System Real-Time messages.
+2 -20
View File
@@ -16,16 +16,7 @@ $(CIRCLE_STDLIB_CONFIG) $(CIRCLE_CONFIG)&:
$(CIRCLESTDLIBHOME)/configure --raspberrypi=$(RASPBERRYPI) --prefix=$(PREFIX)
# 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
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-usb-low-speed-bulk-fix.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-move-dma-defines.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-add-parity32.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-add-iec958.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-add-hdmi-sound-base.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-allow-any-screen-size.patch
@patch -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-44-minimal-usb-drivers.patch
ifeq ($(strip $(GC_SECTIONS)),1)
# Enable function/data sections for circle-stdlib
@@ -123,16 +114,7 @@ clean:
#
veryclean: clean
# Reverse patches
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-allow-any-screen-size.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-add-hdmi-sound-base.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-add-iec958.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-add-parity32.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-move-dma-defines.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(CIRCLEHOME) < patches/circle-43.3-usb-low-speed-bulk-fix.patch
@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 $(CIRCLEHOME) < patches/circle-44-minimal-usb-drivers.patch
@patch -R -N -p1 --no-backup-if-mismatch -r - -d $(FLUIDSYNTHHOME) < patches/fluidsynth-2.2.1-circle.patch
# Clean circle-stdlib
File diff suppressed because it is too large. Load diff
-190
View File
@@ -1,190 +0,0 @@
From 68ae9ec6cce5d5c37e21cada0093200f22ef2d77 Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Sun, 28 Mar 2021 14:55:15 +0200
Subject: [PATCH] soundbasedevice: Add IEC958 (S/PDIF) hardware format
---
include/circle/soundbasedevice.h | 11 ++++-
lib/soundbasedevice.cpp | 85 +++++++++++++++++++++++++++++++-
2 files changed, 93 insertions(+), 3 deletions(-)
diff --git a/include/circle/soundbasedevice.h b/include/circle/soundbasedevice.h
index 07a6686c..6b254e7c 100644
--- a/include/circle/soundbasedevice.h
+++ b/include/circle/soundbasedevice.h
@@ -2,7 +2,7 @@
// soundbasedevice.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2017-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2017-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,12 +28,19 @@
#define SOUND_MAX_SAMPLE_SIZE (sizeof (u32))
#define SOUND_MAX_FRAME_SIZE (SOUND_HW_CHANNELS * SOUND_MAX_SAMPLE_SIZE)
+// IEC958 (S/PDIF)
+#define IEC958_FRAMES_PER_BLOCK 192
+#define IEC958_SUBFRAMES_PER_BLOCK (SOUND_HW_CHANNELS * IEC958_FRAMES_PER_BLOCK)
+#define IEC958_STATUS_BYTES 5
+#define IEC958_B_FRAME_PREAMBLE 0x0F
+
enum TSoundFormat /// All supported formats are interleaved little endian
{
SoundFormatUnsigned8, /// Not supported as hardware format
SoundFormatSigned16,
SoundFormatSigned24,
SoundFormatUnsigned32, /// Not supported as write format
+ SoundFormatIEC958, /// Not supported as write format
SoundFormatUnknown
};
@@ -168,6 +175,8 @@ class CSoundBaseDevice : public CDevice /// Base class of sound devices
void *m_pCallbackParam;
CSpinLock m_SpinLock;
+
+ u8 m_uchIEC958Status[IEC958_STATUS_BYTES];
};
#endif
diff --git a/lib/soundbasedevice.cpp b/lib/soundbasedevice.cpp
index b156239b..d3788495 100644
--- a/lib/soundbasedevice.cpp
+++ b/lib/soundbasedevice.cpp
@@ -2,7 +2,7 @@
// soundbasedevice.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2017-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2017-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
@@ -18,6 +18,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <circle/soundbasedevice.h>
+#include <circle/macros.h>
#include <circle/util.h>
#include <assert.h>
@@ -46,6 +47,7 @@ CSoundBaseDevice::CSoundBaseDevice (TSoundFormat HWFormat, u32 nRange32, unsigne
break;
case SoundFormatSigned24:
+ case SoundFormatIEC958:
m_nHWSampleSize = sizeof (u32);
m_nRangeMin = -(1 << 23)+1;
m_nRangeMax = (1 << 23)-1;
@@ -67,6 +69,33 @@ CSoundBaseDevice::CSoundBaseDevice (TSoundFormat HWFormat, u32 nRange32, unsigne
}
m_nHWFrameSize = SOUND_HW_CHANNELS * m_nHWSampleSize;
+
+ if (m_HWFormat == SoundFormatIEC958)
+ {
+ u8 uchFS, uchOrigFS;
+ switch (m_nSampleRate)
+ {
+ case 22050: uchFS = 4; uchOrigFS = 11; break;
+ case 24000: uchFS = 6; uchOrigFS = 9; break;
+ case 32000: uchFS = 3; uchOrigFS = 12; break;
+ case 44100: uchFS = 0; uchOrigFS = 15; break;
+ case 48000: uchFS = 2; uchOrigFS = 13; break;
+ case 88200: uchFS = 8; uchOrigFS = 7; break;
+ case 96000: uchFS = 10; uchOrigFS = 5; break;
+ case 176400: uchFS = 12; uchOrigFS = 3; break;
+ case 192000: uchFS = 14; uchOrigFS = 1; break;
+
+ default:
+ assert (0);
+ break;
+ }
+
+ m_uchIEC958Status[0] = 0b100; // consumer, PCM, no copyright, no pre-emphasis
+ m_uchIEC958Status[1] = 0; // category (general mode)
+ m_uchIEC958Status[2] = 0; // source number, take no account of channel number
+ m_uchIEC958Status[3] = uchFS; // sampling frequency
+ m_uchIEC958Status[4] = 0b1011 | (uchOrigFS << 4); // 24 bit samples, original freq.
+ }
}
CSoundBaseDevice::~CSoundBaseDevice (void)
@@ -279,7 +308,8 @@ unsigned CSoundBaseDevice::GetChunk (s16 *pBuffer, unsigned nChunkSize)
unsigned CSoundBaseDevice::GetChunk (u32 *pBuffer, unsigned nChunkSize)
{
assert ( m_HWFormat == SoundFormatSigned24
- || m_HWFormat == SoundFormatUnsigned32);
+ || m_HWFormat == SoundFormatUnsigned32
+ || m_HWFormat == SoundFormatIEC958);
return GetChunkInternal (pBuffer, nChunkSize);
}
@@ -340,6 +370,18 @@ void CSoundBaseDevice::ConvertSoundFormat (void *pTo, const void *pFrom)
*pValue = (u32) llValue;
} break;
+ case SoundFormatIEC958: {
+ nValue >>= 4;
+ nValue &= 0xFFFFFF0;
+ if (parity32 (nValue))
+ {
+ nValue |= 0x80000000;
+ }
+
+ s32 *pValue = reinterpret_cast<s32 *> (pTo);
+ *pValue = nValue;
+ } break;
+
default:
assert (0);
break;
@@ -382,6 +424,45 @@ unsigned CSoundBaseDevice::GetChunkInternal (void *pBuffer, unsigned nChunkSize)
nBytes += m_nHWFrameSize;
}
+ // insert control channel and parity bits, and preamble into IEC958 block
+ if (m_HWFormat == SoundFormatIEC958)
+ {
+ u32 *pBuffer32 = static_cast<u32 *> (pBuffer);
+
+ unsigned i;
+ for (i = 0; i < nChunkSize; i += IEC958_SUBFRAMES_PER_BLOCK)
+ {
+ unsigned j;
+ for (j = 0; j < IEC958_STATUS_BYTES * 8 * SOUND_HW_CHANNELS; j++)
+ {
+ u32 *pSubFrame = &pBuffer32[i + j];
+
+ unsigned nFrame = j / SOUND_HW_CHANNELS;
+ if (m_uchIEC958Status[nFrame / 8] & BIT(nFrame % 8))
+ {
+ u32 nValue = *pSubFrame;
+
+ nValue |= 0x40000000;
+
+ nValue &= 0x7FFFFFFF;
+ if (parity32 (nValue))
+ {
+ nValue |= 0x80000000;
+ }
+
+ *pSubFrame = nValue;
+ }
+
+ if (nFrame == 0)
+ {
+ *pSubFrame |= IEC958_B_FRAME_PREAMBLE;
+ }
+ }
+ }
+
+ assert (i == nChunkSize); // nChunkSize must be a multiple of 384
+ }
+
if ( m_pCallback != 0
&& nQueueBytesAvail < m_nNeedDataThreshold)
{
-52
View File
@@ -1,52 +0,0 @@
From ae0a7b847fbfdc8631ebeec8e5c821c3127dd32c Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Sun, 28 Mar 2021 14:48:17 +0200
Subject: [PATCH] util: Add parity32()
---
include/circle/util.h | 6 ++++++
lib/util.cpp | 17 +++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/include/circle/util.h b/include/circle/util.h
index c7075a8a..86c08476 100644
--- a/include/circle/util.h
+++ b/include/circle/util.h
@@ -78,6 +78,12 @@ u32 bswap32 (u32 ulValue);
#define be2le16 bswap16
#define be2le32 bswap32
+#if !defined (__GNUC__) || (AARCH == 32 && STDLIB_SUPPORT == 0)
+ int parity32 (unsigned nValue); // returns number of ones % 1
+#else
+ #define parity32 __builtin_parity
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/util.cpp b/lib/util.cpp
index fa4d51a2..0ca3b6cf 100644
--- a/lib/util.cpp
+++ b/lib/util.cpp
@@ -721,3 +721,20 @@ u32 bswap32 (u32 ulValue)
}
#endif
+
+#if !defined (__GNUC__) || (AARCH == 32 && STDLIB_SUPPORT == 0)
+
+int parity32 (unsigned nValue)
+{
+ int nResult = 0;
+
+ while (nValue != 0)
+ {
+ nResult ^= (nValue & 1);
+ nValue >>= 1;
+ }
+
+ return nResult;
+}
+
+#endif
@@ -1,42 +0,0 @@
From 127c03b88d281f1e9ee0c3e000e844bd59ff6098 Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Mon, 26 Apr 2021 10:29:45 +0200
Subject: [PATCH] koptions: Allow to set any screen size
---
lib/koptions.cpp | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/lib/koptions.cpp b/lib/koptions.cpp
index 5f2cc34d..978e266e 100644
--- a/lib/koptions.cpp
+++ b/lib/koptions.cpp
@@ -2,7 +2,7 @@
// koptions.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
@@ -64,8 +64,7 @@ CKernelOptions::CKernelOptions (void)
if (strcmp (pOption, "width") == 0)
{
unsigned nValue;
- if ( (nValue = GetDecimal (pValue)) != INVALID_VALUE
- && 640 <= nValue && nValue <= 1980)
+ if ((nValue = GetDecimal (pValue)) != INVALID_VALUE)
{
m_nWidth = nValue;
}
@@ -73,8 +72,7 @@ CKernelOptions::CKernelOptions (void)
else if (strcmp (pOption, "height") == 0)
{
unsigned nValue;
- if ( (nValue = GetDecimal (pValue)) != INVALID_VALUE
- && 480 <= nValue && nValue <= 1080)
+ if ((nValue = GetDecimal (pValue)) != INVALID_VALUE)
{
m_nHeight = nValue;
}
-279
View File
@@ -1,279 +0,0 @@
From 5bc33c66eb4875852f4ebf750ee16107b23e1bfb Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Fri, 26 Mar 2021 07:42:19 +0100
Subject: [PATCH] Move defines for DMA controller to dmacommon.h
---
include/circle/dmacommon.h | 49 +++++++++++++++++++++++++++++++++++++-
lib/dmachannel.cpp | 45 +---------------------------------
lib/i2ssoundbasedevice.cpp | 48 +------------------------------------
lib/pwmsoundbasedevice.cpp | 48 +------------------------------------
4 files changed, 51 insertions(+), 139 deletions(-)
diff --git a/include/circle/dmacommon.h b/include/circle/dmacommon.h
index f50a74dc..56599352 100644
--- a/include/circle/dmacommon.h
+++ b/include/circle/dmacommon.h
@@ -2,7 +2,7 @@
/// \file dmacommon.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
@@ -20,6 +20,7 @@
#ifndef _circle_dmacommon_h
#define _circle_dmacommon_h
+#include <circle/bcm2835.h>
#include <circle/types.h>
enum TDREQ
@@ -40,4 +41,50 @@ enum TDREQ
typedef void TDMACompletionRoutine (unsigned nChannel, boolean bStatus, void *pParam);
+//
+// Legacy platform DMA controller
+//
+#define ARM_DMACHAN_CS(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x00)
+ #define CS_RESET (1 << 31)
+ #define CS_ABORT (1 << 30)
+ #define CS_WAIT_FOR_OUTSTANDING_WRITES (1 << 28)
+ #define CS_PANIC_PRIORITY_SHIFT 20
+ #define DEFAULT_PANIC_PRIORITY 15
+ #define CS_PRIORITY_SHIFT 16
+ #define DEFAULT_PRIORITY 1
+ #define CS_ERROR (1 << 8)
+ #define CS_INT (1 << 2)
+ #define CS_END (1 << 1)
+ #define CS_ACTIVE (1 << 0)
+#define ARM_DMACHAN_CONBLK_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x04)
+#define ARM_DMACHAN_TI(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x08)
+ #define TI_PERMAP_SHIFT 16
+ #define TI_BURST_LENGTH_SHIFT 12
+ #define DEFAULT_BURST_LENGTH 0
+ #define TI_SRC_IGNORE (1 << 11)
+ #define TI_SRC_DREQ (1 << 10)
+ #define TI_SRC_WIDTH (1 << 9)
+ #define TI_SRC_INC (1 << 8)
+ #define TI_DEST_DREQ (1 << 6)
+ #define TI_DEST_WIDTH (1 << 5)
+ #define TI_DEST_INC (1 << 4)
+ #define TI_WAIT_RESP (1 << 3)
+ #define TI_TDMODE (1 << 1)
+ #define TI_INTEN (1 << 0)
+#define ARM_DMACHAN_SOURCE_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x0C)
+#define ARM_DMACHAN_DEST_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x10)
+#define ARM_DMACHAN_TXFR_LEN(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x14)
+ #define TXFR_LEN_XLENGTH_SHIFT 0
+ #define TXFR_LEN_YLENGTH_SHIFT 16
+ #define TXFR_LEN_MAX 0x3FFFFFFF
+ #define TXFR_LEN_MAX_LITE 0xFFFF
+#define ARM_DMACHAN_STRIDE(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x18)
+ #define STRIDE_SRC_SHIFT 0
+ #define STRIDE_DEST_SHIFT 16
+#define ARM_DMACHAN_NEXTCONBK(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x1C)
+#define ARM_DMACHAN_DEBUG(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x20)
+ #define DEBUG_LITE (1 << 28)
+#define ARM_DMA_INT_STATUS (ARM_DMA_BASE + 0xFE0)
+#define ARM_DMA_ENABLE (ARM_DMA_BASE + 0xFF0)
+
#endif
diff --git a/lib/dmachannel.cpp b/lib/dmachannel.cpp
index ed79f676..4edccdab 100644
--- a/lib/dmachannel.cpp
+++ b/lib/dmachannel.cpp
@@ -2,7 +2,7 @@
// dmachannel.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,49 +28,6 @@
#define DMA_CHANNELS (DMA_CHANNEL_MAX + 1)
-#define ARM_DMACHAN_CS(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x00)
- #define CS_RESET (1 << 31)
- #define CS_ABORT (1 << 30)
- #define CS_WAIT_FOR_OUTSTANDING_WRITES (1 << 28)
- #define CS_PANIC_PRIORITY_SHIFT 20
- #define DEFAULT_PANIC_PRIORITY 15
- #define CS_PRIORITY_SHIFT 16
- #define DEFAULT_PRIORITY 1
- #define CS_ERROR (1 << 8)
- #define CS_INT (1 << 2)
- #define CS_END (1 << 1)
- #define CS_ACTIVE (1 << 0)
-#define ARM_DMACHAN_CONBLK_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x04)
-#define ARM_DMACHAN_TI(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x08)
- #define TI_PERMAP_SHIFT 16
- #define TI_BURST_LENGTH_SHIFT 12
- #define DEFAULT_BURST_LENGTH 0
- #define TI_SRC_IGNORE (1 << 11)
- #define TI_SRC_DREQ (1 << 10)
- #define TI_SRC_WIDTH (1 << 9)
- #define TI_SRC_INC (1 << 8)
- #define TI_DEST_DREQ (1 << 6)
- #define TI_DEST_WIDTH (1 << 5)
- #define TI_DEST_INC (1 << 4)
- #define TI_WAIT_RESP (1 << 3)
- #define TI_TDMODE (1 << 1)
- #define TI_INTEN (1 << 0)
-#define ARM_DMACHAN_SOURCE_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x0C)
-#define ARM_DMACHAN_DEST_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x10)
-#define ARM_DMACHAN_TXFR_LEN(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x14)
- #define TXFR_LEN_XLENGTH_SHIFT 0
- #define TXFR_LEN_YLENGTH_SHIFT 16
- #define TXFR_LEN_MAX 0x3FFFFFFF
- #define TXFR_LEN_MAX_LITE 0xFFFF
-#define ARM_DMACHAN_STRIDE(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x18)
- #define STRIDE_SRC_SHIFT 0
- #define STRIDE_DEST_SHIFT 16
-#define ARM_DMACHAN_NEXTCONBK(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x1C)
-#define ARM_DMACHAN_DEBUG(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x20)
- #define DEBUG_LITE (1 << 28)
-#define ARM_DMA_INT_STATUS (ARM_DMA_BASE + 0xFE0)
-#define ARM_DMA_ENABLE (ARM_DMA_BASE + 0xFF0)
-
CDMAChannel::CDMAChannel (unsigned nChannel, CInterruptSystem *pInterruptSystem)
: m_nChannel (CMachineInfo::Get ()->AllocateDMAChannel (nChannel)),
m_pControlBlockBuffer (0),
diff --git a/lib/i2ssoundbasedevice.cpp b/lib/i2ssoundbasedevice.cpp
index c6057922..ba6014b3 100644
--- a/lib/i2ssoundbasedevice.cpp
+++ b/lib/i2ssoundbasedevice.cpp
@@ -11,7 +11,7 @@
// https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=8496
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2016-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2016-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
@@ -77,52 +77,6 @@
#define DREQ_A_TX__SHIFT 8
#define DREQ_A_TX__MASK (0x7F << 8)
-//
-// DMA controller
-//
-#define ARM_DMACHAN_CS(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x00)
- #define CS_RESET (1 << 31)
- #define CS_ABORT (1 << 30)
- #define CS_WAIT_FOR_OUTSTANDING_WRITES (1 << 28)
- #define CS_PANIC_PRIORITY_SHIFT 20
- #define DEFAULT_PANIC_PRIORITY 15
- #define CS_PRIORITY_SHIFT 16
- #define DEFAULT_PRIORITY 1
- #define CS_ERROR (1 << 8)
- #define CS_INT (1 << 2)
- #define CS_END (1 << 1)
- #define CS_ACTIVE (1 << 0)
-#define ARM_DMACHAN_CONBLK_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x04)
-#define ARM_DMACHAN_TI(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x08)
- #define TI_PERMAP_SHIFT 16
- #define TI_BURST_LENGTH_SHIFT 12
- #define DEFAULT_BURST_LENGTH 0
- #define TI_SRC_IGNORE (1 << 11)
- #define TI_SRC_DREQ (1 << 10)
- #define TI_SRC_WIDTH (1 << 9)
- #define TI_SRC_INC (1 << 8)
- #define TI_DEST_DREQ (1 << 6)
- #define TI_DEST_WIDTH (1 << 5)
- #define TI_DEST_INC (1 << 4)
- #define TI_WAIT_RESP (1 << 3)
- #define TI_TDMODE (1 << 1)
- #define TI_INTEN (1 << 0)
-#define ARM_DMACHAN_SOURCE_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x0C)
-#define ARM_DMACHAN_DEST_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x10)
-#define ARM_DMACHAN_TXFR_LEN(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x14)
- #define TXFR_LEN_XLENGTH_SHIFT 0
- #define TXFR_LEN_YLENGTH_SHIFT 16
- #define TXFR_LEN_MAX 0x3FFFFFFF
- #define TXFR_LEN_MAX_LITE 0xFFFF
-#define ARM_DMACHAN_STRIDE(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x18)
- #define STRIDE_SRC_SHIFT 0
- #define STRIDE_DEST_SHIFT 16
-#define ARM_DMACHAN_NEXTCONBK(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x1C)
-#define ARM_DMACHAN_DEBUG(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x20)
- #define DEBUG_LITE (1 << 28)
-#define ARM_DMA_INT_STATUS (ARM_DMA_BASE + 0xFE0)
-#define ARM_DMA_ENABLE (ARM_DMA_BASE + 0xFF0)
-
CI2SSoundBaseDevice::CI2SSoundBaseDevice (CInterruptSystem *pInterrupt,
unsigned nSampleRate,
unsigned nChunkSize,
diff --git a/lib/pwmsoundbasedevice.cpp b/lib/pwmsoundbasedevice.cpp
index 2f6a42ba..e7e183af 100644
--- a/lib/pwmsoundbasedevice.cpp
+++ b/lib/pwmsoundbasedevice.cpp
@@ -2,7 +2,7 @@
// pwmsoundbasedevice.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2016-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2016-2021 R. Stange <rsta2@o2online.de>
//
// Information to implement PWM sound is from:
// "Bare metal sound" by Joeboy (RPi forum)
@@ -101,52 +101,6 @@
#define ARM_PWM_DMAC_PANIC__SHIFT 8
#define ARM_PWM_DMAC_ENAB (1 << 31)
-//
-// DMA controller
-//
-#define ARM_DMACHAN_CS(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x00)
- #define CS_RESET (1 << 31)
- #define CS_ABORT (1 << 30)
- #define CS_WAIT_FOR_OUTSTANDING_WRITES (1 << 28)
- #define CS_PANIC_PRIORITY_SHIFT 20
- #define DEFAULT_PANIC_PRIORITY 15
- #define CS_PRIORITY_SHIFT 16
- #define DEFAULT_PRIORITY 1
- #define CS_ERROR (1 << 8)
- #define CS_INT (1 << 2)
- #define CS_END (1 << 1)
- #define CS_ACTIVE (1 << 0)
-#define ARM_DMACHAN_CONBLK_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x04)
-#define ARM_DMACHAN_TI(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x08)
- #define TI_PERMAP_SHIFT 16
- #define TI_BURST_LENGTH_SHIFT 12
- #define DEFAULT_BURST_LENGTH 0
- #define TI_SRC_IGNORE (1 << 11)
- #define TI_SRC_DREQ (1 << 10)
- #define TI_SRC_WIDTH (1 << 9)
- #define TI_SRC_INC (1 << 8)
- #define TI_DEST_DREQ (1 << 6)
- #define TI_DEST_WIDTH (1 << 5)
- #define TI_DEST_INC (1 << 4)
- #define TI_WAIT_RESP (1 << 3)
- #define TI_TDMODE (1 << 1)
- #define TI_INTEN (1 << 0)
-#define ARM_DMACHAN_SOURCE_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x0C)
-#define ARM_DMACHAN_DEST_AD(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x10)
-#define ARM_DMACHAN_TXFR_LEN(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x14)
- #define TXFR_LEN_XLENGTH_SHIFT 0
- #define TXFR_LEN_YLENGTH_SHIFT 16
- #define TXFR_LEN_MAX 0x3FFFFFFF
- #define TXFR_LEN_MAX_LITE 0xFFFF
-#define ARM_DMACHAN_STRIDE(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x18)
- #define STRIDE_SRC_SHIFT 0
- #define STRIDE_DEST_SHIFT 16
-#define ARM_DMACHAN_NEXTCONBK(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x1C)
-#define ARM_DMACHAN_DEBUG(chan) (ARM_DMA_BASE + ((chan) * 0x100) + 0x20)
- #define DEBUG_LITE (1 << 28)
-#define ARM_DMA_INT_STATUS (ARM_DMA_BASE + 0xFE0)
-#define ARM_DMA_ENABLE (ARM_DMA_BASE + 0xFF0)
-
CPWMSoundBaseDevice::CPWMSoundBaseDevice (CInterruptSystem *pInterrupt,
unsigned nSampleRate,
unsigned nChunkSize)
-252
View File
@@ -1,252 +0,0 @@
From 3a3bec6ec8a21abb63171af51b1333108aa2b28f Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Wed, 10 Mar 2021 20:40:05 +0100
Subject: [PATCH] usb/xhci: Use PCIe INTA instead of MSI
* MSI did not work on RPi 4B v1.1 4GB any more for unknown reason
* Results in a more unique interrupt handling for internal and
external xHCI controller
* bcmpciehostbridge: Do not enable MSI in enable_device() any more
* bcmpciehostbridge: Enable INTX instead
Issue #209
---
include/circle/bcm2711int.h | 3 +-
include/circle/usb/xhcidevice.h | 11 ++-----
lib/bcmpciehostbridge.cpp | 7 +++--
lib/usb/xhcidevice.cpp | 53 +++++++--------------------------
4 files changed, 20 insertions(+), 54 deletions(-)
diff --git a/include/circle/bcm2711int.h b/include/circle/bcm2711int.h
index c2237ce0..96e280d4 100644
--- a/include/circle/bcm2711int.h
+++ b/include/circle/bcm2711int.h
@@ -2,7 +2,7 @@
// bcm2711int.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2019-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2019-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
@@ -52,6 +52,7 @@
#define ARM_IRQ_GPIO3 GIC_SPI (116)
#define ARM_IRQ_UART GIC_SPI (121)
#define ARM_IRQ_ARASANSDIO GIC_SPI (126)
+#define ARM_IRQ_PCIE_HOST_INTA GIC_SPI (143)
#define ARM_IRQ_PCIE_HOST_MSI GIC_SPI (148)
#define ARM_IRQ_BCM54213_0 GIC_SPI (157)
#define ARM_IRQ_BCM54213_1 GIC_SPI (158)
diff --git a/include/circle/usb/xhcidevice.h b/include/circle/usb/xhcidevice.h
index 2ca7bb30..bd9a416b 100644
--- a/include/circle/usb/xhcidevice.h
+++ b/include/circle/usb/xhcidevice.h
@@ -2,7 +2,7 @@
// xhcidevice.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2019-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2019-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
@@ -65,21 +65,16 @@ class CXHCIDevice : public CUSBHostController /// USB host controller interface
#endif
private:
-#ifdef USE_XHCI_INTERNAL
void InterruptHandler (void);
static void InterruptStub (void *pParam);
-#else
- void InterruptHandler (unsigned nVector);
- static void InterruptStub (unsigned nVector, void *pParam);
-#endif
boolean HWReset (void);
private:
-#ifdef USE_XHCI_INTERNAL
CInterruptSystem *m_pInterruptSystem;
boolean m_bInterruptConnected;
-#else
+
+#ifndef USE_XHCI_INTERNAL
CBcmPCIeHostBridge m_PCIeHostBridge;
#endif
diff --git a/lib/bcmpciehostbridge.cpp b/lib/bcmpciehostbridge.cpp
index f7a41791..e64cebb0 100644
--- a/lib/bcmpciehostbridge.cpp
+++ b/lib/bcmpciehostbridge.cpp
@@ -7,7 +7,7 @@
// Licensed under GPL-2.0
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2019-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2019-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
@@ -550,6 +550,7 @@ int CBcmPCIeHostBridge::enable_device (u32 nClassCode, unsigned nSlot, unsigned
| PCI_BASE_ADDRESS_MEM_TYPE_64);
write32 (conf + PCI_BASE_ADDRESS_1, upper_32_bits (MEM_PCIE_RANGE_PCIE_START));
+#if 0
uintptr msi_conf = find_pci_capability (conf, PCI_CAP_ID_MSI);
if (!msi_conf)
return -1;
@@ -562,12 +563,14 @@ int CBcmPCIeHostBridge::enable_device (u32 nClassCode, unsigned nSlot, unsigned
write8 (msi_conf + PCI_MSI_FLAGS, PCI_MSI_FLAGS_ENABLE
| PCI_MSI_FLAGS_64BIT
| uchQueueSize << 4);
+#endif
write16 (conf + PCI_COMMAND, PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
| PCI_COMMAND_PARITY
| PCI_COMMAND_SERR
- | PCI_COMMAND_INTX_DISABLE);
+ //| PCI_COMMAND_INTX_DISABLE
+ );
return 0;
}
diff --git a/lib/usb/xhcidevice.cpp b/lib/usb/xhcidevice.cpp
index c5880f40..570251f2 100644
--- a/lib/usb/xhcidevice.cpp
+++ b/lib/usb/xhcidevice.cpp
@@ -2,7 +2,7 @@
// xhcidevice.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2019-2020 R. Stange <rsta2@o2online.de>
+// Copyright (C) 2019-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,14 +27,19 @@
#include <circle/machineinfo.h>
#include <assert.h>
+#ifdef USE_XHCI_INTERNAL
+ #define ARM_IRQ_XHCI ARM_IRQ_XHCI_INTERNAL
+#else
+ #define ARM_IRQ_XHCI ARM_IRQ_PCIE_HOST_INTA
+#endif
+
static const char From[] = "xhci";
CXHCIDevice::CXHCIDevice (CInterruptSystem *pInterruptSystem, CTimer *pTimer, boolean bPlugAndPlay)
: CUSBHostController (bPlugAndPlay),
-#ifdef USE_XHCI_INTERNAL
m_pInterruptSystem (pInterruptSystem),
m_bInterruptConnected (FALSE),
-#else
+#ifndef USE_XHCI_INTERNAL
m_PCIeHostBridge (pInterruptSystem),
#endif
m_SharedMemAllocator (
@@ -63,14 +68,12 @@ CXHCIDevice::~CXHCIDevice (void)
HWReset ();
}
-#ifdef USE_XHCI_INTERNAL
if (m_bInterruptConnected)
{
assert (m_pInterruptSystem != 0);
- m_pInterruptSystem->DisconnectIRQ (ARM_IRQ_XHCI_INTERNAL);
+ m_pInterruptSystem->DisconnectIRQ (ARM_IRQ_XHCI);
m_bInterruptConnected = FALSE;
}
-#endif
m_pScratchpadBufferArray = 0;
m_pScratchpadBuffers = 0;
@@ -126,13 +129,6 @@ boolean CXHCIDevice::Initialize (boolean bScanDevices)
| XHCI_PCIE_FUNC << 12;
Tags.GetTag (PROPTAG_NOTIFY_XHCI_RESET, &NotifyXHCIReset, sizeof NotifyXHCIReset, 4);
- if (!m_PCIeHostBridge.ConnectMSI (InterruptStub, this))
- {
- CLogger::Get ()->Write (From, LogError, "Cannot connect MSI");
-
- return FALSE;
- }
-
if (!m_PCIeHostBridge.EnableDevice (XHCI_PCI_CLASS_CODE, XHCI_PCIE_SLOT, XHCI_PCIE_FUNC))
{
CLogger::Get ()->Write (From, LogError, "Cannot enable xHCI device");
@@ -236,11 +232,9 @@ boolean CXHCIDevice::Initialize (boolean bScanDevices)
m_pRootHub = new CXHCIRootHub (nMaxPorts, this);
assert (m_pRootHub != 0);
-#ifdef USE_XHCI_INTERNAL
assert (m_pInterruptSystem != 0);
- m_pInterruptSystem->ConnectIRQ (ARM_IRQ_XHCI_INTERNAL, InterruptStub, this);
+ m_pInterruptSystem->ConnectIRQ (ARM_IRQ_XHCI, InterruptStub, this);
m_bInterruptConnected = TRUE;
-#endif
// start controller
m_pMMIO->op_write32 (XHCI_REG_OP_USBCMD, m_pMMIO->op_read32 (XHCI_REG_OP_USBCMD)
@@ -346,31 +340,18 @@ void CXHCIDevice::FreeSharedMem (void *pBlock)
m_SharedMemAllocator.Free (pBlock);
}
-#ifdef USE_XHCI_INTERNAL
void CXHCIDevice::InterruptHandler (void)
-#else
-void CXHCIDevice::InterruptHandler (unsigned nVector)
-#endif
{
#ifdef XHCI_DEBUG2
-#ifdef USE_XHCI_INTERNAL
CLogger::Get ()->Write (From, LogDebug, "IRQ");
-#else
- CLogger::Get ()->Write (From, LogDebug, "MSI%u", nVector);
-#endif
-#endif
-#ifndef USE_XHCI_INTERNAL
- assert (nVector == 0);
#endif
// acknowledge interrupt
u32 nStatus = m_pMMIO->op_read32 (XHCI_REG_OP_USBSTS);
m_pMMIO->op_write32 (XHCI_REG_OP_USBSTS, nStatus | XHCI_REG_OP_USBSTS_EINT);
-#ifdef USE_XHCI_INTERNAL
m_pMMIO->rt_write32 (0, XHCI_REG_RT_IR_IMAN, m_pMMIO->rt_read32 (0, XHCI_REG_RT_IR_IMAN)
| XHCI_REG_RT_IR_IMAN_IP);
-#endif
if (nStatus & XHCI_REG_OP_USBSTS_HCH)
{
@@ -406,8 +387,6 @@ void CXHCIDevice::InterruptHandler (unsigned nVector)
}
}
-#ifdef USE_XHCI_INTERNAL
-
void CXHCIDevice::InterruptStub (void *pParam)
{
CXHCIDevice *pThis = (CXHCIDevice *) pParam;
@@ -416,18 +395,6 @@ void CXHCIDevice::InterruptStub (void *pParam)
pThis->InterruptHandler ();
}
-#else
-
-void CXHCIDevice::InterruptStub (unsigned nVector, void *pParam)
-{
- CXHCIDevice *pThis = (CXHCIDevice *) pParam;
- assert (pThis != 0);
-
- pThis->InterruptHandler (nVector);
-}
-
-#endif
-
boolean CXHCIDevice::HWReset (void)
{
if ( !m_pMMIO->op_wait32 (XHCI_REG_OP_USBSTS, XHCI_REG_OP_USBSTS_CNR, 0, 100000)
@@ -1,158 +0,0 @@
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;
}
@@ -1,106 +0,0 @@
From 91075a403fb952f60c83707e56b239e615c6b3f3 Mon Sep 17 00:00:00 2001
From: Rene Stange <rsta2@o2online.de>
Date: Wed, 24 Mar 2021 22:40:05 +0100
Subject: [PATCH] usb: Add workaround for low-speed devices with bulk EPs
There are some low-speed USB devices, which have bulk endpoints. This
is normally not allowed by the USB specification. To be able to use
such a device, we treat these endpoints being interrupt EPs. This has
not been tested on RPi 4 yet.
See: https://github.com/dwhinham/mt32-pi/discussions/102
---
lib/usb/dwhcixferstagedata.cpp | 1 -
lib/usb/usbendpoint.cpp | 26 +++++++++++++++++++++++++-
lib/usb/xhciendpoint.cpp | 15 +++++++++++++++
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/lib/usb/dwhcixferstagedata.cpp b/lib/usb/dwhcixferstagedata.cpp
index 32f3f356..cc783a2d 100644
--- a/lib/usb/dwhcixferstagedata.cpp
+++ b/lib/usb/dwhcixferstagedata.cpp
@@ -185,7 +185,6 @@ void CDWHCITransferStageData::TransactionComplete (u32 nStatus, u32 nPacketsLeft
if ( (nStatus & DWHCI_HOST_CHAN_INT_NAK)
&& m_pURB->IsCompleteOnNAK ())
{
- assert (m_pEndpoint->GetType () == EndpointTypeBulk);
assert (m_bIn);
m_nPackets = 0; // no data is available, complete transfer
diff --git a/lib/usb/usbendpoint.cpp b/lib/usb/usbendpoint.cpp
index 05a81279..305487c5 100644
--- a/lib/usb/usbendpoint.cpp
+++ b/lib/usb/usbendpoint.cpp
@@ -2,7 +2,7 @@
// usbendpoint.cpp
//
// Circle - A C++ bare metal environment for Raspberry Pi
-// Copyright (C) 2014-2019 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
@@ -19,6 +19,7 @@
//
#include <circle/usb/usbendpoint.h>
#include <circle/sysconfig.h>
+#include <circle/logger.h>
#include <assert.h>
CUSBEndpoint::CUSBEndpoint (CUSBDevice *pDevice)
@@ -113,6 +114,29 @@ CUSBEndpoint::CUSBEndpoint (CUSBDevice *pDevice, const TUSBEndpointDescriptor *p
}
#endif
+ // workaround for low-speed devices with bulk endpoints,
+ // which is normally forbidden by the USB spec.
+ if ( m_pDevice->GetSpeed () == USBSpeedLow
+ && m_Type == EndpointTypeBulk)
+ {
+ CLogger::Get ()->Write ("uep", LogWarning, "Device is not fully USB compliant");
+
+ m_Type = EndpointTypeInterrupt;
+
+ if (m_nMaxPacketSize > 8)
+ {
+ m_nMaxPacketSize = 8;
+ }
+
+#if RASPPI <= 3
+#ifdef USE_USB_SOF_INTR
+ m_nInterval = 1;
+#else
+ m_nInterval = 20;
+#endif
+#endif
+ }
+
#if RASPPI >= 4
m_pXHCIEndpoint = new CXHCIEndpoint ((CXHCIUSBDevice *) m_pDevice, pDesc,
(CXHCIDevice *) m_pDevice->GetHost ());
diff --git a/lib/usb/xhciendpoint.cpp b/lib/usb/xhciendpoint.cpp
index fa4e8f30..5a9eb837 100644
--- a/lib/usb/xhciendpoint.cpp
+++ b/lib/usb/xhciendpoint.cpp
@@ -100,6 +100,21 @@ CXHCIEndpoint::CXHCIEndpoint (CXHCIUSBDevice *pDevice, const TUSBEndpointDescrip
m_uchInterval = 0;
}
+ // workaround for low-speed devices with bulk endpoints,
+ // which is normally forbidden by the USB spec.
+ if ( m_pDevice->GetSpeed () == USBSpeedLow
+ && (m_uchAttributes & 3) == 2)
+ {
+ m_uchAttributes = 3; // fake interrupt endpoint
+
+ if (m_usMaxPacketSize > 8)
+ {
+ m_usMaxPacketSize = 8;
+ }
+
+ m_uchInterval = ConvertInterval (1, USBSpeedLow);
+ }
+
// calculate endpoint ID
assert ((m_uchEndpointAddress & 0x0F) >= 1);
m_uchEndpointID = (m_uchEndpointAddress & 0x0F) * 2;
@@ -1,147 +0,0 @@
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);