Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2022-01-10 00:29:47 +0300
committerDavid Crocker <dcrocker@eschertech.com>2022-01-10 00:29:47 +0300
commitd9ff09f7c9030389c0fa7bb8eb7f85156c9d9045 (patch)
tree050deb7efa50f9749876532d5f799ae0e08ab388 /src
parentc0356a4933bbbe11af20032ee1965358a29cf4bd (diff)
Support external SD card on MB6HC
Diffstat (limited to 'src')
-rw-r--r--src/Duet3_V06/Pins_Duet3_V06.h8
-rw-r--r--src/Libraries/sd_mmc/sd_mmc.c13
-rw-r--r--src/Libraries/sd_mmc/sd_mmc.h3
-rw-r--r--src/Libraries/sd_mmc/sd_mmc_spi.cpp19
-rw-r--r--src/Libraries/sd_mmc/sd_mmc_spi.h3
-rw-r--r--src/Platform/Platform.cpp12
-rw-r--r--src/Platform/RepRap.cpp12
-rw-r--r--src/RepRapFirmware.h3
-rw-r--r--src/Storage/MassStorage.cpp53
-rw-r--r--src/Storage/MassStorage.h12
10 files changed, 119 insertions, 19 deletions
diff --git a/src/Duet3_V06/Pins_Duet3_V06.h b/src/Duet3_V06/Pins_Duet3_V06.h
index 773b1d09..741df19e 100644
--- a/src/Duet3_V06/Pins_Duet3_V06.h
+++ b/src/Duet3_V06/Pins_Duet3_V06.h
@@ -151,10 +151,10 @@ constexpr Pin DiagPin = PortCPin(20);
constexpr bool DiagOnPolarity = true;
// SD cards
-constexpr size_t NumSdCards = 1;
-constexpr Pin SdCardDetectPins[1] = { PortAPin(29) };
-constexpr Pin SdWriteProtectPins[1] = { NoPin };
-constexpr Pin SdSpiCSPins[1] = { NoPin };
+constexpr size_t NumSdCards = 2; // we now allow one SPI-connected SD card to be configured at boot time
+constexpr Pin SdCardDetectPins[NumSdCards] = { PortAPin(29), NoPin };
+constexpr Pin SdWriteProtectPins[NumSdCards] = { NoPin, NoPin };
+constexpr Pin SdSpiCSPins[NumSdCards] = { NoPin, NoPin };
constexpr uint32_t ExpectedSdCardSpeed = 25000000;
constexpr IRQn SdhcIRQn = HSMCI_IRQn;
diff --git a/src/Libraries/sd_mmc/sd_mmc.c b/src/Libraries/sd_mmc/sd_mmc.c
index d05eb40a..11d0cd75 100644
--- a/src/Libraries/sd_mmc/sd_mmc.c
+++ b/src/Libraries/sd_mmc/sd_mmc.c
@@ -1928,6 +1928,19 @@ uint32_t sd_mmc_get_interface_speed(uint8_t slot)
#endif
+#if SD_MMC_SPI_MEM_CNT != 0
+
+// Change the CS pin used by an SPI-connected card slot. Only used by the Duet 3 MB6HC. Linker garbage collection will eliminate this function in other builds.
+void sd_mmc_change_cs_pin(uint8_t slot, Pin csPin) noexcept
+{
+ if (slot >= SD_MMC_HSMCI_MEM_CNT)
+ {
+ sd_mmc_spi_change_cs_pin(slot - SD_MMC_HSMCI_MEM_CNT, csPin);
+ }
+}
+
+#endif
+
// Initialise for reading blocks
// On entry the card is not selected
// If SD_MMC_OK is returned then the card is selected, otherwise it is not selected
diff --git a/src/Libraries/sd_mmc/sd_mmc.h b/src/Libraries/sd_mmc/sd_mmc.h
index 619bf3a1..b71be5bd 100644
--- a/src/Libraries/sd_mmc/sd_mmc.h
+++ b/src/Libraries/sd_mmc/sd_mmc.h
@@ -177,6 +177,9 @@ void sd_mmc_unmount(uint8_t slot) noexcept;
// Get the interface speed in bytes/sec
uint32_t sd_mmc_get_interface_speed(uint8_t slot) noexcept;
+// Change the CS pin used by an SPI-connected card slot. Only used by the Duet 3 MB6HC. Linker garbage collection will eliminate this function in other builds.
+void sd_mmc_change_cs_pin(uint8_t slot, Pin csPin) noexcept;
+
#endif
/**
diff --git a/src/Libraries/sd_mmc/sd_mmc_spi.cpp b/src/Libraries/sd_mmc/sd_mmc_spi.cpp
index a32336b9..2df31a90 100644
--- a/src/Libraries/sd_mmc/sd_mmc_spi.cpp
+++ b/src/Libraries/sd_mmc/sd_mmc_spi.cpp
@@ -70,7 +70,7 @@ extern void debugPrintf(const char* fmt, ...) noexcept;
static sd_mmc_spi_errno_t sd_mmc_spi_err;
//! Slot array of SPI structures
-static SharedSpiClient *sd_mmc_spi_devices[SD_MMC_SPI_MEM_CNT];
+static SharedSpiClient *sd_mmc_spi_devices[SD_MMC_SPI_MEM_CNT] = { 0 };
static SharedSpiClient *currentSpiClient = nullptr;
//! 32 bits response of the last command
@@ -108,7 +108,11 @@ static uint8_t sd_mmc_spi_crc7(uint8_t * buf, uint8_t size) noexcept
value = *buf++;
for (i = 0; i < 8; i++) {
crc <<= 1;
+#if 1 // DC
+ if ((value ^ crc) & 0x80)
+#else
if ((value & 0x80) ^ (crc & 0x80))
+#endif
{
crc ^= 0x09;
}
@@ -348,6 +352,19 @@ void sd_mmc_spi_init(const Pin csPins[SD_MMC_SPI_MEM_CNT]) noexcept
}
}
+#if 1
+
+// This function is used by the Duet 3 MB6HC to enable support for a second SD card
+void sd_mmc_spi_change_cs_pin(uint8_t spiSlot, Pin csPin) noexcept
+{
+ if (spiSlot < SD_MMC_SPI_MEM_CNT)
+ {
+ sd_mmc_spi_devices[spiSlot]->SetCsPin(csPin);
+ }
+}
+
+#endif
+
// Note, every call to sd_mmc_spi_select_device must be matched to a call to sd_mmc_spi_deselect_device so that the SPI mutex gets released!
// Unfortunately, sd_mmc.c calls this more than one without deselecting it in between. So check whether it is already selected.
bool sd_mmc_spi_select_device(uint8_t slot, uint32_t clock, uint8_t bus_width, bool high_speed) noexcept
diff --git a/src/Libraries/sd_mmc/sd_mmc_spi.h b/src/Libraries/sd_mmc/sd_mmc_spi.h
index 164bc625..80be7dd5 100644
--- a/src/Libraries/sd_mmc/sd_mmc_spi.h
+++ b/src/Libraries/sd_mmc/sd_mmc_spi.h
@@ -243,6 +243,9 @@ typedef void (*spiIdleFunc_t)(uint32_t, uint32_t) noexcept;
// Set the idle function and return the old one
spiIdleFunc_t sd_mmc_spi_set_idle_func(spiIdleFunc_t) noexcept;
+// This function is used by the Duet 3 MB6HC to enable support for a second SD card
+void sd_mmc_spi_change_cs_pin(uint8_t spiSlot, Pin csPin) noexcept;
+
#endif
//! @}
diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp
index 8e1b12f8..b6a14f48 100644
--- a/src/Platform/Platform.cpp
+++ b/src/Platform/Platform.cpp
@@ -4404,7 +4404,13 @@ GCodeResult Platform::ConfigurePort(GCodeBuffer& gb, const StringRef& reply) THR
{
// Exactly one of FHJPSR is allowed
unsigned int charsPresent = 0;
- for (char c : (const char[]){'R', 'J', 'F', 'H', 'P', 'S'})
+ for (char c :
+#ifdef DUET3_V06
+ (const char[]){'D', 'R', 'J', 'F', 'H', 'P', 'S'}
+#else
+ (const char[]){'R', 'J', 'F', 'H', 'P', 'S'}
+#endif
+ )
{
charsPresent <<= 1;
if (gb.Seen(c))
@@ -4443,6 +4449,10 @@ GCodeResult Platform::ConfigurePort(GCodeBuffer& gb, const StringRef& reply) THR
const uint32_t slot = gb.GetLimitedUIValue('R', MaxSpindles);
return spindles[slot].Configure(gb, reply);
}
+#ifdef DUET3_V06
+ case 64: // D
+ return MassStorage::ConfigureSdCard(gb, reply);
+#endif
default:
reply.copy("exactly one of FHJPSR must be given");
diff --git a/src/Platform/RepRap.cpp b/src/Platform/RepRap.cpp
index 035818f0..b2c56027 100644
--- a/src/Platform/RepRap.cpp
+++ b/src/Platform/RepRap.cpp
@@ -238,7 +238,7 @@ constexpr ObjectModelArrayDescriptor RepRap::volumesArrayDescriptor =
constexpr ObjectModelArrayDescriptor RepRap::volChangesArrayDescriptor =
{
nullptr,
- [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return NumSdCards; },
+ [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return MassStorage::GetNumVolumes(); },
[] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue
{ return ExpressionValue((int32_t)MassStorage::GetVolumeSeq(context.GetLastIndex())); }
};
@@ -314,7 +314,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] =
{ "trackedObjects", OBJECT_MODEL_FUNC_NOSELF((int32_t)MaxTrackedObjects), ObjectModelEntryFlags::verbose },
{ "triggers", OBJECT_MODEL_FUNC_NOSELF((int32_t)MaxTriggers), ObjectModelEntryFlags::verbose },
#if HAS_MASS_STORAGE
- { "volumes", OBJECT_MODEL_FUNC_NOSELF((int32_t)NumSdCards), ObjectModelEntryFlags::verbose },
+ { "volumes", OBJECT_MODEL_FUNC_NOSELF((int32_t)MassStorage::GetNumVolumes()), ObjectModelEntryFlags::verbose },
#else
{ "volumes", OBJECT_MODEL_FUNC_NOSELF((int32_t)0), ObjectModelEntryFlags::verbose },
#endif
@@ -1688,14 +1688,14 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) con
#if HAS_MASS_STORAGE
// Total and mounted volumes
size_t mountedCards = 0;
- for (size_t i = 0; i < NumSdCards; i++)
+ for (size_t i = 0; i < MassStorage::GetNumVolumes(); i++)
{
if (MassStorage::IsDriveMounted(i))
{
- mountedCards |= (1 << i);
+ mountedCards |= (1u << i);
}
}
- response->catf(",\"volumes\":%u,\"mountedVolumes\":%u", NumSdCards, mountedCards);
+ response->catf(",\"volumes\":%u,\"mountedVolumes\":%u", MassStorage::GetNumVolumes(), mountedCards);
#endif
// Machine mode and name
@@ -2079,7 +2079,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq) const noexc
{
// Add the static fields
response->catf(",\"geometry\":\"%s\",\"axes\":%u,\"totalAxes\":%u,\"axisNames\":\"%s\",\"volumes\":%u,\"numTools\":%u,\"myName\":\"%.s\",\"firmwareName\":\"%.s\"",
- move->GetGeometryString(), numVisibleAxes, gCodes->GetTotalAxes(), gCodes->GetAxisLetters(), NumSdCards, GetNumberOfContiguousTools(), myName.c_str(), FIRMWARE_NAME);
+ move->GetGeometryString(), numVisibleAxes, gCodes->GetTotalAxes(), gCodes->GetAxisLetters(), MassStorage::GetNumVolumes(), GetNumberOfContiguousTools(), myName.c_str(), FIRMWARE_NAME);
}
response->cat("}\n"); // include a newline to help PanelDue resync
diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h
index 0351298c..2db51861 100644
--- a/src/RepRapFirmware.h
+++ b/src/RepRapFirmware.h
@@ -101,7 +101,8 @@ enum class PinUsedBy : uint8_t
gpout,
filamentMonitor,
temporaryInput,
- sensor
+ sensor,
+ sdCard
};
#include "Pins.h"
diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp
index 8e21ad70..dcab61c2 100644
--- a/src/Storage/MassStorage.cpp
+++ b/src/Storage/MassStorage.cpp
@@ -19,6 +19,10 @@ static_assert(SD_MMC_MEM_CNT == NumSdCards);
# include <SBC/SbcInterface.h>
#endif
+#ifdef DUET3_V06
+# include <GCodes/GCodeBuffer/GCodeBuffer.h>
+#endif
+
// A note on using mutexes:
// Each SD card volume has its own mutex. There is also one for the file table, and one for the find first/find next buffer.
// The FatFS subsystem locks and releases the appropriate volume mutex when it is called.
@@ -93,6 +97,10 @@ static uint64_t GetFreeSpace(size_t slot)
static const char * const VolPathNames[] = { "0:/", "1:/" };
static_assert(ARRAY_SIZE(VolPathNames) >= NumSdCards, "Incorrect VolPathNames array");
+#ifdef DUET3_V06
+static IoPort sd1Ports[2]; // first element is CS port, second is CD port
+#endif
+
constexpr ObjectModelTableEntry SdCardInfo::objectModelTable[] =
{
// Within each group, these entries must be in alphabetical order
@@ -173,6 +181,41 @@ static FileStore files[MAX_FILES];
#if HAS_MASS_STORAGE
+# ifdef DUET3_V06
+
+// Return the number of volumes, which on the 6HC is normally 1 but can be increased to 2
+size_t MassStorage::GetNumVolumes() noexcept
+{
+ return (sd1Ports[0].IsValid()) ? 2 : 1; // we have 2 slots if the second one has a valid CS pin, else 1
+}
+
+// Configure additional SD card slots
+// The card detect pin may be NoPin if the SD card slot doesn't support card detect
+GCodeResult MassStorage::ConfigureSdCard(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException)
+{
+ (void)gb.GetLimitedUIValue('D', 1, 2); // only slot 1 may be configured
+ IoPort * const portAddresses[2] = { &sd1Ports[0], &sd1Ports[1] };
+ if (gb.Seen('C'))
+ {
+ const PinAccess accessNeeded[2] = { PinAccess::write1, PinAccess::read };
+ if (IoPort::AssignPorts(gb, reply, PinUsedBy::sdCard, 2, portAddresses, accessNeeded) == 0)
+ {
+ return GCodeResult::error;
+ }
+ sd_mmc_change_cs_pin(1, sd1Ports[0].GetPin());
+ info[1].cdPin = sd1Ports[1].GetPin();
+ reprap.VolumesUpdated();
+ }
+ else
+ {
+ reply.copy("SD card 1 uses pins ");
+ IoPort::AppendPinNames(reply, 2, portAddresses);
+ }
+ return GCodeResult::ok;
+}
+
+# endif
+
// Sequence number management
uint16_t MassStorage::GetVolumeSeq(unsigned int volume) noexcept
{
@@ -895,7 +938,7 @@ bool MassStorage::CheckDriveMounted(const char* path) noexcept
const size_t card = (strlen(path) >= 2 && path[1] == ':' && isDigit(path[0]))
? path[0] - '0'
: 0;
- return card < NumSdCards && info[card].isMounted;
+ return card < GetNumVolumes() && info[card].isMounted;
}
// Return true if any files are open on the file system
@@ -941,7 +984,7 @@ bool MassStorage::IsCardDetected(size_t card) noexcept
// This may only be called to mount one card at a time.
GCodeResult MassStorage::Mount(size_t card, const StringRef& reply, bool reportSuccess) noexcept
{
- if (card >= NumSdCards)
+ if (card >= GetNumVolumes())
{
reply.copy("SD card number out of range");
return GCodeResult::error;
@@ -1037,7 +1080,7 @@ GCodeResult MassStorage::Mount(size_t card, const StringRef& reply, bool reportS
// If an error occurs, return true with the error message in 'reply'.
GCodeResult MassStorage::Unmount(size_t card, const StringRef& reply) noexcept
{
- if (card >= NumSdCards)
+ if (card >= GetNumVolumes())
{
reply.copy("SD card number out of range");
return GCodeResult::error;
@@ -1058,7 +1101,7 @@ GCodeResult MassStorage::Unmount(size_t card, const StringRef& reply) noexcept
bool MassStorage::IsDriveMounted(size_t drive) noexcept
{
- return drive < NumSdCards
+ return drive < GetNumVolumes()
#if HAS_MASS_STORAGE
&& info[drive].isMounted
#endif
@@ -1166,7 +1209,7 @@ void MassStorage::RecordSimulationTime(const char *printingFilePath, uint32_t si
// Get information about the SD card and interface speed
MassStorage::InfoResult MassStorage::GetCardInfo(size_t slot, uint64_t& capacity, uint64_t& freeSpace, uint32_t& speed, uint32_t& clSize) noexcept
{
- if (slot >= NumSdCards)
+ if (slot >= GetNumVolumes())
{
return InfoResult::badSlot;
}
diff --git a/src/Storage/MassStorage.h b/src/Storage/MassStorage.h
index 86b0782f..854d56b4 100644
--- a/src/Storage/MassStorage.h
+++ b/src/Storage/MassStorage.h
@@ -48,6 +48,12 @@ namespace MassStorage
bool FileExists(const char *filePath) noexcept;
void CloseAllFiles() noexcept;
void Spin() noexcept;
+
+# ifdef DUET3_V06
+ size_t GetNumVolumes() noexcept; // The number of SD slots may be 1 or 2 on the 6HC
+# else
+ inline size_t GetNumVolumes() noexcept { return NumSdCards; }
+# endif
#endif
#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE
@@ -99,8 +105,11 @@ namespace MassStorage
InfoResult GetCardInfo(size_t slot, uint64_t& capacity, uint64_t& freeSpace, uint32_t& speed, uint32_t& clSize) noexcept;
+# ifdef DUET3_V06
+ GCodeResult ConfigureSdCard(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Configure additional SD card slots
+# endif
+
# if SUPPORT_OBJECT_MODEL
- inline size_t GetNumVolumes() noexcept { return NumSdCards; }
const ObjectModel *_ecv_from GetVolume(size_t vol) noexcept;
# endif
@@ -108,4 +117,5 @@ namespace MassStorage
}
+
#endif