diff --git a/src/Configuration.h b/src/Configuration.h index 79287ad..95762cc 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -30,7 +30,7 @@ Licence: GPL #endif #ifndef VERSION -#define VERSION "1.11" +#define VERSION "1.11d" #endif #ifndef DATE @@ -174,7 +174,12 @@ const float FILAMENT_WIDTH = 1.75; // Millimetres #define EOF_STRING "" +#ifdef DUET_NG +#define IAP_UPDATE_FILE "iap4e.bin" +#else #define IAP_UPDATE_FILE "iap.bin" +#endif + #define IAP_FIRMWARE_FILE "RepRapFirmware.bin" // List defaults diff --git a/src/Platform.cpp b/src/Platform.cpp index 828b586..a103cea 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -723,15 +723,26 @@ void Platform::UpdateFirmware() // Step 1 - Write update binary to Flash and overwrite the remaining space with zeros // Leave the last 1KB of Flash memory untouched, so we can reuse the NvData after this update + #if !defined(IFLASH_PAGE_SIZE) && defined(IFLASH0_PAGE_SIZE) # define IFLASH_PAGE_SIZE IFLASH0_PAGE_SIZE #endif - char data[IFLASH_PAGE_SIZE]; - int bytesRead; - for(uint32_t flashAddr = IAP_FLASH_START; flashAddr < IAP_FLASH_END; flashAddr += IFLASH_PAGE_SIZE) + // Use a 32-bit aligned buffer. This gives us the option of calling the EFC functions directly in future. + uint32_t data32[IFLASH_PAGE_SIZE/4]; + char* const data = reinterpret_cast(data32); + +#if (SAM4S || SAM4E) + // The EWP command is not supported for non-8KByte sectors in the SAM4 series. + // So unlock and erase the complete 64Kb sector first. + // TODO save the NVRAM area and restore it later + + flash_unlock(IAP_FLASH_START, IAP_FLASH_END, nullptr, nullptr); + flash_erase_sector(IAP_FLASH_START); + + for (uint32_t flashAddr = IAP_FLASH_START; flashAddr < IAP_FLASH_END; flashAddr += IFLASH_PAGE_SIZE) { - bytesRead = iapFile->Read(data, IFLASH_PAGE_SIZE); + const int bytesRead = iapFile->Read(data, IFLASH_PAGE_SIZE); if (bytesRead > 0) { @@ -743,28 +754,82 @@ void Platform::UpdateFirmware() // Write one page at a time cpu_irq_disable(); - flash_unlock(flashAddr, flashAddr + IFLASH_PAGE_SIZE - 1, nullptr, nullptr); - flash_write(flashAddr, data, IFLASH_PAGE_SIZE, 1); - flash_lock(flashAddr, flashAddr + IFLASH_PAGE_SIZE - 1, nullptr, nullptr); + const uint32_t rc = flash_write(flashAddr, data, IFLASH_PAGE_SIZE, 0); cpu_irq_enable(); + if (rc != FLASH_RC_OK) + { + MessageF(GENERIC_MESSAGE, "Error: Flash write failed, code=%u, address=0x%08x\n", rc, flashAddr); + return; + } // Verify written data if (memcmp(reinterpret_cast(flashAddr), data, bytesRead) != 0) { - Message(GENERIC_MESSAGE, "Error: Verify during Flash write failed!\n"); + MessageF(GENERIC_MESSAGE, "Error: Verify during flash write failed, address=0x%08x\n", flashAddr); return; } } else { - // Empty write buffer so we can use it to fill up the remaining space + // Fill up the remaining space with zeros + memset(data, 0, sizeof(data[0]) * sizeof(data)); + cpu_irq_disable(); + flash_write(flashAddr, data, IFLASH_PAGE_SIZE, 0); + cpu_irq_enable(); + } + } + + // Re-lock the whole area + flash_lock(IAP_FLASH_START, IAP_FLASH_END, nullptr, nullptr); + +#else // SAM3X code + + for (uint32_t flashAddr = IAP_FLASH_START; flashAddr < IAP_FLASH_END; flashAddr += IFLASH_PAGE_SIZE) + { + const int bytesRead = iapFile->Read(data, IFLASH_PAGE_SIZE); + + if (bytesRead > 0) + { + // Do we have to fill up the remaining buffer with zeros? if (bytesRead != IFLASH_PAGE_SIZE) { - memset(data, 0, sizeof(data[0]) * sizeof(data)); - bytesRead = IFLASH_PAGE_SIZE; + memset(data + bytesRead, 0, sizeof(data[0]) * (IFLASH_PAGE_SIZE - bytesRead)); } + // Write one page at a time + cpu_irq_disable(); + + const char* op = "unlock"; + uint32_t rc = flash_unlock(flashAddr, flashAddr + IFLASH_PAGE_SIZE - 1, nullptr, nullptr); + + if (rc == FLASH_RC_OK) + { + op = "write"; + rc = flash_write(flashAddr, data, IFLASH_PAGE_SIZE, 1); + } + if (rc == FLASH_RC_OK) + { + op = "lock"; + rc = flash_lock(flashAddr, flashAddr + IFLASH_PAGE_SIZE - 1, nullptr, nullptr); + } + cpu_irq_enable(); + + if (rc != FLASH_RC_OK) + { + MessageF(GENERIC_MESSAGE, "Error: Flash %s failed, code=%u, address=0x%08x\n", op, rc, flashAddr); + return; + } + // Verify written data + if (memcmp(reinterpret_cast(flashAddr), data, bytesRead) != 0) + { + MessageF(GENERIC_MESSAGE, "Error: Verify during flash write failed, address=0x%08x\n", flashAddr); + return; + } + } + else + { // Fill up the remaining space + memset(data, 0, sizeof(data[0]) * sizeof(data)); cpu_irq_disable(); flash_unlock(flashAddr, flashAddr + IFLASH_PAGE_SIZE - 1, nullptr, nullptr); flash_write(flashAddr, data, IFLASH_PAGE_SIZE, 1); @@ -772,6 +837,8 @@ void Platform::UpdateFirmware() cpu_irq_enable(); } } +#endif + iapFile->Close(); // Step 2 - Let the firmware do whatever is necessary before we exit this program