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
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2022-05-27 17:51:01 +0300
committerDavid Crocker <dcrocker@eschertech.com>2022-05-27 17:51:01 +0300
commit539c6f40cc1dedc08a5e157cd3b6d27bf3b37db2 (patch)
treedf26ce69a887732356f36417d12d4fbf68e6d172
parent8a8d675ade52b4b524b6c26713a6d61ea7ec4861 (diff)
parent8c5715d207701cf3af2b38bd8499637496e3ce77 (diff)
Merge branch '3.4-spi-tft' of https://github.com/Duet3D/RepRapFirmware.git into 3.4-spi-tft
-rw-r--r--src/Config/Pins_Duet3_MB6XD.h3
-rw-r--r--src/Config/Pins_DuetNG.h6
-rw-r--r--src/GCodes/GCodes2.cpp18
-rw-r--r--src/Networking/UploadingNetworkResponder.cpp10
-rw-r--r--src/Networking/W5500Ethernet/Wiznet/Ethernet/WizSpi.cpp106
-rw-r--r--src/ObjectModel/ObjectModel.cpp9
-rw-r--r--src/Platform/OutputMemory.cpp68
-rw-r--r--src/Platform/OutputMemory.h1
-rw-r--r--src/Platform/Platform.cpp48
-rw-r--r--src/Platform/Platform.h4
-rw-r--r--src/Version.h2
11 files changed, 125 insertions, 150 deletions
diff --git a/src/Config/Pins_Duet3_MB6XD.h b/src/Config/Pins_Duet3_MB6XD.h
index 59a8b140..2aee62ce 100644
--- a/src/Config/Pins_Duet3_MB6XD.h
+++ b/src/Config/Pins_Duet3_MB6XD.h
@@ -98,7 +98,8 @@ constexpr Pin UsbVBusPin = PortCPin(21); // Pin used to monitor VBUS on USB po
// Drivers
constexpr Pin STEP_PINS[NumDirectDrivers] = { PortCPin(18), PortCPin(16), PortCPin(28), PortCPin(01), PortCPin(4), PortCPin(9) };
constexpr Pin DIRECTION_PINS[NumDirectDrivers] = { PortBPin(5), PortDPin(10), PortAPin(4), PortAPin(22), PortCPin(3), PortDPin(14) };
-constexpr Pin ENABLE_PINS[NumDirectDrivers] = { PortBPin(4), PortAPin(21), PortAPin(9), PortAPin(23), PortAPin(2), PortDPin(17) };
+constexpr Pin ENABLE_PINS_v01[NumDirectDrivers] = { PortBPin(4), PortAPin(21), PortAPin(9), PortAPin(23), PortAPin(2), PortDPin(17) };
+constexpr Pin ENABLE_PINS_v100[NumDirectDrivers] = { PortBPin(4), PortAPin(21), PortCPin(20), PortAPin(23), PortAPin(2), PortDPin(17) };
constexpr Pin DRIVER_ERR_PINS[NumDirectDrivers] = { PortDPin(29), PortCPin(17), PortDPin(13), PortCPin(02), PortDPin(31), PortCPin(10) };
constexpr Pin StepGatePin = PortDPin(22);
constexpr GpioPinFunction StepGatePinFunction = GpioPinFunction::C; // TIOB11
diff --git a/src/Config/Pins_DuetNG.h b/src/Config/Pins_DuetNG.h
index c4339c34..09e53fe6 100644
--- a/src/Config/Pins_DuetNG.h
+++ b/src/Config/Pins_DuetNG.h
@@ -564,6 +564,12 @@ constexpr DmaChannel DmacChanWiFiTx = 1;
constexpr DmaChannel DmacChanWiFiRx = 2;
#endif
+#if HAS_W5500_NETWORKING
+// We can use the same DMA channels as for WiFi because only one of them will be present
+constexpr DmaChannel DmacChanW5500Tx = 1;
+constexpr DmaChannel DmacChanW5500Rx = 2;
+#endif
+
namespace StepPins
{
// *** These next three functions must use the same bit assignments in the drivers bitmap ***
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 55064adf..97943d8e 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -2533,19 +2533,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx
bool dummy = false;
String<MaxMessageLength> title;
- gb.TryGetQuotedString('R', title.GetRef(), dummy);
+ (void)gb.TryGetQuotedString('R', title.GetRef(), dummy);
- int32_t sParam = 1;
- gb.TryGetIValue('S', sParam, dummy);
- if (sParam < 0 || sParam > 3)
- {
- reply.copy("Invalid message box mode");
- result = GCodeResult::error;
- break;
- }
+ uint32_t sParam = 1;
+ (void)gb.TryGetLimitedUIValue('S', sParam, dummy, 4);
float tParam;
- if (sParam == 0 || sParam == 1)
+ if (sParam <= 1)
{
tParam = DefaultMessageTimeout;
gb.TryGetFValue('T', tParam, dummy);
@@ -2572,7 +2566,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx
}
// Don't lock the movement system, because if we do then only the channel that issues the M291 can move the axes
- if (sParam == 2 || sParam == 3)
+ if (sParam >= 2)
{
#if HAS_SBC_INTERFACE
if (reprap.UsingSbcInterface())
@@ -2675,7 +2669,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx
break;
case 305: // Set/report specific heater parameters
- reply.copy("M305 has been replaced by M308 and M950 in RepRapFirmware 3");
+ reply.copy("M305 has been replaced by M308 and M950");
result = GCodeResult::error;
break;
diff --git a/src/Networking/UploadingNetworkResponder.cpp b/src/Networking/UploadingNetworkResponder.cpp
index 5b4245de..6cac6b39 100644
--- a/src/Networking/UploadingNetworkResponder.cpp
+++ b/src/Networking/UploadingNetworkResponder.cpp
@@ -111,7 +111,14 @@ void UploadingNetworkResponder::FinishUpload(uint32_t fileLength, time_t fileLas
const char *uploadFilename = filenameBeingProcessed.c_str();
if (uploadError)
{
+#if 0 // Temporary code to save files with upload errors and report successful uploads
+ String<MaxFilenameLength> newName;
+ MassStorage::CombineName(newName.GetRef(), Platform::GetGCodeDir(), "uploadError_");
+ newName.catf("%04u", (unsigned int)(millis() % 10000));
+ MassStorage::Rename(uploadFilename, newName.c_str(), true, true);
+#else
MassStorage::Delete(uploadFilename, true);
+#endif
}
else
{
@@ -126,6 +133,9 @@ void UploadingNetworkResponder::FinishUpload(uint32_t fileLength, time_t fileLas
// Update the file timestamp if it was specified
(void)MassStorage::SetLastModifiedTime(origFilename.c_str(), fileLastModified);
}
+#if 0 // Temporary code to save files with upload errors and report successful uploads
+ GetPlatform().Message(GenericMessage, "Successful upload\n");
+#endif
}
filenameBeingProcessed.Clear();
}
diff --git a/src/Networking/W5500Ethernet/Wiznet/Ethernet/WizSpi.cpp b/src/Networking/W5500Ethernet/Wiznet/Ethernet/WizSpi.cpp
index 525767d5..74da25e4 100644
--- a/src/Networking/W5500Ethernet/Wiznet/Ethernet/WizSpi.cpp
+++ b/src/Networking/W5500Ethernet/Wiznet/Ethernet/WizSpi.cpp
@@ -7,6 +7,7 @@
#include "WizSpi.h"
#include <Config/Pins.h>
+#include <Cache.h>
// Define exactly one of the following as 1, the other as zero
#define USE_PDC 1 // use peripheral DMA controller
@@ -26,32 +27,32 @@
// SPI data rate. I tried 60MHz and we got some data corruption when uploading files, so I reduced it to 40MHz.
// 2018-01-11: We have now received one report of data corruption at 40MHz, so reduced this to 30MHz
-const uint32_t SpiClockFrequency = 30000000;
+// 2022-05-23: Very occasionally we get data corruption when uploading files, with a character being replaced by the following character. So reduced to 25MHz.
+const uint32_t SpiClockFrequency = 25000000; // actually gets rounded down to 120/5 = 24MHz
const unsigned int SpiPeripheralChannelId = 0; // we use NPCS0 as the slave select signal
// Functions called by the W5500 module to transfer data to/from the W5500 via SPI
#if USE_PDC
-static Pdc *spi_pdc;
static inline void spi_rx_dma_enable() noexcept
{
- pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); // we have to transmit in order to receive
+ pdc_enable_transfer(spi_get_pdc_base(W5500_SPI), PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); // we have to transmit in order to receive
}
static inline void spi_tx_dma_enable() noexcept
{
- pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN);
+ pdc_enable_transfer(spi_get_pdc_base(W5500_SPI), PERIPH_PTCR_TXTEN);
}
static inline void spi_rx_dma_disable() noexcept
{
- pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // we have to transmit in order to receive
+ pdc_disable_transfer(spi_get_pdc_base(W5500_SPI), PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // we have to transmit in order to receive
}
static inline void spi_tx_dma_disable() noexcept
{
- pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS);
+ pdc_disable_transfer(spi_get_pdc_base(W5500_SPI), PERIPH_PTCR_TXTDIS);
}
static inline bool spi_dma_check_rx_complete() noexcept
@@ -69,7 +70,7 @@ static void spi_tx_dma_setup(const uint8_t *buf, uint32_t length) noexcept
pdc_packet_t pdc_spi_packet;
pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf);
pdc_spi_packet.ul_size = length;
- pdc_tx_init(spi_pdc, &pdc_spi_packet, nullptr);
+ pdc_tx_init(spi_get_pdc_base(W5500_SPI), &pdc_spi_packet, nullptr);
}
static void spi_rx_dma_setup(uint8_t *buf, uint32_t length) noexcept
@@ -77,79 +78,81 @@ static void spi_rx_dma_setup(uint8_t *buf, uint32_t length) noexcept
pdc_packet_t pdc_spi_packet;
pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(buf);
pdc_spi_packet.ul_size = length;
- pdc_rx_init(spi_pdc, &pdc_spi_packet, nullptr);
- pdc_tx_init(spi_pdc, &pdc_spi_packet, nullptr); // we have to transmit in order to receive
+ pdc_rx_init(spi_get_pdc_base(W5500_SPI), &pdc_spi_packet, nullptr);
+ pdc_tx_init(spi_get_pdc_base(W5500_SPI), &pdc_spi_packet, nullptr); // we have to transmit in order to receive
}
#endif
#if USE_DMAC
-// Our choice of DMA channels to use
-const uint32_t CONF_SPI_DMAC_TX_CH = 1;
-const uint32_t CONF_SPI_DMAC_RX_CH = 2;
-
-// Hardware IDs of the SPI transmit and receive DMA interfaces. See atsam datasheet.
-const uint32_t DMA_HW_ID_SPI_TX = 1;
-const uint32_t DMA_HW_ID_SPI_RX = 2;
-
static inline void spi_rx_dma_enable() noexcept
{
- dmac_channel_enable(DMAC, CONF_SPI_DMAC_RX_CH);
+ dmac_channel_enable(DMAC, DmacChanW5500Rx);
+ dmac_channel_enable(DMAC, DmacChanW5500Tx);
}
static inline void spi_tx_dma_enable() noexcept
{
- dmac_channel_enable(DMAC, CONF_SPI_DMAC_TX_CH);
+ dmac_channel_enable(DMAC, DmacChanW5500Tx);
}
static inline void spi_rx_dma_disable() noexcept
{
- dmac_channel_disable(DMAC, CONF_SPI_DMAC_RX_CH);
+ dmac_channel_disable(DMAC, DmacChanW5500Tx);
+ dmac_channel_disable(DMAC, DmacChanW5500Rx);
}
static inline void spi_tx_dma_disable() noexcept
{
- dmac_channel_disable(DMAC, CONF_SPI_DMAC_TX_CH);
+ dmac_channel_disable(DMAC, DmacChanW5500Tx);
}
static bool spi_dma_check_rx_complete() noexcept
{
uint32_t status = DMAC->DMAC_CHSR;
- if ( ((status & (DMAC_CHSR_ENA0 << CONF_SPI_DMAC_RX_CH)) == 0) // controller is not enabled, perhaps because it finished a full buffer transfer
- || ((status & (DMAC_CHSR_EMPT0 << CONF_SPI_DMAC_RX_CH)) != 0) // controller is enabled, probably suspended, and the FIFO is empty
+ if ( ((status & (DMAC_CHSR_ENA0 << DmacChanW5500Rx)) == 0) // controller is not enabled, perhaps because it finished a full buffer transfer
+ || ((status & (DMAC_CHSR_EMPT0 << DmacChanW5500Rx)) != 0) // controller is enabled, probably suspended, and the FIFO is empty
)
{
// Disable the channel.
// We also need to set the resume bit, otherwise it remains suspended when we re-enable it.
- DMAC->DMAC_CHDR = (DMAC_CHDR_DIS0 << CONF_SPI_DMAC_RX_CH) | (DMAC_CHDR_RES0 << CONF_SPI_DMAC_RX_CH);
+ DMAC->DMAC_CHDR = (DMAC_CHDR_DIS0 << DmacChanW5500Rx) | (DMAC_CHDR_RES0 << DmacChanW5500Rx);
return true;
}
return false;
}
-static void spi_tx_dma_setup(const TransactionBuffer *buf, uint32_t maxTransmitLength) noexcept
+static inline bool spi_dma_check_tx_complete() noexcept
+{
+ uint32_t status = DMAC->DMAC_CHSR;
+ return ((status & (DMAC_CHSR_ENA0 << DmacChanW5500Tx)) == 0) // controller is not enabled, perhaps because it finished a full buffer transfer
+ || ((status & (DMAC_CHSR_EMPT0 << DmacChanW5500Tx)) != 0); // controller is enabled, probably suspended, and the FIFO is empty
+}
+
+static void spi_tx_dma_setup(const uint8_t *buf, uint32_t length) noexcept
{
- DMAC->DMAC_EBCISR; // clear any pending interrupts
+ DMAC->DMAC_EBCISR; // clear any pending interrupts
- dmac_channel_set_source_addr(DMAC, CONF_SPI_DMAC_TX_CH, reinterpret_cast<uint32_t>(buf));
- dmac_channel_set_destination_addr(DMAC, CONF_SPI_DMAC_TX_CH, reinterpret_cast<uint32_t>(&(W5500_SPI->SPI_TDR)));
- dmac_channel_set_descriptor_addr(DMAC, CONF_SPI_DMAC_TX_CH, 0);
- dmac_channel_set_ctrlA(DMAC, CONF_SPI_DMAC_TX_CH, maxTransmitLength | DMAC_CTRLA_SRC_WIDTH_WORD | DMAC_CTRLA_DST_WIDTH_BYTE);
- dmac_channel_set_ctrlB(DMAC, CONF_SPI_DMAC_TX_CH,
+ dmac_channel_set_source_addr(DMAC, DmacChanW5500Tx, reinterpret_cast<uint32_t>(buf));
+ dmac_channel_set_destination_addr(DMAC, DmacChanW5500Tx, reinterpret_cast<uint32_t>(&(W5500_SPI->SPI_TDR)));
+ dmac_channel_set_descriptor_addr(DMAC, DmacChanW5500Tx, 0);
+ dmac_channel_set_ctrlA(DMAC, DmacChanW5500Tx, length | DMAC_CTRLA_SRC_WIDTH_WORD | DMAC_CTRLA_DST_WIDTH_BYTE);
+ dmac_channel_set_ctrlB(DMAC, DmacChanW5500Tx,
DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_DST_INCR_FIXED);
}
-static void spi_rx_dma_setup(const TransactionBuffer *buf) noexcept
+static void spi_rx_dma_setup(uint8_t *buf, uint32_t length) noexcept
{
- DMAC->DMAC_EBCISR; // clear any pending interrupts
+ DMAC->DMAC_EBCISR; // clear any pending interrupts
- dmac_channel_set_source_addr(DMAC, CONF_SPI_DMAC_RX_CH, reinterpret_cast<uint32_t>(&(W5500_SPI->SPI_RDR)));
- dmac_channel_set_destination_addr(DMAC, CONF_SPI_DMAC_RX_CH, reinterpret_cast<uint32_t>(buf));
- dmac_channel_set_descriptor_addr(DMAC, CONF_SPI_DMAC_RX_CH, 0);
-// dmac_channel_set_ctrlA(DMAC, CONF_SPI_DMAC_RX_CH, TransactionBuffer::MaxTransferBytes | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_WORD);
- dmac_channel_set_ctrlB(DMAC, CONF_SPI_DMAC_RX_CH,
+ dmac_channel_set_source_addr(DMAC, DmacChanW5500Rx, reinterpret_cast<uint32_t>(&(W5500_SPI->SPI_RDR)));
+ dmac_channel_set_destination_addr(DMAC, DmacChanW5500Rx, reinterpret_cast<uint32_t>(buf));
+ dmac_channel_set_descriptor_addr(DMAC, DmacChanW5500Rx, 0);
+ dmac_channel_set_ctrlA(DMAC, DmacChanW5500Rx, length | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_WORD);
+ dmac_channel_set_ctrlB(DMAC, DmacChanW5500Rx,
DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_PER2MEM_DMA_FC | DMAC_CTRLB_SRC_INCR_FIXED | DMAC_CTRLB_DST_INCR_INCREMENTING);
+ spi_tx_dma_setup(buf, length); // we have to transmit in order to receive
}
#endif
@@ -170,15 +173,12 @@ namespace WizSpi
void Init() noexcept
{
#if USE_PDC
- spi_pdc = spi_get_pdc_base(W5500_SPI);
- // The PDCs are masters 2 and 3 and the SRAM is slave 0. Give the receive PDCs the highest priority.
+ // The SPI PDC is on peripheral bridge 0 which is master #2. Give the SPI PDC the highest priority.
matrix_set_master_burst_type(0, MATRIX_ULBT_8_BEAT_BURST);
matrix_set_slave_default_master_type(0, MATRIX_DEFMSTR_LAST_DEFAULT_MASTER);
- matrix_set_slave_priority(0, (3 << MATRIX_PRAS0_M2PR_Pos) | (3 << MATRIX_PRAS0_M3PR_Pos));
+ matrix_set_slave_priority(0, 3 << MATRIX_PRAS0_M2PR_Pos);
matrix_set_slave_slot_cycle(0, 8);
-#endif
-
-#if USE_DMAC
+#elif USE_DMAC
pmc_enable_periph_clk(ID_DMAC);
dmac_init(DMAC);
dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN);
@@ -203,7 +203,6 @@ namespace WizSpi
#if USE_PDC || USE_DMAC
spi_dma_disable();
#endif
-
spi_reset(W5500_SPI); // this clears the transmit and receive registers and puts the SPI into slave mode
W5500_SPI->SPI_MR = SPI_MR_MSTR // master mode
| SPI_MR_MODFDIS // disable fault detection
@@ -221,12 +220,10 @@ namespace WizSpi
#if USE_DMAC
// Configure DMA RX channel
- dmac_channel_set_configuration(DMAC, CONF_SPI_DMAC_RX_CH,
- DMAC_CFG_SRC_PER(DMA_HW_ID_SPI_RX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG);
+ dmac_channel_set_configuration(DMAC, DmacChanW5500Rx, DMAC_CFG_SRC_PER(DMA_HW_ID_SPI_RX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG);
// Configure DMA TX channel
- dmac_channel_set_configuration(DMAC, CONF_SPI_DMAC_TX_CH,
- DMAC_CFG_DST_PER(DMA_HW_ID_SPI_TX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG);
+ dmac_channel_set_configuration(DMAC, DmacChanW5500Tx, DMAC_CFG_DST_PER(DMA_HW_ID_SPI_TX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG);
#endif
}
@@ -234,7 +231,7 @@ namespace WizSpi
{
NVIC_DisableIRQ(W5500_SPI_IRQn);
spi_disable(W5500_SPI);
-#if USE_PDC || USE_DMA
+#if USE_PDC || USE_DMAC
spi_dma_disable();
#endif
}
@@ -363,7 +360,7 @@ namespace WizSpi
(void)W5500_SPI->SPI_RDR; // clear previous data
}
-#if USE_PDC
+#if USE_PDC || USE_DMAC
spi_rx_dma_setup(rx_data, len);
spi_rx_dma_enable();
uint32_t timeout = SPI_TIMEOUT;
@@ -371,7 +368,11 @@ namespace WizSpi
{
--timeout;
}
+ // The SPI peripheral signals transfer complete at the start of transferring the last byte. If we disable the DMA too soon, there might be a chance
+ // that the transfer does not complete. Therefore, delay disabling DMA until we have invalidated the cache, which takes some time.
+ Cache::InvalidateAfterDMAReceive(rx_data, len);
spi_rx_dma_disable();
+
if (timeout == 0)
{
return SPI_ERROR_TIMEOUT;
@@ -413,7 +414,8 @@ namespace WizSpi
{
if (len != 0)
{
-#if USE_PDC
+#if USE_PDC || USE_DMAC
+ Cache::FlushBeforeDMASend(tx_data, len);
spi_tx_dma_setup(tx_data, len);
spi_tx_dma_enable();
uint32_t timeout = SPI_TIMEOUT;
diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp
index 215c7414..5bffcd3c 100644
--- a/src/ObjectModel/ObjectModel.cpp
+++ b/src/ObjectModel/ObjectModel.cpp
@@ -1072,10 +1072,6 @@ decrease(strlen(idString)) // recursion variant
throw context.ConstructParseException("array index out of bounds");
}
- if (context.WantExists())
- {
- return ExpressionValue(true);
- }
return ExpressionValue((int32_t)(Bitmap<uint32_t>::MakeFromRaw(val.uVal).GetSetBitNumber(context.GetLastIndex())));
}
}
@@ -1121,11 +1117,6 @@ decrease(strlen(idString)) // recursion variant
throw context.ConstructParseException("array index out of bounds");
}
- if (context.WantExists())
- {
- return ExpressionValue(true);
- }
-
return ExpressionValue((int32_t)(Bitmap<uint64_t>::MakeFromRaw(val.Get56BitValue()).GetSetBitNumber(context.GetLastIndex())));
}
}
diff --git a/src/Platform/OutputMemory.cpp b/src/Platform/OutputMemory.cpp
index b2ac7433..14a1e368 100644
--- a/src/Platform/OutputMemory.cpp
+++ b/src/Platform/OutputMemory.cpp
@@ -22,26 +22,29 @@ void OutputBuffer::Append(OutputBuffer *other) noexcept
if (other != nullptr)
{
last->next = other;
- last = other->last;
+ OutputBuffer * const newLast = other->last;
if (other->hadOverflow)
{
hadOverflow = true;
}
- for (OutputBuffer *item = Next(); item != other; item = item->Next())
+ OutputBuffer *item = this;
+ do
{
- item->last = last;
+ item->last = newLast;
+ item = item->Next();
}
+ while (item != other);
}
}
void OutputBuffer::IncreaseReferences(size_t refs) noexcept
{
- if (refs > 0)
+ if (refs != 0)
{
TaskCriticalSectionLocker lock;
- for(OutputBuffer *item = this; item != nullptr; item = item->Next())
+ for (OutputBuffer *item = this; item != nullptr; item = item->Next())
{
item->references += refs;
item->isReferenced = true;
@@ -59,20 +62,6 @@ size_t OutputBuffer::Length() const noexcept
return totalLength;
}
-char &OutputBuffer::operator[](size_t index) noexcept
-{
- // Get the right buffer to access
- OutputBuffer *itemToIndex = this;
- while (index >= itemToIndex->DataLength())
- {
- index -= itemToIndex->DataLength();
- itemToIndex = itemToIndex->Next();
- }
-
- // Return the char reference
- return itemToIndex->data[index];
-}
-
char OutputBuffer::operator[](size_t index) const noexcept
{
// Get the right buffer to access
@@ -89,7 +78,7 @@ char OutputBuffer::operator[](size_t index) const noexcept
const char *OutputBuffer::Read(size_t len) noexcept
{
- size_t offset = bytesRead;
+ const size_t offset = bytesRead;
bytesRead += len;
return data + offset;
}
@@ -120,7 +109,7 @@ size_t OutputBuffer::printf(const char *_ecv_array fmt, ...) noexcept
{
va_list vargs;
va_start(vargs, fmt);
- size_t ret = vprintf(fmt, vargs);
+ const size_t ret = vprintf(fmt, vargs);
va_end(vargs);
return ret;
}
@@ -138,7 +127,7 @@ size_t OutputBuffer::catf(const char *_ecv_array fmt, ...) noexcept
{
va_list vargs;
va_start(vargs, fmt);
- size_t ret = vcatf(fmt, vargs);
+ const size_t ret = vcatf(fmt, vargs);
va_end(vargs);
return ret;
}
@@ -146,9 +135,13 @@ size_t OutputBuffer::catf(const char *_ecv_array fmt, ...) noexcept
size_t OutputBuffer::lcatf(const char *_ecv_array fmt, ...) noexcept
{
size_t extra = 0;
- if (Length() != 0 && operator[](Length() - 1) != '\n')
+ if (last->dataLength != 0 && last->data[last->dataLength - 1] != '\n')
{
extra = cat('\n');
+ if (extra == 0)
+ {
+ return 0;
+ }
}
va_list vargs;
@@ -235,11 +228,12 @@ size_t OutputBuffer::cat(const char *_ecv_array src, size_t len) noexcept
}
nextBuffer->references = references;
last->next = nextBuffer;
- last = nextBuffer->last;
- for (OutputBuffer *item = Next(); item != nextBuffer; item = item->Next())
+ OutputBuffer *item = this;
+ do
{
- item->last = last;
- }
+ item->last = nextBuffer;
+ item = item->Next();
+ } while (item != nextBuffer);
}
const size_t copyLength = min<size_t>(len - copied, OUTPUT_BUFFER_SIZE - last->dataLength);
memcpy(last->data + last->dataLength, src + copied, copyLength);
@@ -251,11 +245,17 @@ size_t OutputBuffer::cat(const char *_ecv_array src, size_t len) noexcept
size_t OutputBuffer::lcat(const char *_ecv_array src, size_t len) noexcept
{
- if (Length() != 0)
+ size_t extra = 0;
+ if (last->dataLength != 0 && last->data[last->dataLength - 1] != '\n')
{
- cat('\n');
+ extra = cat('\n');
+ if (extra == 0)
+ {
+ return 0;
+ }
}
- return cat(src, len);
+
+ return cat(src, len) + extra;
}
size_t OutputBuffer::cat(StringRef &str) noexcept
@@ -294,13 +294,11 @@ size_t OutputBuffer::EncodeChar(char c) noexcept
if (esc != 0)
{
- cat('\\');
- cat(esc);
- return 2;
+ const size_t written = cat('\\');
+ return (written == 0) ? written : written + cat(esc);
}
- cat(c);
- return 1;
+ return cat(c);
}
size_t OutputBuffer::EncodeReply(OutputBuffer *src) noexcept
diff --git a/src/Platform/OutputMemory.h b/src/Platform/OutputMemory.h
index c8a3f59b..0ef8cd53 100644
--- a/src/Platform/OutputMemory.h
+++ b/src/Platform/OutputMemory.h
@@ -35,7 +35,6 @@ public:
size_t DataLength() const noexcept { return dataLength; } // How many bytes have been written to this instance?
size_t Length() const noexcept; // How many bytes have been written to the whole chain?
- char& operator[](size_t index) noexcept;
char operator[](size_t index) const noexcept;
const char *_ecv_array Read(size_t len) noexcept;
void Taken(size_t len) noexcept { bytesRead += len; }
diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp
index 23942868..4737d85a 100644
--- a/src/Platform/Platform.cpp
+++ b/src/Platform/Platform.cpp
@@ -551,40 +551,6 @@ void Platform::Init() noexcept
# endif
#endif
-#if defined(DUET_06_085)
- ARRAY_INIT(defaultMacAddress, DefaultMacAddress);
-
- // Motor current setting on Duet 0.6 and 0.8.5
- I2C::Init();
- mcpExpansion.setMCP4461Address(0x2E); // not required for mcpDuet, as this uses the default address
- ARRAY_INIT(potWipes, POT_WIPES);
- senseResistor = SENSE_RESISTOR;
- maxStepperDigipotVoltage = MAX_STEPPER_DIGIPOT_VOLTAGE;
- stepperDacVoltageRange = STEPPER_DAC_VOLTAGE_RANGE;
- stepperDacVoltageOffset = STEPPER_DAC_VOLTAGE_OFFSET;
-#elif defined(__ALLIGATOR__)
- pinMode(EthernetPhyResetPin, INPUT); // Init Ethernet Phy Reset Pin
-
- // Alligator Init DAC for motor current vref
- ARRAY_INIT(spiDacCS, SPI_DAC_CS);
- dacAlligator.Init(spiDacCS[0]);
- dacPiggy.Init(spiDacCS[1]);
- // Get macaddress from EUI48 eeprom
- eui48MacAddress.Init(Eui48csPin);
- if (!eui48MacAddress.getEUI48(defaultMacAddress))
- {
- ARRAY_INIT(defaultMacAddress, DefaultMacAddress);
- }
-
- Microstepping::Init(); // Init Motor FAULT detect Pin
- pinMode(ExpansionVoltageLevelPin, ExpansionVoltageLevel==3 ? OUTPUT_LOW : OUTPUT_HIGH); // Init Expansion Voltage Level Pin
- pinMode(MotorFaultDetectPin,INPUT); // Init Motor FAULT detect Pin
- pinMode(ExpansionPiggyDetectPin,INPUT); // Init Expansion Piggy module presence Pin
- pinMode(FTDIconverterResetPin,INPUT); // Init FTDI Serial Converter Reset Pin
- pinMode(SpiEEPROMcsPin,OUTPUT_HIGH); // Init Spi EEPROM Cs pin, not implemented, default unselected
- pinMode(SpiFLASHcsPin,OUTPUT_HIGH); // Init Spi FLASH Cs pin, not implemented, default unselected
-#endif
-
#if defined(__LPC17xx__)
if (hasDriverCurrentControl)
{
@@ -646,6 +612,7 @@ void Platform::Init() noexcept
// Set up the local drivers. Do this after we have read any direction pins that specify the board type.
#ifdef DUET3_MB6XD
+ ENABLE_PINS = (GetBoardType() == BoardType::Duet3_6XD_v01) ? ENABLE_PINS_v01 : ENABLE_PINS_v100;
unsigned int numErrorHighDrivers = 0;
#endif
for (size_t driver = 0; driver < NumDirectDrivers; ++driver)
@@ -3793,12 +3760,15 @@ void Platform::SetBoardType(BoardType bt) noexcept
? BoardType::Duet3Mini_WiFi
: BoardType::Duet3Mini_Ethernet;
#elif defined(DUET3_MB6HC)
- // Driver 0 direction has a pulldown resistor on v0.6 and v1.0 boards, but won't on v1.01 boards
+ // Driver 0 direction has a pulldown resistor on v0.6 and v1.0 boards, but not on v1.01 boards
pinMode(DIRECTION_PINS[0], INPUT_PULLUP);
delayMicroseconds(20); // give the pullup resistor time to work
board = (digitalRead(DIRECTION_PINS[0])) ? BoardType::Duet3_6HC_v101 : BoardType::Duet3_6HC_v06_100;
#elif defined(DUET3_MB6XD)
- board = BoardType::Duet3_6XD;
+ // Driver 0 direction has a pulldown resistor on v1.0 boards, but not on v0.1 boards
+ pinMode(DIRECTION_PINS[0], INPUT_PULLUP);
+ delayMicroseconds(20); // give the pullup resistor time to work
+ board = (digitalRead(DIRECTION_PINS[0])) ? BoardType::Duet3_6XD_v01 : BoardType::Duet3_6XD_v100;
#elif defined(FMDC_V02) || defined(FMDC_V03)
board = BoardType::FMDC;
#elif defined(SAME70XPLD)
@@ -3878,7 +3848,8 @@ const char *_ecv_array Platform::GetElectronicsString() const noexcept
case BoardType::Duet3_6HC_v06_100: return "Duet 3 " BOARD_SHORT_NAME " v0.6 or 1.0";
case BoardType::Duet3_6HC_v101: return "Duet 3 " BOARD_SHORT_NAME " v1.01 or later";
#elif defined(DUET3_MB6XD)
- case BoardType::Duet3_6XD: return "Duet 3 " BOARD_SHORT_NAME; // we have only one version at present
+ case BoardType::Duet3_6XD_v01: return "Duet 3 " BOARD_SHORT_NAME " v0.1";
+ case BoardType::Duet3_6XD_v100: return "Duet 3 " BOARD_SHORT_NAME " v1.0 or later";
#elif defined(FMDC_V02) || defined(FMDC_V03)
case BoardType::FMDC: return "Duet 3 " BOARD_SHORT_NAME;
#elif defined(SAME70XPLD)
@@ -3917,7 +3888,8 @@ const char *_ecv_array Platform::GetBoardString() const noexcept
case BoardType::Duet3_6HC_v06_100: return "duet3mb6hc100";
case BoardType::Duet3_6HC_v101: return "duet3mb6hc101";
#elif defined(DUET3_MB6XD)
- case BoardType::Duet3_6XD: return "duet3mb6xd"; // we have only one version at present
+ case BoardType::Duet3_6XD_v01: return "duet3mb6xd001"; // we have only one version at present
+ case BoardType::Duet3_6XD_v100: return "duet3mb6xd100"; // we have only one version at present
#elif defined(FMDC_V02) || defined(FMDC_V03)
case BoardType::FMDC: return "fmdc";
#elif defined(SAME70XPLD)
diff --git a/src/Platform/Platform.h b/src/Platform/Platform.h
index 2cf433a1..36462474 100644
--- a/src/Platform/Platform.h
+++ b/src/Platform/Platform.h
@@ -127,7 +127,8 @@ enum class BoardType : uint8_t
Duet3_6HC_v06_100 = 1,
Duet3_6HC_v101 = 2,
#elif defined(DUET3_MB6XD)
- Duet3_6XD = 1,
+ Duet3_6XD_v01 = 1,
+ Duet3_6XD_v100 = 2,
#elif defined(FMDC_V02) || defined(FMDC_V03)
FMDC,
#elif defined(SAME70XPLD)
@@ -790,6 +791,7 @@ private:
uint32_t stepPulseMinimumPeriodClocks; // minimum period between leading edges of step pulses, in step clocks
uint32_t directionSetupClocks; // minimum direction change to step high time, in step clocks
uint32_t directionHoldClocksFromLeadingEdge; // minimum step high to direction low step clocks, calculated from the step low to direction change hold time
+ const Pin *ENABLE_PINS; // 6XD version 0.1 uses different enable pins from version 1.0 and later
#else
uint32_t slowDriversBitmap; // bitmap of driver port bits that need extended step pulse timing
uint32_t slowDriverStepTimingClocks[4]; // minimum step high, step low, dir setup and dir hold timing for slow drivers
diff --git a/src/Version.h b/src/Version.h
index 8a6cdf11..ea28bdb2 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -10,7 +10,7 @@
#ifndef VERSION
// Note: the complete VERSION string must be in standard version number format and must not contain spaces! This is so that DWC can parse it.
-# define MAIN_VERSION "3.4.1rc1"
+# define MAIN_VERSION "3.4.1rc2"
# ifdef USE_CAN0
# define VERSION_SUFFIX "(CAN0)"
# else