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:
-rw-r--r--src/Comms/FirmwareUpdater.cpp39
-rw-r--r--src/Comms/FirmwareUpdater.h9
-rw-r--r--src/Comms/PanelDueUpdater.cpp11
-rw-r--r--src/Comms/PanelDueUpdater.h6
-rw-r--r--src/GCodes/GCodes.cpp5
-rw-r--r--src/GCodes/GCodes.h3
-rw-r--r--src/GCodes/GCodes3.cpp34
-rw-r--r--src/GCodes/GCodes4.cpp12
-rw-r--r--src/RepRap.cpp23
-rw-r--r--src/RepRap.h6
-rw-r--r--src/bossa/Flasher.cpp8
-rw-r--r--src/bossa/Flasher.h4
12 files changed, 100 insertions, 60 deletions
diff --git a/src/Comms/FirmwareUpdater.cpp b/src/Comms/FirmwareUpdater.cpp
index 780aa8db..8b60378b 100644
--- a/src/Comms/FirmwareUpdater.cpp
+++ b/src/Comms/FirmwareUpdater.cpp
@@ -29,41 +29,51 @@ namespace FirmwareUpdater
// Check that the prerequisites are satisfied.
// Return true if yes, else print a message and return false.
- GCodeResult CheckFirmwareUpdatePrerequisites(uint8_t moduleMap, GCodeBuffer& gb, const StringRef& reply, const size_t serialChannel) noexcept
+ GCodeResult CheckFirmwareUpdatePrerequisites(
+ Bitmap<uint8_t> moduleMap,
+ GCodeBuffer& gb,
+ const StringRef& reply,
+ const size_t serialChannel,
+ const StringRef& filenameRef) noexcept
{
#if HAS_WIFI_NETWORKING
- if ( (moduleMap & (1 << WifiExternalFirmwareModule)) != 0
- || (moduleMap & (1 << WifiFirmwareModule)) != 0)
+ if (moduleMap.IsBitSet(WifiExternalFirmwareModule) || moduleMap.IsBitSet(WifiFirmwareModule))
{
GCodeResult result;
if (!reprap.GetGCodes().CheckNetworkCommandAllowed(gb, reply, result))
{
return result;
}
- if ((moduleMap & (1 << WifiExternalFirmwareModule)) != 0 && (moduleMap & (1 << WifiFirmwareModule)) != 0)
+ if (moduleMap.IsBitSet(WifiExternalFirmwareModule) && moduleMap.IsBitSet(WifiFirmwareModule))
{
reply.copy("Invalid combination of firmware update modules");
return GCodeResult::error;
}
- if ((moduleMap & (1 << WifiFirmwareModule)) != 0
- && !reprap.GetPlatform().FileExists(FIRMWARE_DIRECTORY, WIFI_FIRMWARE_FILE))
+ if (moduleMap.IsBitSet(WifiFirmwareModule))
{
- reply.printf("File %s not found", FIRMWARE_DIRECTORY WIFI_FIRMWARE_FILE);
- return GCodeResult::error;
+ String<MaxFilenameLength> location;
+ if (!MassStorage::CombineName(location.GetRef(), FIRMWARE_DIRECTORY, filenameRef.IsEmpty() ? WIFI_FIRMWARE_FILE : filenameRef.c_str())
+ || !MassStorage::FileExists(location.c_str()))
+ {
+ reply.printf("File %s not found", location.c_str());
+ return GCodeResult::error;
+ }
}
}
#endif
#if HAS_AUX_DEVICES
- if ((moduleMap & (1 << PanelDueFirmwareModule)) != 0)
+ if (moduleMap.IsBitSet(PanelDueFirmwareModule))
{
if (!reprap.GetPlatform().IsAuxEnabled(serialChannel-1) || reprap.GetPlatform().IsAuxRaw(serialChannel-1))
{
reply.printf("Aux port %d is not enabled or not in PanelDue mode", serialChannel-1);
return GCodeResult::error;
}
- if (!reprap.GetPlatform().FileExists(FIRMWARE_DIRECTORY, PANEL_DUE_FIRMWARE_FILE))
+ String<MaxFilenameLength> location;
+ if (!MassStorage::CombineName(location.GetRef(), FIRMWARE_DIRECTORY, filenameRef.IsEmpty() ? PANEL_DUE_FIRMWARE_FILE : filenameRef.c_str())
+ || !MassStorage::FileExists(location.c_str()))
{
- reply.printf("File %s not found", PanelDueUpdater::firmwareFilename);
+ reply.printf("File %s not found", location.c_str());
return GCodeResult::error;
}
}
@@ -88,7 +98,7 @@ namespace FirmwareUpdater
return true;
}
- void UpdateModule(unsigned int module, const size_t serialChannel) noexcept
+ void UpdateModule(unsigned int module, const size_t serialChannel, const StringRef& filenameRef) noexcept
{
#if HAS_WIFI_NETWORKING || HAS_AUX_DEVICES
switch(module)
@@ -111,7 +121,8 @@ namespace FirmwareUpdater
WifiFirmwareUploader * const uploader = reprap.GetNetwork().GetWifiUploader();
if (uploader != nullptr)
{
- uploader->SendUpdateFile(WIFI_FIRMWARE_FILE, FIRMWARE_DIRECTORY, WifiFirmwareUploader::FirmwareAddress);
+ const char* binaryFilename = filenameRef.IsEmpty() ? WIFI_FIRMWARE_FILE : filenameRef.c_str();
+ uploader->SendUpdateFile(binaryFilename, FIRMWARE_DIRECTORY, WifiFirmwareUploader::FirmwareAddress);
}
}
break;
@@ -124,7 +135,7 @@ namespace FirmwareUpdater
{
platform.InitPanelDueUpdater();
}
- platform.GetPanelDueUpdater()->Start(serialChannel);
+ platform.GetPanelDueUpdater()->Start(filenameRef, serialChannel);
}
# endif
}
diff --git a/src/Comms/FirmwareUpdater.h b/src/Comms/FirmwareUpdater.h
index aa9f8f0a..4e4d4530 100644
--- a/src/Comms/FirmwareUpdater.h
+++ b/src/Comms/FirmwareUpdater.h
@@ -17,9 +17,14 @@ namespace FirmwareUpdater
const unsigned int PanelDueFirmwareModule = 4;
#endif
- GCodeResult CheckFirmwareUpdatePrerequisites(uint8_t moduleMap, GCodeBuffer& gb, const StringRef& reply, size_t serialChannel) noexcept;
+ GCodeResult CheckFirmwareUpdatePrerequisites(
+ Bitmap<uint8_t> moduleMap,
+ GCodeBuffer& gb,
+ const StringRef& reply,
+ size_t serialChannel,
+ const StringRef& filenameRef) noexcept;
bool IsReady() noexcept;
- void UpdateModule(unsigned int module, const size_t serialChannel) noexcept;
+ void UpdateModule(unsigned int module, const size_t serialChannel, const StringRef& filenameRef) noexcept;
}
#endif /* SRC_NETWORKING_FIRMWAREUPDATER_H_ */
diff --git a/src/Comms/PanelDueUpdater.cpp b/src/Comms/PanelDueUpdater.cpp
index 5789501b..353f2458 100644
--- a/src/Comms/PanelDueUpdater.cpp
+++ b/src/Comms/PanelDueUpdater.cpp
@@ -108,6 +108,7 @@ PanelDueUpdater::PanelDueUpdater() noexcept
, offset(0)
, erasedAndResetAt(0)
, state(FlashState::idle)
+ , filename(nullptr)
{
}
@@ -120,13 +121,14 @@ PanelDueUpdater::~PanelDueUpdater() noexcept
delete flasher;
}
-void PanelDueUpdater::Start(const uint32_t serialChan) noexcept
+void PanelDueUpdater::Start(const StringRef& filenameRef, const uint32_t serialChan) noexcept
{
if (state != FlashState::idle)
{
return;
}
serialChannel = serialChan;
+ filename = filenameRef.IsEmpty() ? PANEL_DUE_FIRMWARE_FILE : filenameRef.c_str();
state = FlashState::eraseAndReset;
}
@@ -204,7 +206,7 @@ void PanelDueUpdater::Spin() noexcept
case FlashState::bossaWrite:
{
- bool done = flasher->write(firmwareFilename, offset);
+ bool done = flasher->write(filename, FIRMWARE_DIRECTORY, offset);
if (done)
{
offset = 0; // Reset it for verification
@@ -218,7 +220,7 @@ void PanelDueUpdater::Spin() noexcept
{
uint32_t pageErrors;
uint32_t totalErrors;
- bool done = flasher->verify(firmwareFilename, pageErrors, totalErrors, offset);
+ bool done = flasher->verify(filename, FIRMWARE_DIRECTORY, pageErrors, totalErrors, offset);
if (done && pageErrors == 0)
{
state = FlashState::bossaWriteOptions;
@@ -283,6 +285,9 @@ void PanelDueUpdater::Spin() noexcept
offset = 0;
erasedAndResetAt = 0;
+
+ filename = nullptr;
+
state = FlashState::idle;
}
break;
diff --git a/src/Comms/PanelDueUpdater.h b/src/Comms/PanelDueUpdater.h
index b48ae7b4..a92abfbd 100644
--- a/src/Comms/PanelDueUpdater.h
+++ b/src/Comms/PanelDueUpdater.h
@@ -33,12 +33,9 @@ public:
PanelDueUpdater() noexcept;
virtual ~PanelDueUpdater() noexcept;
void Spin() noexcept;
- void Start(const uint32_t serialChan = 1) noexcept;
+ void Start(const StringRef& filenameRef, const uint32_t serialChan = 1) noexcept;
bool Idle() const noexcept { return state == FlashState::idle; }
- // For now fix the filename here
- constexpr static const char* const firmwareFilename = FIRMWARE_DIRECTORY PANEL_DUE_FIRMWARE_FILE;
-
private:
NamedEnum(FlashState, uint8_t,
idle,
@@ -65,6 +62,7 @@ private:
uint32_t offset;
uint32_t erasedAndResetAt;
FlashState state;
+ const char* filename;
UARTClass* GetAuxPort() noexcept;
};
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index d4a1fb70..6f9613d7 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -296,7 +296,10 @@ void GCodes::Reset() noexcept
#endif
pausePending = filamentChangePausePending = false;
moveBuffer.filePos = noFilePosition;
- firmwareUpdateModuleMap = 0;
+ firmwareUpdateModuleMap.Clear();
+ filenameString.Clear();
+ isFlashing = false;
+ isFlashingPanelDue = false;
lastFilamentError = FilamentSensorStatus::ok;
currentZProbeNumber = 0;
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index d0dda5d0..8e59d083 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -635,7 +635,8 @@ private:
TriggerNumbersBitmap triggersPending; // Bitmap of triggers pending but not yet executed
// Firmware update
- uint8_t firmwareUpdateModuleMap; // Bitmap of firmware modules to be updated
+ Bitmap<uint8_t> firmwareUpdateModuleMap; // Bitmap of firmware modules to be updated
+ String<MaxFilenameLength> filenameString; // Filename for the current update
bool isFlashing; // Is a new firmware binary going to be flashed?
bool isFlashingPanelDue; // Are we in the process of flashing PanelDue?
diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp
index 59f65f09..a985a576 100644
--- a/src/GCodes/GCodes3.cpp
+++ b/src/GCodes/GCodes3.cpp
@@ -1102,7 +1102,7 @@ GCodeResult GCodes::UpdateFirmware(GCodeBuffer& gb, const StringRef &reply)
reprap.GetHeat().SwitchOffAll(true); // turn all heaters off because the main loop may get suspended
DisableDrives(); // all motors off
- if (firmwareUpdateModuleMap == 0) // have we worked out which modules to update?
+ if (firmwareUpdateModuleMap.IsEmpty()) // have we worked out which modules to update?
{
// Find out which modules we have been asked to update
if (gb.Seen('S'))
@@ -1116,42 +1116,54 @@ GCodeResult GCodes::UpdateFirmware(GCodeBuffer& gb, const StringRef &reply)
if (t >= NumFirmwareUpdateModules)
{
reply.printf("Invalid module number '%" PRIu32 "'\n", t);
- firmwareUpdateModuleMap = 0;
+ firmwareUpdateModuleMap.Clear();
return GCodeResult::error;
break;
}
- firmwareUpdateModuleMap |= (1u << t);
+ firmwareUpdateModuleMap.SetBit(t);
}
}
else
{
- firmwareUpdateModuleMap = (1u << 0); // no modules specified, so update module 0 to match old behaviour
+ firmwareUpdateModuleMap.SetBit(0); // no modules specified, so update module 0 to match old behaviour
}
- if (firmwareUpdateModuleMap == 0)
+ if (firmwareUpdateModuleMap.IsEmpty())
{
return GCodeResult::ok; // nothing to update
}
+ filenameString.Clear();
+ if (gb.Seen('P'))
+ {
+ if (firmwareUpdateModuleMap.CountSetBits() > 1)
+ {
+ reply.copy("Filename can only be provided when updating excactly one module\n");
+ firmwareUpdateModuleMap.Clear();
+ return GCodeResult::error;
+ }
+ gb.GetQuotedString(filenameString.GetRef());
+ }
+
// Check prerequisites of all modules to be updated, if any are not met then don't update any of them
#if HAS_WIFI_NETWORKING || HAS_AUX_DEVICES
const auto result = FirmwareUpdater::CheckFirmwareUpdatePrerequisites(
firmwareUpdateModuleMap, gb, reply,
# if HAS_AUX_DEVICES
- serialChannelForPanelDueFlashing
+ serialChannelForPanelDueFlashing,
#else
- 0
+ 0,
#endif
- );
+ filenameString.GetRef());
if (result != GCodeResult::ok)
{
- firmwareUpdateModuleMap = 0;
+ firmwareUpdateModuleMap.Clear();
return result;
}
#endif
- if ((firmwareUpdateModuleMap & 1) != 0 && !reprap.CheckFirmwareUpdatePrerequisites(reply))
+ if (firmwareUpdateModuleMap.IsBitSet(0) && !reprap.CheckFirmwareUpdatePrerequisites(reply, filenameString.GetRef()))
{
- firmwareUpdateModuleMap = 0;
+ firmwareUpdateModuleMap.Clear();
return GCodeResult::error;
}
}
diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp
index 7cfa5f86..c5005067 100644
--- a/src/GCodes/GCodes4.cpp
+++ b/src/GCodes/GCodes4.cpp
@@ -471,10 +471,10 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept
bool updating = false;
for (unsigned int module = 1; module < NumFirmwareUpdateModules; ++module)
{
- if ((firmwareUpdateModuleMap & (1u << module)) != 0)
+ if (firmwareUpdateModuleMap.IsBitSet(module))
{
- firmwareUpdateModuleMap &= ~(1u << module);
- FirmwareUpdater::UpdateModule(module, serialChannelForPanelDueFlashing);
+ firmwareUpdateModuleMap.ClearBit(module);
+ FirmwareUpdater::UpdateModule(module, serialChannelForPanelDueFlashing, filenameString.GetRef());
updating = true;
isFlashingPanelDue = (module == FirmwareUpdater::PanelDueFirmwareModule);
break;
@@ -502,11 +502,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept
break;
case GCodeState::flashing2:
- if ((firmwareUpdateModuleMap & 1) != 0)
+ if (firmwareUpdateModuleMap.IsBitSet(0))
{
// Update main firmware
- firmwareUpdateModuleMap = 0;
- reprap.UpdateFirmware();
+ firmwareUpdateModuleMap.Clear();
+ reprap.UpdateFirmware(filenameString.GetRef());
// The above call does not return unless an error occurred
}
isFlashing = false;
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index bb77f424..4b9253b2 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -2682,13 +2682,15 @@ bool RepRap::WriteToolParameters(FileStore *f, const bool forceWriteOffsets) noe
#else
// Check the prerequisites for updating the main firmware. Return True if satisfied, else print a message to 'reply' and return false.
-bool RepRap::CheckFirmwareUpdatePrerequisites(const StringRef& reply) noexcept
+bool RepRap::CheckFirmwareUpdatePrerequisites(const StringRef& reply, const StringRef& filenameRef) noexcept
{
#if HAS_MASS_STORAGE
- FileStore * const firmwareFile = platform->OpenFile(FIRMWARE_DIRECTORY, IAP_FIRMWARE_FILE, OpenMode::read);
+ FileStore * const firmwareFile = platform->OpenFile(FIRMWARE_DIRECTORY, filenameRef.IsEmpty() ? IAP_FIRMWARE_FILE : filenameRef.c_str(), OpenMode::read);
if (firmwareFile == nullptr)
{
- reply.printf("Firmware binary \"%s\" not found", FIRMWARE_DIRECTORY IAP_FIRMWARE_FILE);
+ String<MaxFilenameLength> firmwareBinaryLocation;
+ MassStorage::CombineName(firmwareBinaryLocation.GetRef(), FIRMWARE_DIRECTORY, filenameRef.IsEmpty() ? IAP_FIRMWARE_FILE : filenameRef.c_str());
+ reply.printf("Firmware binary \"%s\" not found", firmwareBinaryLocation.c_str());
return false;
}
@@ -2700,7 +2702,7 @@ bool RepRap::CheckFirmwareUpdatePrerequisites(const StringRef& reply) noexcept
firmwareFile->Seek(32) &&
#endif
- firmwareFile->Read(reinterpret_cast<char*>(&firstDword), sizeof(firstDword)) == (int)sizeof(firstDword);
+ firmwareFile->Read(reinterpret_cast<char*>(&firstDword), sizeof(firstDword)) == (int)sizeof(firstDword);
firmwareFile->Close();
if (!ok || firstDword !=
#if SAME5x
@@ -2727,7 +2729,7 @@ bool RepRap::CheckFirmwareUpdatePrerequisites(const StringRef& reply) noexcept
}
// Update the firmware. Prerequisites should be checked before calling this.
-void RepRap::UpdateFirmware() noexcept
+void RepRap::UpdateFirmware(const StringRef& filenameRef) noexcept
{
#if HAS_MASS_STORAGE
FileStore * const iapFile = platform->OpenFile(FIRMWARE_DIRECTORY, IAP_UPDATE_FILE, OpenMode::read);
@@ -2737,12 +2739,13 @@ void RepRap::UpdateFirmware() noexcept
return;
}
+
PrepareToLoadIap();
// Use RAM-based IAP
iapFile->Read(reinterpret_cast<char *>(IAP_IMAGE_START), iapFile->Length());
iapFile->Close();
- StartIap();
+ StartIap(filenameRef);
#endif
}
@@ -2798,7 +2801,7 @@ void RepRap::PrepareToLoadIap() noexcept
#endif
}
-void RepRap::StartIap() noexcept
+void RepRap::StartIap(const StringRef& filenameRef) noexcept
{
// Disable all interrupts, then reallocate the vector table and program entry point to the new IAP binary
// This does essentially what the Atmel AT02333 paper suggests (see 3.2.2 ff)
@@ -2827,7 +2830,9 @@ void RepRap::StartIap() noexcept
#if HAS_MASS_STORAGE
// Newer versions of IAP reserve space above the stack for us to pass the firmware filename
- static const char filename[] = FIRMWARE_DIRECTORY IAP_FIRMWARE_FILE;
+ String<MaxFilenameLength> firmwareFileLocation;
+ MassStorage::CombineName(firmwareFileLocation.GetRef(), FIRMWARE_DIRECTORY, filenameRef.IsEmpty() ? IAP_FIRMWARE_FILE : filenameRef.c_str());
+ const char* filename = firmwareFileLocation.c_str();
const uint32_t topOfStack = *reinterpret_cast<uint32_t *>(IAP_IMAGE_START);
if (topOfStack + sizeof(filename) <=
# if SAME5x
@@ -2839,7 +2844,7 @@ void RepRap::StartIap() noexcept
# endif
)
{
- memcpy(reinterpret_cast<char*>(topOfStack), filename, sizeof(filename));
+ strcpy(reinterpret_cast<char*>(topOfStack), filename);
}
#endif
diff --git a/src/RepRap.h b/src/RepRap.h
index 77ca2b36..029fac95 100644
--- a/src/RepRap.h
+++ b/src/RepRap.h
@@ -168,10 +168,10 @@ public:
bool IsProcessingConfig() const noexcept { return processingConfig; }
// Firmware update operations
- bool CheckFirmwareUpdatePrerequisites(const StringRef& reply) noexcept;
- void UpdateFirmware() noexcept;
+ bool CheckFirmwareUpdatePrerequisites(const StringRef& reply, const StringRef& filenameRef) noexcept;
+ void UpdateFirmware(const StringRef& filenameRef) noexcept;
void PrepareToLoadIap() noexcept;
- [[noreturn]] void StartIap() noexcept;
+ [[noreturn]] void StartIap(const StringRef& filenameRef) noexcept;
void ReportInternalError(const char *file, const char *func, int line) const noexcept; // report an internal error
diff --git a/src/bossa/Flasher.cpp b/src/bossa/Flasher.cpp
index 011849b9..976906a0 100644
--- a/src/bossa/Flasher.cpp
+++ b/src/bossa/Flasher.cpp
@@ -44,7 +44,7 @@ void Flasher::erase(uint32_t foffset) THROWS(GCodeException)
_flash->eraseAuto(false);
}
-bool Flasher::write(const char* filename, uint32_t& foffset) THROWS(GCodeException)
+bool Flasher::write(const char* filename, const char* dir, uint32_t& foffset) THROWS(GCodeException)
{
uint32_t pageSize = _flash->pageSize();
uint32_t numPages;
@@ -54,7 +54,7 @@ bool Flasher::write(const char* filename, uint32_t& foffset) THROWS(GCodeExcepti
{
pageNum = 0;
Platform& platform = reprap.GetPlatform();
- infile = MassStorage::OpenFile(filename, OpenMode::read, 0);
+ infile = platform.OpenFile(dir, filename, OpenMode::read);
if (infile == nullptr)
{
platform.MessageF(ErrorMessage, "Failed to open file %s\n", filename);
@@ -111,7 +111,7 @@ bool Flasher::write(const char* filename, uint32_t& foffset) THROWS(GCodeExcepti
return true;
}
-bool Flasher::verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t& foffset) THROWS(GCodeException)
+bool Flasher::verify(const char* filename, const char* dir, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t& foffset) THROWS(GCodeException)
{
uint32_t pageSize = _flash->pageSize();
uint8_t bufferA[pageSize];
@@ -134,7 +134,7 @@ bool Flasher::verify(const char* filename, uint32_t& pageErrors, uint32_t& total
// Note that we can skip all checks for file validity here since
// we would not get here from write() if any of these failed
- infile = MassStorage::OpenFile(filename, OpenMode::read, 0);
+ infile = reprap.GetPlatform().OpenFile(dir, filename, OpenMode::read);
}
try
diff --git a/src/bossa/Flasher.h b/src/bossa/Flasher.h
index f3421883..e0d365bb 100644
--- a/src/bossa/Flasher.h
+++ b/src/bossa/Flasher.h
@@ -58,8 +58,8 @@ public:
virtual ~Flasher() {}
void erase(uint32_t foffset) THROWS(GCodeException);
- bool write(const char* filename, uint32_t& foffset) THROWS(GCodeException);
- bool verify(const char* filename, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t& foffset) THROWS(GCodeException);
+ bool write(const char* filename, const char* dir, uint32_t& foffset) THROWS(GCodeException);
+ bool verify(const char* filename, const char* dir, uint32_t& pageErrors, uint32_t& totalErrors, uint32_t& foffset) THROWS(GCodeException);
void lock(/* std::string& regionArg, */ bool enable) THROWS(GCodeException);
private: