diff options
author | David Crocker <dcrocker@eschertech.com> | 2022-05-27 17:51:01 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2022-05-27 17:51:01 +0300 |
commit | 539c6f40cc1dedc08a5e157cd3b6d27bf3b37db2 (patch) | |
tree | df26ce69a887732356f36417d12d4fbf68e6d172 | |
parent | 8a8d675ade52b4b524b6c26713a6d61ea7ec4861 (diff) | |
parent | 8c5715d207701cf3af2b38bd8499637496e3ce77 (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.h | 3 | ||||
-rw-r--r-- | src/Config/Pins_DuetNG.h | 6 | ||||
-rw-r--r-- | src/GCodes/GCodes2.cpp | 18 | ||||
-rw-r--r-- | src/Networking/UploadingNetworkResponder.cpp | 10 | ||||
-rw-r--r-- | src/Networking/W5500Ethernet/Wiznet/Ethernet/WizSpi.cpp | 106 | ||||
-rw-r--r-- | src/ObjectModel/ObjectModel.cpp | 9 | ||||
-rw-r--r-- | src/Platform/OutputMemory.cpp | 68 | ||||
-rw-r--r-- | src/Platform/OutputMemory.h | 1 | ||||
-rw-r--r-- | src/Platform/Platform.cpp | 48 | ||||
-rw-r--r-- | src/Platform/Platform.h | 4 | ||||
-rw-r--r-- | src/Version.h | 2 |
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 |