diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index 16959703a..d3466eb5a 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -728,63 +728,6 @@ void beginBoard() } // Initialize the allocate and forget PSRAM buffers -void beginBuffers() -{ - // Display the memory use before buffer allocation - if (settings.debugMalloc) - reportHeapNow(true); - - // Only allocate these buffers from PSRAM - if ((settings.enablePsram == false) || (ESP.getPsramSize() == 0)) - { - systemPrintf("WARNING: PSRAM not available, delaying buffer allocation!\r\n"); - systemPrintf("settings.enablePsram: %s\r\n", settings.enablePsram ? "true" : "false"); - if (settings.debugMalloc == false) - reportHeapNow(true); - return; - } - - // Walk the list of buffers - for (int index = 0; index < dfuBufferInfoCount; index++) - { - uint8_t * address; - size_t length; - - // Determine if this buffer will get used - if (dfuBufferInfo[index]._present && (*dfuBufferInfo[index]._present == false)) - // Never used - continue; - - // Determine if this buffer will be in PSRAM - length = dfuBufferInfo[index]._sizeInBytes; - dfuBufferInfo[index]._bufferData->_length = length; - if (length < settings.psramMallocLevel) - { - // No, allocation comes from RAM - systemPrintf("WARNING: Delaying allocation of %s from RAM\r\n", - dfuBufferInfo[index]._description); - systemPrintf("%s: %d bytes < %d bytes for PSRAM allocation\r\n", - dfuBufferInfo[index]._description, length, settings.psramMallocLevel); - continue; - } - - // Allocate the buffer - address = (uint8_t *)rtkMalloc(length, dfuBufferInfo[index]._description); - dfuBufferInfo[index]._bufferData->_address = address; - if (address == nullptr) - { - systemPrintf("WARNING: PSRAM low, delay allocation for %s, %d bytes\r\n", - dfuBufferInfo[index]._description, length); - if (settings.debugMalloc == false) - reportHeapNow(true); - } - } - - // Display the memory use after buffer allocation - if (settings.debugMalloc) - reportHeapNow(true); -} - void beginVersion() { espFirmwareVersionGet(deviceFirmware, sizeof(deviceFirmware), false); diff --git a/Firmware/RTK_Everywhere/Device_Firmware_Update.ino b/Firmware/RTK_Everywhere/Device_Firmware_Update.ino deleted file mode 100644 index d4923f213..000000000 --- a/Firmware/RTK_Everywhere/Device_Firmware_Update.ino +++ /dev/null @@ -1,1871 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Firmware_Update.ino - - Generic support routines to program firmware devices -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifdef COMPILE_MENU_FIRMWARE - -#ifdef COMPILE_NETWORK - -//---------------------------------------- -// Constants -//---------------------------------------- - -const char * dfuStateName[] = -{ - "DFUS_DONE", - "DFUS_INIT", - "DFUS_WAIT_NETWORK", - "DFUS_GET_DEVICE", - "DFUS_GET_NETWORK_FILES", - "DFUS_GET_HTTP_FILE_LIST_REQ", - "DFUS_GET_NETWORK_FILE_LIST", - "DFUS_GET_NVM_FILE_LIST", - "DFUS_GET_SD_FILE_LIST", - "DFUS_SELECT_FILE", - "DFUS_SELECT_ACTION", - "DFUS_CRC_OPEN_INPUT", - "DFUS_CRC_READ_DATA", - "DFUS_CRC_CLOSE", - "DFUS_DEVICE_OPEN_INPUT", - "DFUS_DEVICE_FILL_BUFFER", - "DFUS_DEVICE_RESET", - "DFUS_DEVICE_OPEN_OUTPUT", - "DFUS_DEVICE_PROGRAM_FIRMWARE", - "DFUS_READ_FIRMWARE_DATA", - "DFUS_DEVICE_CLOSE", - "DFUS_NEXT_DEVICE", - "DFUS_REBOOT", -}; -const int dfuStateNameCount = sizeof(dfuStateName) / sizeof(dfuStateName[0]); - -#define DFU_USER_INPUT_STRING 0 -#define DFU_USER_INPUT_NOT_DONE -1 -#define DFU_USER_INPUT_EXIT -2 -#define DFU_USER_INPUT_TIMEOUT -3 -#define DFU_USER_INPUT_OVERFLOWS_BUFFER -4 -#define DFU_USER_INPUT_NOT_A_NUMBER -5 - -const char * dfuEqualSigns = "=================================================="; - -//---------------------------------------- -// Locals -//---------------------------------------- - -static bool dfuLoopInUpdate; // Loop in deviceFirmwareUpdate while set - -//---------------------------------------- -// Display the action menu -//---------------------------------------- -void deviceFirmwareActionMenu(DEVICE_FIRMWARE_CTX * ctx) -{ - if (ctx->_doAll == false) - { -// inMainMenu = true; - systemPrintf("\r\nAction:\r\n"); - - // Display the menu - if ((ctx->_inputDeviceType == DFU_IDT_NVM) || (ctx->_inputDeviceType == DFU_IDT_SD)) - systemPrintf("d) Delete the file\r\n"); - if (ctx->_deviceInfo->_useNvm && (ctx->_inputDeviceType != DFU_IDT_NVM)) - systemPrintf("n) Copy file to NVM\r\n"); - if (present.microSd && (ctx->_inputDeviceType != DFU_IDT_SD)) - systemPrintf("s) Copy file to SD card\r\n"); - systemPrintf("u) Update device firmware\r\n"); - systemPrintf("x) Exit\r\n"); - - // Discard the input - serialInputClear(&Serial); - - // Output the prompt - systemPrintf("Select an action: "); - - // Start the menu timeout timer - deviceFirmwareTimerStart(ctx); - } -} - -//---------------------------------------- -// Allocate the buffers -//---------------------------------------- -bool deviceFirmwareBufferAllocate(DEVICE_FIRMWARE_CTX * ctx) -{ - // Determine which buffers need to be dynamically allocated - if (settings.debugFirmwareUpdate) - systemPrintf("Allocating %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareData)]._description); - ctx->_dynamicAllocationFd = bufferDynamicallyAllocate(&dfuFirmwareData); - deviceFirmwareBufferRestore(ctx, nullptr); - - if (settings.debugFirmwareUpdate) - systemPrintf("Allocating %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareFileNamesNet)]._description); - ctx->_dynamicAllocationNet = bufferDynamicallyAllocate(&dfuFirmwareFileNamesNet); - if (ctx->_doAll == false) - { - if (settings.debugFirmwareUpdate) - systemPrintf("Allocating %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareFileNamesNvm)]._description); - ctx->_dynamicAllocationNvm = bufferDynamicallyAllocate(&dfuFirmwareFileNamesNvm); - - ctx->_dynamicAllocationSd = false; - if (present.microSd) - { - if (settings.debugFirmwareUpdate) - systemPrintf("Allocating %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareFileNamesSd)]._description); - ctx->_dynamicAllocationSd = bufferDynamicallyAllocate(&dfuFirmwareFileNamesSd); - } - } - - // Return buffer allocation status - return (dfuFirmwareData._address - && dfuFirmwareFileNamesNet._address - && ((ctx->_doAll == true) - || (dfuFirmwareFileNamesNvm._address - && ((present.microSd == false) - || dfuFirmwareFileNamesSd._address) - ) - ) - ); -} - -//---------------------------------------- -// Empty the buffers and remove the name and sort extensions -//---------------------------------------- -void deviceFirmwareBufferEmpty(DEVICE_FIRMWARE_CTX * ctx) -{ - for (int index = 0; index < dfuBufferInfoCount; index++) - { - bufferNameSortFree(index); - dfuBufferInfo[index]._bufferData->_offset = 0; - } -} - -//---------------------------------------- -// Free the buffers -//---------------------------------------- -void deviceFirmwareBufferFree(DEVICE_FIRMWARE_CTX * ctx, bool freeDataBuffer) -{ - if (ctx->_doAll == false) - { - // Release the SD card file name buffer - if (settings.debugFirmwareUpdate) - systemPrintf("Freeing %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareFileNamesSd)]._description); - bufferNameSortFree(bufferGetIndex(&dfuFirmwareFileNamesSd)); - ctx->_dynamicAllocationSd = false; - - // Release the NVM file name buffer - if (settings.debugFirmwareUpdate) - systemPrintf("Freeing %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareFileNamesNvm)]._description); - bufferNameSortFree(bufferGetIndex(&dfuFirmwareFileNamesNvm)); - ctx->_dynamicAllocationNvm = false; - } - - // Release the network file name buffer - if (settings.debugFirmwareUpdate) - systemPrintf("Freeing %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareFileNamesNet)]._description); - bufferNameSortFree(bufferGetIndex(&dfuFirmwareFileNamesNet)); - ctx->_dynamicAllocationNet = false; - - // Release the firmware data buffer - if (freeDataBuffer) - { - if (settings.debugFirmwareUpdate) - systemPrintf("Freeing %s\r\n", dfuBufferInfo[bufferGetIndex(&dfuFirmwareData)]._description); - bufferNameSortFree(bufferGetIndex(&dfuFirmwareData)); - ctx->_dynamicAllocationFd = false; - } -} - -//---------------------------------------- -// Restore the data buffer -//---------------------------------------- -void deviceFirmwareBufferRestore(DEVICE_FIRMWARE_CTX * ctx, - DFU_BUFFER_DATA * bufferData) -{ - // Update the offset value - if (bufferData) - bufferData->_offset = ctx->_validDataBytes; - - // Restore the context to point at the data buffer - if (dfuFirmwareData._address) - { - ctx->_buffer = dfuFirmwareData._address; - ctx->_bufferLength = dfuFirmwareData._length; - } - else - { - ctx->_buffer = nullptr; - ctx->_bufferLength = 0; - } -} - -//---------------------------------------- -// Cleanup after performing the device firmware update -//---------------------------------------- -void deviceFirmwareCleanup(DEVICE_FIRMWARE_CTX * ctx) -{ - if (ctx == nullptr) - return; - - // Done with the network - if (ctx->_networkConfigured) - { - systemPrintf("Removing NETCONSUMER_DEVICE_OTA\r\n"); - networkConsumerRemove(NETCONSUMER_DEVICE_OTA, NETWORK_ANY, __FILE__, __LINE__); - } - - // Done with the save data buffer - if (ctx->_saveData) - { - if (settings.debugFirmwareUpdate) - systemPrintf("Freeing ctx->_saveData, %d bytes\r\n", ctx->_saveDataLength); - rtkFree(ctx->_saveData, "DFU: ctx->_saveData"); - } - - // Done with the context - if (settings.debugFirmwareUpdate) - systemPrintf("Freeing device firmware update context, %d bytes\r\n", sizeof(*ctx)); - rtkFree(ctx, "Device firmware context"); - dfuContext = nullptr; -// inMainMenu = false; -} - -//---------------------------------------- -// Close the files -//---------------------------------------- -void deviceFirmwareClose(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - // Display the CRC - if (ctx->_complete) - systemPrintf("CRC: 0x%08x\r\n", ctx->_crc); - - // Display complete - systemPrintf("%s\r\n", dfuEqualSigns); - systemPrintf("%s %s %s!\r\n", ctx->_deviceInfo->_deviceName, - (ctx->_outputDeviceType == DFU_ODT_DEVICE) ? - "firmware update" : "file copy", - (ctx->_bytesWritten == ctx->_fileBytes) ? - "complete" : "failed"); - systemPrintf("%s\r\n", dfuEqualSigns); - - // Close the output file - deviceFirmwareCloseOutput(ctx); - - // Close the input file - deviceFirmwareCloseInput(ctx); - - // Determine if all firmware was written - dfuLoopInUpdate = false; - if (ctx->_doAll) - { - if (ctx->_complete == false) - ctx->_reboot = false; - deviceFirmwareFileListReload(ctx); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - } - else - { - if ((ctx->_outputDeviceType == DFU_ODT_NVM) - || (ctx->_outputDeviceType == DFU_ODT_SD)) - { - // File copy - deviceFirmwareFileListReload(ctx); - } - - // Programming a device - else - deviceFirmwareStateSet(ctx, ctx->_reboot ? DFUS_REBOOT : DFUS_NEXT_DEVICE); - } -} - -//---------------------------------------- -// Close the input file -//---------------------------------------- -void deviceFirmwareCloseInput(DEVICE_FIRMWARE_CTX * ctx) -{ - // Close the input file - if (ctx->_inputDeviceType == DFU_IDT_NETWORK) - dfuNetworkCleanup(ctx, nullptr); - else if (ctx->_inputDeviceType == DFU_IDT_NVM) - dfuNvmClose(ctx); - else if (ctx->_inputDeviceType == DFU_IDT_SD) - dfuSdClose(ctx); - - // Display the statistics - if (ctx->_complete) - deviceFirmwarePerformUpdate(ctx); -} - -//---------------------------------------- -// Close the output file or device -//---------------------------------------- -void deviceFirmwareCloseOutput(DEVICE_FIRMWARE_CTX * ctx) -{ - // Close the output file - if (ctx->_outputDeviceType == DFU_ODT_DEVICE) - { - // Finish the firmware update - if (ctx->_deviceInfo->_close) - { - if (settings.debugFirmwareUpdate && ctx->_complete) - systemPrintf("Done with the %s firmware update\r\n", - ctx->_deviceInfo->_deviceName); - ctx->_deviceInfo->_close(ctx); - } - else if (settings.debugFirmwareUpdate) - systemPrintf("NOT IMPLEMENTED: %s firmware update close routine!\r\n", - ctx->_deviceInfo->_deviceName); - } - else if (ctx->_outputDeviceType == DFU_ODT_NVM) - dfuNvmClose(ctx); - else if (ctx->_outputDeviceType == DFU_ODT_SD) - dfuSdClose(ctx); -} - -//---------------------------------------- -// Close the firmware file -//---------------------------------------- -void deviceFirmwareCrcClose(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - deviceFirmwareCloseInput(ctx); - if (ctx->_bytesRead == ctx->_fileBytes) - { - // Display the statistics - deviceFirmwarePerformUpdate(ctx); - systemPrintf("CRC: 0x%08x\r\n", ctx->_crc); - ctx->_crcSave = ctx->_crc; - deviceFirmwareStateSet(ctx, DFUS_DEVICE_OPEN_INPUT); - } - else - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - ctx->_crc = 0; -} - -//---------------------------------------- -// Open the firmware file and output device -//---------------------------------------- -void deviceFirmwareCrcOpen(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - // Give user a hint as to what is taking so long - if (settings.debugFirmwareUpdate) - { - if (ctx->_inputDeviceType == DFU_IDT_NETWORK) - systemPrintf("Opening URL: %s\r\n", ctx->_url.c_str()); - else - systemPrintf("Opening firmware file: %s\r\n", ctx->_fileName.c_str()); - } - systemPrintf("Computing %s firmware CRC\r\n", ctx->_deviceInfo->_deviceName); - if (deviceFirmwareOpenInput(ctx, currentMsec)) - deviceFirmwareStateSet(ctx, DFUS_CRC_READ_DATA); - else - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); -} - -//---------------------------------------- -// Read some firmware data -//---------------------------------------- -void deviceFirmwareCrcReadData(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - if (deviceFirmwareRead(ctx, currentMsec, DFUS_CRC_CLOSE)) - { - // Compute the CRC across these bytes - ctx->_crc = crc32Compute(ctx->_crc, ctx->_buffer, ctx->_validDataBytes); - - // Empty the buffer - ctx->_validDataBytes = 0; - - // Wait until done - if (ctx->_bytesRead == ctx->_fileBytes) - deviceFirmwareStateSet(ctx, DFUS_CRC_CLOSE); - } -} - -//---------------------------------------- -// Determine if the device is available for firmware updates -//---------------------------------------- -bool deviceFirmwareDeviceAvailable(int deviceIndex) -{ - bool deviceAvailable; - const DEVICE_FIRMWARE_INFO * deviceInfo; - bool * devicePresent; - - do - { - deviceAvailable = false; - deviceInfo = &deviceFirmwareInfo[deviceIndex]; - - // Check if this device is in the system - devicePresent = deviceInfo->_present; - if (devicePresent && (*devicePresent == false)) - // Not in the system - break; - - // We cannot do ESP32 OTA if there is only one partition - if ((strcmp("ESP32", deviceInfo->_deviceName) == 0) - && (dfuEsp32AreFirmwareWritesSupported() == false)) - break; - deviceAvailable = true; - } while (0); - return deviceAvailable; -} - -//---------------------------------------- -// Display the device menu -//---------------------------------------- -void deviceFirmwareDeviceListMenu(DEVICE_FIRMWARE_CTX * ctx) -{ - if (ctx->_doAll == false) - { -// inMainMenu = true; - systemPrintf("\r\nDevice List:\r\n"); - - // Walk the list of devices - for (int index = 0; index < deviceFirmwareInfoCount; index++) - { - // Check if this device is in the system - if (deviceFirmwareDeviceAvailable(index) == false) - continue; - - // Display the device - systemPrintf("%c) %s\r\n", '0' + index, deviceFirmwareInfo[index]._deviceName); - } - - systemPrintf("x) Exit\r\n"); - - // Discard the input - serialInputClear(&Serial); - ctx->_buffer[0] = 0; - ctx->_validDataBytes = 0; - - // Output the prompt - systemPrintf("Select a device: "); - - // Start the menu timeout timer - deviceFirmwareTimerStart(ctx); - } -} - -//---------------------------------------- -// List the files -//---------------------------------------- -void deviceFirmwareFileList(int bufferIndex, - int fileCount, - const char * prefix, - int offset) -{ - DFU_BUFFER_DATA * bufferData = dfuBufferInfo[bufferIndex]._bufferData; - char ** nameArray = bufferData->_nameArray; - int * sortArray = bufferData->_sortArray; - - // List the files - if (nameArray && sortArray) - for (int index = 0; index < fileCount; index++) - systemPrintf("%d) %s:/%s\r\n", offset + index, prefix, nameArray[sortArray[index]]); -} - -//---------------------------------------- -// Display the file list menu -//---------------------------------------- -void deviceFirmwareFileListMenu(DEVICE_FIRMWARE_CTX * ctx) -{ - int offset; - - if (ctx->_doAll == false) - { -// inMainMenu = true; - - // Display the firmware version - if (ctx->_deviceInfo->_version) - systemPrintf("\r\nCurrent firmware version: %s\r\n", ctx->_deviceInfo->_version(ctx).c_str()); - - // Display the files - offset = 0; - systemPrintf("\r\nFile List:\r\n"); - deviceFirmwareFileList(bufferGetIndex(&dfuFirmwareFileNamesNet), - ctx->_fileCountNet, - deviceFirmwareGetDevicePrefix(DFU_IDT_NETWORK), - offset); - offset += ctx->_fileCountNet; - deviceFirmwareFileList(bufferGetIndex(&dfuFirmwareFileNamesNvm), - ctx->_fileCountNvm, - deviceFirmwareGetDevicePrefix(DFU_IDT_NVM), - offset); - offset += ctx->_fileCountNvm; - deviceFirmwareFileList(bufferGetIndex(&dfuFirmwareFileNamesSd), - ctx->_fileCountSd, - deviceFirmwareGetDevicePrefix(DFU_IDT_SD), - offset); - - systemPrintf("x) Exit\r\n"); - - // Discard the input - serialInputClear(&Serial); - ctx->_buffer[0] = 0; - ctx->_validDataBytes = 0; - - // Output the prompt - systemPrintf("Select file: "); - - // Start the menu timeout timer - deviceFirmwareTimerStart(ctx); - } -} - -//---------------------------------------- -// Prepare to get the file list again -//---------------------------------------- -void deviceFirmwareFileListReload(DEVICE_FIRMWARE_CTX * ctx) -{ - // Prepare the buffers for listing the files again - deviceFirmwareBufferEmpty(ctx); - - // No files available yet - ctx->_fileCountNet = 0; - ctx->_fileCountNvm = 0; - ctx->_fileCountSd = 0; - ctx->_fileCount = 0; - - // Input device and output device have not been chosen yet - ctx->_inputDeviceType = DFU_IDT_NONE; - ctx->_outputDeviceType = DFU_ODT_NONE; - - // Display the file list again - if (ctx->_doAll) - systemPrintf("Getting the file list...\r\n"); - deviceFirmwareStateSet(ctx, ctx->_networkConfigured ? DFUS_GET_NETWORK_FILES - : DFUS_GET_NVM_FILE_LIST); -} - -//---------------------------------------- -// Sort the list of firmware files -//---------------------------------------- -void deviceFirmwareFileSort(int bufferIndex, int fileCount) -{ - DFU_BUFFER_DATA * bufferData = dfuBufferInfo[bufferIndex]._bufferData; - char ** nameArray = bufferData->_nameArray; - int * sortArray = bufferData->_sortArray; - - // Bubble sort the file names newest to oldest - for (int i = 0; i < (fileCount - 1); i++) - for (int j = i + 1; j < fileCount; j++) - // Determine if the entries should be switched - if (strcmp(nameArray[sortArray[i]], nameArray[sortArray[j]]) < 0) - { - // Switch the entries - int temp = sortArray[i]; - sortArray[i] = sortArray[j]; - sortArray[j] = temp; - } -} - -//---------------------------------------- -// Get the input device prefix -//---------------------------------------- -const char * deviceFirmwareGetDevicePrefix(int inputDeviceType) -{ - if (inputDeviceType == DFU_IDT_NETWORK) - return "NET"; - if (inputDeviceType == DFU_IDT_NVM) - return "NVM"; - if (inputDeviceType == DFU_IDT_SD) - return "SD"; - return "NONE"; -} - -//---------------------------------------- -// Get a number from the user -//---------------------------------------- -int deviceFirmwareGetNumber(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int value; - - // Get the user input - value = deviceFirmwareGetUserInput(ctx, currentMsec); - if (value == DFU_USER_INPUT_STRING) - { - // Determine if a number was input - if ((sscanf((char *)ctx->_buffer, "0x%x", &value) == 1) - || (sscanf((char *)ctx->_buffer, "0X%x", &value) == 1) - || (sscanf((char *)ctx->_buffer, "%d", &value) == 1)) - { - return value; - } - - // Return the input error - value = DFU_USER_INPUT_NOT_A_NUMBER; - } - - return value; -} - -//---------------------------------------- -// Get a value from the user -//---------------------------------------- -int deviceFirmwareGetUserInput(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - uint8_t incoming; - int value; - - // Handle the menu timeout - ctx = dfuContext; - if ((currentMsec - ctx->_timerMsec) >= (menuTimeout * MILLISECONDS_IN_A_SECOND)) - { - systemPrintf("\r\nUser input timeout\r\n"); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - return DFU_USER_INPUT_TIMEOUT; - } - - // Get the user selection - if (Serial.available()) - { - // Get an input character - incoming = Serial.read(); - - // All done at the end of the line - if ((incoming == '\r') || (incoming == '\n')) - { - systemPrintln(); - return DFU_USER_INPUT_STRING; - } - - // Handle the backspace - if (incoming == '\b') - { - if (ctx->_validDataBytes) - { - systemPrintf("\b \b"); - ctx->_validDataBytes -= 1; - ctx->_buffer[ctx->_validDataBytes] = 0; - } - else - // Output the bell character - systemPrintf("%c", (char)0x07); - return DFU_USER_INPUT_NOT_DONE; - } - - // Echo the input - else - systemPrintf("%c", incoming); - - // Handle the error cases - if ((ctx->_validDataBytes == 0) && (incoming == 'x')) - { - systemPrintln(); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - return DFU_USER_INPUT_EXIT; - } - - // Save the input - ctx->_buffer[ctx->_validDataBytes++] = incoming; - ctx->_buffer[ctx->_validDataBytes] = 0; - - // Check for buffer overflow - if (ctx->_validDataBytes >= (ctx->_bufferLength - 1)) - { - systemPrintf("\r\nBuffer overflow\r\n"); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - return DFU_USER_INPUT_OVERFLOWS_BUFFER; - } - } - return DFU_USER_INPUT_NOT_DONE; -} - -//---------------------------------------- -// Initialize the firmware update -//---------------------------------------- -void deviceFirmwareInit(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int nextState; - - do - { - nextState = DFUS_NEXT_DEVICE; - - // Allocate the buffers - if (deviceFirmwareBufferAllocate(ctx) == false) - break; - - // Determine if the network is online - ctx->_networkConfigured = (present.ethernet_ws5500 || wifiStationIsSsidSet()); - if ((present.microSd == false) && (ctx->_networkConfigured == false)) - { - systemPrintf("Network not configured!\r\n"); - nextState = DFUS_GET_DEVICE; - break; - } - - // Request the network - systemPrintf("Adding NETCONSUMER_DEVICE_OTA\r\n"); - networkConsumerAdd(NETCONSUMER_DEVICE_OTA, NETWORK_ANY, __FILE__, __LINE__); - systemPrintf("Waiting for network\r\n"); - deviceFirmwareTimerStart(ctx); - nextState = DFUS_WAIT_NETWORK; - } while (0); - deviceFirmwareStateSet(ctx, nextState); -} - -//---------------------------------------- -// Blink a LED to indicate activity -//---------------------------------------- -void deviceFirmwareLedBlink(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - if ((currentMsec - ctx->_lastBlinkMsec) >= (MILLISECONDS_IN_A_SECOND / 4)) - { - ctx->_lastBlinkMsec = currentMsec; - - // Toggle LED to indicate activity - bluetoothLedBlink(); - } -} - -//---------------------------------------- -// Cleanup after the current firmware update and prepare for the next one -//---------------------------------------- -void deviceFirmwareNextDevice(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - // Done with the web server - if (ctx->_https) - { - ctx->_networkClient; - ctx->_https->end(); - delete ctx->_https; - ctx->_https = nullptr; - } - - // Free the buffers - deviceFirmwareBufferFree(ctx, false); - - // Free the write buffer - if (ctx->_writeBuffer) - { - rtkFree(ctx->_writeBuffer, "Firmware update write buffer"); - ctx->_writeBuffer = nullptr; - } - - // Free the device specific context - if (ctx->_devCtx) - { - rtkFree(ctx->_devCtx, "Device specific firmware update context"); - ctx->_devCtx = nullptr; - } - - // Handle the next device - deviceFirmwareStateSet(ctx, ctx->_doAll ? DFUS_GET_DEVICE : - (ctx->_reboot ? DFUS_REBOOT : DFUS_DONE)); -} - -//---------------------------------------- -// Open the firmware file -//---------------------------------------- -void deviceFirmwareOpenFirmwareFile(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - const char * devicePrefix; - - // Get the file device - devicePrefix = deviceFirmwareGetDevicePrefix(ctx->_inputDeviceType); - - // Give user a hint as to what is taking so long - systemPrintf("Opening %s firmware file %s:%s\r\n", - ctx->_deviceInfo->_deviceName, - devicePrefix, - ctx->_fileName.c_str()); - if (deviceFirmwareOpenInput(ctx, currentMsec)) - { - if (settings.debugFirmwareUpdate) - systemPrintf("%d bytes\r\n", ctx->_fileBytes); - deviceFirmwareReduceBufferSize(ctx); - deviceFirmwareStateSet(ctx, DFUS_DEVICE_FILL_BUFFER); - } - else - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); -} - -//---------------------------------------- -// Open the input device -//---------------------------------------- -bool deviceFirmwareOpenInput(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - // Verify that the output was specified - if (ctx->_outputDeviceType == DFU_ODT_NONE) - reportFatalError("Output device type is DFU_ODT_NONE!"); - - ctx->_bytesRead = 0; - ctx->_complete = false; - ctx->_startMsec = millis(); - - // Network file read path - // ctx->_http --> ctx->_networkClient --> ctx->_buffer - if (ctx->_inputDeviceType == DFU_IDT_NETWORK) - // Send HTTP GET request - return deviceFirmwareOpenUrl(ctx, currentMsec); - - // NVM file read data path: - // ctx->_nvmFile --> ctx->_buffer - if (ctx->_inputDeviceType == DFU_IDT_NVM) - return dfuNvmOpen(ctx, false); - - // SD file read data path: - // ctx->_sdFile --> ctx->_buffer - if (ctx->_inputDeviceType == DFU_IDT_SD) - return dfuSdOpen(ctx, false); - - // Testing case - return true; -} - -//---------------------------------------- -// Open the output device -//---------------------------------------- -void deviceFirmwareOpenOutput(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - bool result; - - do - { - ctx->_bytesWritten = 0; - ctx->_packetNumber = 0; - result = false; - - // Network write data path - // ctx->_buffer --> ctx->_writeBuffer --> device - if (ctx->_outputDeviceType == DFU_ODT_DEVICE) - { - systemPrintf("Updating %s firmware\r\n", ctx->_deviceInfo->_deviceName); - - // Determine if there is an open routine - if (ctx->_deviceInfo->_open) - { - result = ctx->_deviceInfo->_open(ctx); - if (result) - break; - - // Display the error - systemPrintf("ERROR: %s firmware open failed!\r\n", - ctx->_deviceInfo->_deviceName); - rtkTaskList(&Serial); - } - else - { - if (settings.debugFirmwareUpdate) - systemPrintf("NOT IMPLEMENTED: %s firmware update open routine!\r\n", - ctx->_deviceInfo->_deviceName); - - // Enable testing of new devices - result = true; - } - break; - } - - // NVM write data path - // ctx->_buffer --> ctx->_nvmFile --> NVM - if (ctx->_outputDeviceType == DFU_ODT_NVM) - { - result = dfuNvmOpen(ctx, true); - break; - } - - // SD card write data path - // ctx->_buffer --> ctx->_sdFile --> SD card - if (ctx->_outputDeviceType == DFU_ODT_SD) - { - result = dfuSdOpen(ctx, true); - break; - } - - // testing case - result = true; - } while (0); - - // Set the next state - if (result) - deviceFirmwareStateSet(ctx, DFUS_DEVICE_PROGRAM_FIRMWARE); - else - deviceFirmwareClose(ctx, currentMsec); -} - -//---------------------------------------- -// Open the URL -//---------------------------------------- -bool deviceFirmwareOpenUrl(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int attempt; - int httpResponseCode; - - if (settings.debugFirmwareUpdate) - systemPrintf("URL: %s\r\n", ctx->_url.c_str()); - - // Send HTTP GET request - attempt = 0; - do - { - // Open the connection to the web server - ctx->_startMsec = currentMsec; - ctx->_https = new HTTPClient; - ctx->_https->begin(ctx->_url); - ctx->_https->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - httpResponseCode = ctx->_https->GET(); - if (httpResponseCode == -1) - ctx->_https->end(); - - // Display the error - if ((httpResponseCode != 200) || (settings.debugFirmwareUpdate)) - systemPrintf("HTTP Response code: %d\r\n", httpResponseCode); - } while ((httpResponseCode == -1) && (++attempt < 3)); - - // Handle the responses - if (httpResponseCode != 200) - { - systemPrintf("ERROR: Failed to open url: %s\r\n", ctx->_url.c_str()); - return false; - } - - // Save the file length - ctx->_fileBytes = ctx->_https->getSize(); - if (settings.debugFirmwareUpdate) - systemPrintf("File size: %d bytes\r\n", ctx->_fileBytes); - - // Get TCP stream - ctx->_networkClient = ctx->_https->getStreamPtr(); - return true; -} - -//---------------------------------------- -// Perform the firmware update -//---------------------------------------- -void deviceFirmwarePerformUpdate(DEVICE_FIRMWARE_CTX * ctx) -{ - uint64_t bytesPerSecond; - uint32_t milliseconds; - uint32_t seconds; - uint32_t startMsec; - - // Display the firmware transfer / update rate - milliseconds = millis() - ctx->_startMsec; - if (milliseconds == 0) - milliseconds = 1; - bytesPerSecond = (ctx->_fileBytes * 1000ULL) / (uint64_t)milliseconds; - seconds = milliseconds / MILLISECONDS_IN_A_SECOND; - milliseconds -= seconds * MILLISECONDS_IN_A_SECOND; - systemPrintf("%d firmware bytes in %d.%03d seconds, %d bytes/second\r\n", - ctx->_fileBytes, seconds, milliseconds, - (uint32_t)bytesPerSecond); -} - -//---------------------------------------- -// Read data from the input device -// Returns true when buffer is full -//---------------------------------------- -bool deviceFirmwareRead(DEVICE_FIRMWARE_CTX * ctx, - uint32_t currentMsec, - int readErrorState) -{ - ssize_t bytesRead; - size_t length; - - // Blink the LED - deviceFirmwareLedBlink(ctx, currentMsec); - - // Move remaining data to the beginning of the buffer - if (ctx->_validDataBytes && (ctx->_data != ctx->_buffer)) - memcpy(ctx->_buffer, ctx->_data, ctx->_validDataBytes); - - // Read firmware data from the input device - bytesRead = 0; - length = ctx->_fileBytes - ctx->_bytesRead; - if (length) - { - // Fill the buffer or read the remaining bytes - length = min(length, ctx->_bufferLength - ctx->_validDataBytes); - - // Read firmware data from the input device - ctx->_data = &ctx->_buffer[ctx->_validDataBytes]; - if (ctx->_inputDeviceType == DFU_IDT_NETWORK) - bytesRead = dfuNetworkRead(ctx, ctx->_data, length); - else if (ctx->_inputDeviceType == DFU_IDT_NVM) - bytesRead = dfuNvmRead(ctx, ctx->_data, length); - else - bytesRead = dfuSdRead(ctx, ctx->_data, length); - - // Check for read error - if (bytesRead < 0) - { - // Read failed - systemPrintf("Read failed, closing files\r\n"); - deviceFirmwareStateSet(ctx, readErrorState); - return false; - } - else if (bytesRead) - // Compute the CRC - ctx->_crc = crc32Compute(ctx->_crc, ctx->_data, bytesRead); - } - - // Remaining data starts at the beginning of the buffer - ctx->_data = ctx->_buffer; - if (bytesRead > 0) - { - // Account for the firmware bytes read - ctx->_validDataBytes += bytesRead; - ctx->_bytesRead += bytesRead; - - // Display the number of bytes read - if (settings.debugFirmwareUpdate && ctx->_debugVerbose) - systemPrintf("bytesRead: %d\r\n", bytesRead); - } - - // Done when: - // * Buffer is full - // * Have all remaining bytes - // * All bytes have been read - // * At least one packet/frame can be programmed on the device - if ((ctx->_validDataBytes == ctx->_bufferLength) - || (ctx->_validDataBytes == (ctx->_fileBytes - ctx->_bytesRead)) - || (ctx->_bytesRead == ctx->_fileBytes) - || ((ctx->_outputDeviceType == DFU_ODT_DEVICE) - && (ctx->_validDataBytes >= ctx->_bytesMax))) - { - return true; - } - return false; -} - -//---------------------------------------- -// Fill the read buffer -//---------------------------------------- -void deviceFirmwareReadFillBuffer(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - if (deviceFirmwareRead(ctx, currentMsec, DFUS_DEVICE_CLOSE)) - { - if (ctx->_outputDeviceType == DFU_ODT_DEVICE) - deviceFirmwareStopTasks(ctx); - if (ctx->_doAll == false) - ctx->_reboot = true; - deviceFirmwareStateSet(ctx, DFUS_DEVICE_RESET); - } -} - -//---------------------------------------- -// Read some firmware data -//---------------------------------------- -void deviceFirmwareReadFirmwareData(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - if (deviceFirmwareRead(ctx, currentMsec, DFUS_CRC_CLOSE)) - deviceFirmwareStateSet(ctx, DFUS_DEVICE_PROGRAM_FIRMWARE); -} - -//---------------------------------------- -// Reduce the buffer size when a write routine does not exist -//---------------------------------------- -void deviceFirmwareReduceBufferSize(DEVICE_FIRMWARE_CTX * ctx) -{ - size_t temp; - - if ((ctx->_outputDeviceType == DFU_ODT_DEVICE) - && (ctx->_deviceInfo->_write == nullptr)) - { - systemPrintf("NOT IMPLEMENTED: %s firmware update write routine!\r\n", - ctx->_deviceInfo->_deviceName); - systemPrintf("WARNING: Using dummy %s firmware update write routine!\r\n", - ctx->_deviceInfo->_deviceName); - systemPrintf("Reducing the following values for testing:\r\n"); - size_t temp = ctx->_bufferLength; - ctx->_bufferLength = 4; - systemPrintf("bufferLength: %d --> %d bytes\r\n", temp, ctx->_bufferLength); - - temp = ctx->_fileBytes; - ctx->_fileBytes = min(temp, (size_t)16); - if (temp != ctx->_fileBytes) - systemPrintf("fileBytes: %d --> %d bytes\r\n", temp, ctx->_fileBytes); - - temp = ctx->_bytesMax; - ctx->_bytesMax = min(temp, (size_t)2); - if (temp != ctx->_bytesMax) - systemPrintf("bytesMax: %d --> %d bytes\r\n", temp, ctx->_bytesMax); - } -} - -//---------------------------------------- -// Reset the device before doing the firmware update -// -// file copy firmware update -// | | -// | V -// | .-----------------------. Error -// '-------->| DFUS_DEVICE_RESET |-------------------. -// '-----------------------' | -// | if (DFU_ODT_DEVICE) | -// | true -> loopInUpdate | -// V | -// .-----------------------------. Error | -// | DFUS_DEVICE_OPEN_OUTPUT |------------. | -// '-----------------------------' | | -// | | | -// V | | -// Done .-------------------------------. | | -// .-------| DFUS_DEVICE_PROGRAM_FIRMWARE |<------. | | -// | '-------------------------------' | | | -// | | Need more data | | | -// | V | | | -// | .-----------------------------. More | | | -// | | DFUS_READ_FIRMWARE_DATA |--------' | | -// | '-----------------------------' data | | -// | | Error | | -// | V | | -// | .-----------------------. | | -// '---------->| DFUS_DEVICE_CLOSE |<--------------' | -// '-----------------------' | -// | false -> loopInUpdate | -// if (doAll == false) | | -// .-----------------------+ | -// | | if (doAll == true) | -// | V | -// | .-----------------------. | -// | | DFUS_NEXT_DEVICE |<------------------' -// | '-----------------------' -// | -// | if (reboot == true) .-----------------------. -// +----------------------->| DFUS_REBOOT | -// | '-----------------------' -// | -// | if (reboot == false) .-----------------------. -// '----------------------->| DFUS_DONE | -// '-----------------------' -// -//---------------------------------------- -void deviceFirmwareReset(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - const char * deviceName; - - deviceName = ctx->_deviceInfo->_deviceName; - - // Enable looping in update when programming a device - dfuLoopInUpdate = (ctx->_outputDeviceType == DFU_ODT_DEVICE); - - // Reset is not necessary when copying files - if (dfuLoopInUpdate) - { - // Get the reset routine - if (ctx->_deviceInfo->_reset) - { - if (settings.debugFirmwareUpdate) - systemPrintf("Resetting %s for firmware update\r\n", deviceName); - if (ctx->_deviceInfo->_reset(ctx, currentMsec)) - deviceFirmwareStateSet(ctx, DFUS_DEVICE_OPEN_OUTPUT); - else - { - systemPrintf("ERROR: %s firmware reset failed!\r\n", deviceName); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - } - return; - } - - // Testing or device does not require reset - if (settings.debugFirmwareUpdate) - systemPrintf("NOT IMPLEMENTED: %s firmware update reset routine!\r\n", - deviceName); - } - deviceFirmwareStateSet(ctx, DFUS_DEVICE_OPEN_OUTPUT); -} - -//---------------------------------------- -// Determine which action to perform -//---------------------------------------- -void deviceFirmwareSelectAction(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int action; - DFU_BUFFER_DATA * bufferData; - int bufferIndex; - const DEVICE_FIRMWARE_INFO * deviceInfo; - int fileNumber; - const char **nameArray; - const int * sortArray; - String url; - - do - { - // Verify that the input was specified - if (ctx->_inputDeviceType == DFU_IDT_NONE) - reportFatalError("Input device type is DFU_ODT_NONE!"); - - // Are all the devices being updated? - deviceInfo = ctx->_deviceInfo; - if (ctx->_doAll) - { - // Performing the firmware update - ctx->_outputDeviceType = DFU_ODT_DEVICE; - deviceFirmwareStateSet(ctx, ctx->_deviceInfo->_crcNeeded - ? DFUS_CRC_OPEN_INPUT - : DFUS_DEVICE_OPEN_INPUT); - break; - } - - // Handle the menu timeout - if ((currentMsec - ctx->_timerMsec) >= (menuTimeout * MILLISECONDS_IN_A_SECOND)) - { - systemPrintf("\r\nUser input timeout\r\n"); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - break; - } - - // Get the action from user input - if (Serial.available() == 0) - break; - action = Serial.read(); - - // Done timing out the menu choice - ctx->_timerMsec = 0; - - // Echo the input - systemPrintf("%c\r\n", action); - - // Initiate the action - if ((action == 'd') - && ((ctx->_inputDeviceType == DFU_IDT_NVM) - || (ctx->_inputDeviceType == DFU_IDT_SD))) - { - // Display the menu choice - if (settings.debugFirmwareUpdate) - systemPrintf("\r\nDelete the firmware file\r\n"); - - // Delete the file - if (ctx->_inputDeviceType == DFU_IDT_NVM) - dfuNvmDelete(ctx->_fileName.c_str()); - else - dfuSdDelete(ctx->_fileName.c_str()); - - // Display the file list again - deviceFirmwareFileListReload(ctx); - } - else if ((action == 'n') && ctx->_deviceInfo->_useNvm - && (ctx->_inputDeviceType != DFU_IDT_NVM)) - { - // Display the menu choice - if (settings.debugFirmwareUpdate) - systemPrintf("\r\nCopy firmware file to NVM\r\n"); - - // Start the file copy - ctx->_outputDeviceType = DFU_ODT_NVM; - deviceFirmwareStateSet(ctx, DFUS_DEVICE_OPEN_INPUT); - } - else if ((action == 's') && present.microSd - && (ctx->_inputDeviceType != DFU_IDT_SD)) - { - // Display the menu choice - if (settings.debugFirmwareUpdate) - systemPrintf("\r\nCopy firmware file to SD card\r\n"); - - // Start the file copy - ctx->_outputDeviceType = DFU_ODT_SD; - deviceFirmwareStateSet(ctx, DFUS_DEVICE_OPEN_INPUT); - } - else if (action == 'u') - { - // Display the menu choice - if (settings.debugFirmwareUpdate) - systemPrintf("\r\nUpdate %s firmware\r\n", ctx->_deviceInfo->_deviceName); - - // Start the programming process - ctx->_outputDeviceType = DFU_ODT_DEVICE; - deviceFirmwareStateSet(ctx, ctx->_deviceInfo->_crcNeeded - ? DFUS_CRC_OPEN_INPUT - : DFUS_DEVICE_OPEN_INPUT); - } - else if (action == 'x') - deviceFirmwareStateSet(ctx, DFUS_DONE); - else - { - systemPrintf("\r\nInvalid selection\r\n"); - deviceFirmwareActionMenu(ctx); - } - } while (0); -} - -//---------------------------------------- -// Select the device to use -//---------------------------------------- -void deviceFirmwareSelectDevice(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int incoming; - size_t length; - - do - { - // Are all devices being updated - if (ctx->_doAll) - { - // Start from the end of the device list - if (ctx->_deviceInfo == nullptr) - ctx->_deviceInfo = &deviceFirmwareInfo[deviceFirmwareInfoCount]; - - // Locate the next device - while (1) - { - // Determine if it is time to reboot - if (ctx->_deviceInfo == &deviceFirmwareInfo[0]) - { - if (ctx->_reboot) - dfuEsp32Reboot(); - - systemPrintf("%s\r\n", dfuEqualSigns); - systemPrintf("HALTED: Firmware update failed!\r\n"); - systemPrintf("%s\r\n", dfuEqualSigns); - reportFatalError("Firmware update failed!"); - } - - // Determine if the next device is in the system - ctx->_deviceInfo -= 1; - if ((ctx->_deviceInfo->_present == nullptr) - || (*ctx->_deviceInfo->_present)) - { - if ((dfuBufferInfo[0]._bufferData == nullptr) - || (dfuBufferInfo[0]._bufferData->_address == nullptr)) - { - // Allocate the buffers - if (deviceFirmwareBufferAllocate(ctx) == false) - reportFatalError("Failed buffer allocation!"); - } - - // Display the firmware version - if (ctx->_deviceInfo->_version) - systemPrintf("Current firmware version: %s\r\n", ctx->_deviceInfo->_version(ctx).c_str()); - - // Program the next device - goto nextDevice; - } - } - } - - // Handle the menu timeout - incoming = deviceFirmwareGetNumber(ctx, currentMsec); - - // Done timing out the menu choice - if (incoming != DFU_USER_INPUT_NOT_DONE) - ctx->_timerMsec = 0; - - if (incoming == DFU_USER_INPUT_NOT_A_NUMBER) - { - systemPrintf("Invalid selection\r\n"); - - // Display the menu again - deviceFirmwareDeviceListMenu(ctx); - break; - } - - // Get the user selection - if ((incoming >= 0) && (incoming <= deviceFirmwareInfoCount)) - { - // Valid menu choice - ctx->_deviceInfo = &deviceFirmwareInfo[incoming]; - -nextDevice: - // Display the menu choice - systemPrintf("Selected device: %s\r\n", ctx->_deviceInfo->_deviceName); - - // Allocate the necessary write buffer - length = ctx->_deviceInfo->_writeBufferBytes; - if (length) - { - // Allocate the write buffer for this device - ctx->_writeBuffer = (uint8_t *)rtkMalloc(length, "Firmware update write buffer"); - if (ctx->_writeBuffer == nullptr) - { - systemPrintf("ERROR: Failed to allocate the write buffer of %d bytes\r\n", length); - reportHeapNow(true); - if (ctx->_doAll) - ctx->_reboot = false; - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - break; - } - } - - // Allocate the device specific context - length = ctx->_deviceInfo->_devContextBytes; - if (length) - { - // Allocate the device specific context - ctx->_devCtx = (uint8_t *)rtkMalloc(length, "Device specific firmware update context"); - if (ctx->_devCtx == nullptr) - { - systemPrintf("ERROR: Failed to allocate the device specific context of %d bytes\r\n", length); - reportHeapNow(true); - if (ctx->_doAll) - ctx->_reboot = false; - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - break; - } - - // Initialize the device specific context - memset(ctx->_devCtx, 0, length); - if (ctx->_deviceInfo->_initDevCtx) - { - if (ctx->_deviceInfo->_initDevCtx(ctx) == false) - { - systemPrintf("ERROR: Failed to initialize the %s device specific context\r\n", - ctx->_deviceInfo->_deviceName); - if (ctx->_doAll) - ctx->_reboot = false; - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - } - } - } - - // Determine maximum bytes to write at a time - ctx->_bytesMax = ctx->_deviceInfo->_maxWriteBytes - ? ctx->_deviceInfo->_maxWriteBytes : ctx->_bufferLength; - - // Get the files - systemPrintf("Getting the file list...\r\n"); - deviceFirmwareStateSet(ctx, ctx->_networkConfigured ? DFUS_GET_NETWORK_FILES - : DFUS_GET_NVM_FILE_LIST); - break; - } - - // Continue putting together the input string - } while (0); -} - -//---------------------------------------- -// Determine which file was selected -//---------------------------------------- -void deviceFirmwareSelectFile(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - DFU_BUFFER_DATA * bufferData; - int bufferIndex; - const DEVICE_FIRMWARE_INFO * deviceInfo; - int fileNumber; - const char **nameArray; - const int * sortArray; - String url; - - do - { - // Are all the devices being updated? - deviceInfo = ctx->_deviceInfo; - if (ctx->_doAll) - { - // Yes, does this device have some firmware? - if (ctx->_fileCountNet) - { - // Yes, use the most recent network firmware file - ctx->_inputDeviceType = DFU_IDT_NETWORK; - fileNumber = 0; - break; - } - - // Skip this device - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - break; - } - - // Get the file selection from user input - fileNumber = deviceFirmwareGetNumber(ctx, currentMsec); - - // Done timing out the menu choice - if (fileNumber != DFU_USER_INPUT_NOT_DONE) - ctx->_timerMsec = 0; - - // Process the user request - switch (fileNumber) - { - default: - if ((fileNumber >= 0) && (fileNumber < ctx->_fileCount)) - { - // Valid menu choice, get the selected file - break; - } - - // Fall through - // | - // V - - case DFU_USER_INPUT_NOT_A_NUMBER: - systemPrintf("Invalid selection\r\n"); - deviceFirmwareFileListMenu(ctx); - return; - - case DFU_USER_INPUT_NOT_DONE: - // Continue putting together the input string - return; - - case DFU_USER_INPUT_OVERFLOWS_BUFFER: - systemPrintf("ERROR: Input buffer overflow\r\n"); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - return; - - case DFU_USER_INPUT_TIMEOUT: - systemPrintf("ERROR: User input timeout\r\n"); - deviceFirmwareStateSet(ctx, DFUS_NEXT_DEVICE); - return; - } - } while (0); - - // Determine the type of input and the file name array and index - if (fileNumber < ctx->_fileCountNet) - { - ctx->_inputDeviceType = DFU_IDT_NETWORK; - bufferData = &dfuFirmwareFileNamesNet; - } - else - { - fileNumber -= ctx->_fileCountNet; - if (fileNumber < ctx->_fileCountNvm) - { - ctx->_inputDeviceType = DFU_IDT_NVM; - bufferData = &dfuFirmwareFileNamesNvm; - } - else - { - fileNumber -= ctx->_fileCountNvm; - ctx->_inputDeviceType = DFU_IDT_SD; - bufferData = &dfuFirmwareFileNamesSd; - } - } - - // Get the array addresses - bufferIndex = bufferGetIndex(bufferData); - nameArray = (const char **)bufferData->_nameArray; - sortArray = bufferData->_sortArray; - - // Build the file name - ctx->_fileName = "/"; - ctx->_fileName += nameArray[sortArray[fileNumber]]; - - // Build the raw URL - url = deviceInfo->_server; - if (deviceInfo->_rawBranch) - url += deviceInfo->_rawBranch; - if (deviceInfo->_directory) - url += deviceInfo->_directory; - url += ctx->_fileName; - ctx->_url = url; - ctx->_validDataBytes = 0; - - // Display the menu choice - if (settings.debugFirmwareUpdate) - systemPrintf("Selected file: %s:%s\r\n", - deviceFirmwareGetDevicePrefix(ctx->_inputDeviceType), - ctx->_fileName.c_str()); - - // Determine what to do with this file - deviceFirmwareStateSet(ctx, DFUS_SELECT_ACTION); - - // Display the menu - deviceFirmwareActionMenu(ctx); -} - -//---------------------------------------- -// Get the state name -//---------------------------------------- -const char * deviceFirmwareStateGetName(int state) -{ - if ((state >= 0) && (state < dfuStateNameCount)) - return dfuStateName[state]; - else - return "Unknown"; -} - -//---------------------------------------- -// Update device firmware state -//---------------------------------------- -void deviceFirmwareStateSet(DEVICE_FIRMWARE_CTX * ctx,int newState) -{ - const char * currentStateName; - const char * newStateName; - - if (settings.debugFirmwareUpdate) - { - currentStateName = deviceFirmwareStateGetName(ctx->_state); - newStateName = deviceFirmwareStateGetName(newState); - if (newStateName == currentStateName) - systemPrintf("Device firmware state transition: *%s\r\n", currentStateName); - else - systemPrintf("Device firmware state transition: %s --> %s\r\n", currentStateName, newStateName); - } - ctx->_state = newState; -} - -//---------------------------------------- -// Stop tasks -//---------------------------------------- -void deviceFirmwareStopTasks(DEVICE_FIRMWARE_CTX * ctx) -{ - // Turn off any tasks so that we are not disrupted - wifiEspNowOff(__FILE__, __LINE__); - if (ctx->_networkConfigured == false) - wifiStopAll(); - bluetoothEnd(); - - // Delete tasks if running - tasksStopGnssUart(); -} - -//---------------------------------------- -// Start the timer -//---------------------------------------- -void deviceFirmwareTimerStart(DEVICE_FIRMWARE_CTX * ctx) -{ - // Verify that the timer is not already in use - if (ctx->_timerMsec) - reportFatalError("Device firmware update timer in use!"); - - ctx->_timerMsec = millis(); -} - -//---------------------------------------- -// Perform the device firmware update -//---------------------------------------- -bool deviceFirmwareUpdate(uint32_t currentMsec) -{ - DEVICE_FIRMWARE_CTX * ctx; - bool running; - const char * stateName; - - // Get the context instance - running = false; - ctx = dfuContext; - if (ctx) - { - do - { - running = true; - - // Blink the LED - deviceFirmwareLedBlink(ctx, currentMsec); - - // Perform the firmware update - switch (ctx->_state) - { - case DFUS_INIT: deviceFirmwareInit(ctx, currentMsec); break; - case DFUS_WAIT_NETWORK: deviceFirmwareWaitForNetwork(ctx, currentMsec); break; - case DFUS_GET_DEVICE: deviceFirmwareSelectDevice(ctx, currentMsec); break; - case DFUS_GET_NETWORK_FILES: dfuNetworkFileListBuildUrl(ctx); break; - case DFUS_GET_HTTP_FILE_LIST_REQ: dfuNetworkFileListHtmlRequest(ctx, currentMsec); break; - case DFUS_GET_NETWORK_FILE_LIST: dfuNetworkFileListGetFileName(ctx, currentMsec); break; - case DFUS_GET_NVM_FILE_LIST: dfuNvmGetFiles(ctx, currentMsec); break; - case DFUS_GET_SD_FILE_LIST: dfuSdGetFiles(ctx, currentMsec); break; - case DFUS_SELECT_FILE: deviceFirmwareSelectFile(ctx, currentMsec); break; - case DFUS_SELECT_ACTION: deviceFirmwareSelectAction(ctx, currentMsec); break; - case DFUS_CRC_OPEN_INPUT: deviceFirmwareCrcOpen(ctx, currentMsec); break; - case DFUS_CRC_READ_DATA: deviceFirmwareCrcReadData(ctx, currentMsec); break; - case DFUS_CRC_CLOSE: deviceFirmwareCrcClose(ctx, currentMsec); break; - case DFUS_DEVICE_OPEN_INPUT: deviceFirmwareOpenFirmwareFile(ctx, currentMsec); break; - case DFUS_DEVICE_FILL_BUFFER: deviceFirmwareReadFillBuffer(ctx, currentMsec); break; - case DFUS_DEVICE_RESET: deviceFirmwareReset(ctx, currentMsec); break; - case DFUS_DEVICE_OPEN_OUTPUT: deviceFirmwareOpenOutput(ctx, currentMsec); break; - case DFUS_DEVICE_PROGRAM_FIRMWARE: deviceFirmwareWrite(ctx, currentMsec); break; - case DFUS_READ_FIRMWARE_DATA: deviceFirmwareReadFirmwareData(ctx, currentMsec); break; - case DFUS_DEVICE_CLOSE: deviceFirmwareClose(ctx, currentMsec); break; - case DFUS_NEXT_DEVICE: deviceFirmwareNextDevice(ctx, currentMsec); break; - case DFUS_REBOOT: dfuEsp32Reboot(); break; - - case DFUS_DONE: - deviceFirmwareBufferFree(ctx, true); - deviceFirmwareCleanup(ctx); - running = false; - break; - - default: - stateName = deviceFirmwareStateGetName(ctx->_state); - systemPrintf("Device firmware update state: %d (%s)\r\n", ctx->_state, stateName); - reportFatalError("Device firmware update state not implemented!"); - deviceFirmwareStateSet(ctx, DFUS_DONE); - break; - } - } while (dfuLoopInUpdate); - } - return running; -} - -//---------------------------------------- -// State machine to perform the device firmware update -//---------------------------------------- -bool deviceFirmwareUpdateBegin(bool doAll, - bool debugVerbose, - size_t saveDataLength) -{ - DEVICE_FIRMWARE_CTX * ctx; - uint32_t currentMsec; - size_t length; - bool running; - - do - { - running = false; - - // Verify the state table - deviceFirmwareVerifyTables(); - - // Only call this routine when device firmware update is not running - if (dfuContext) - { - reportFatalError("ERROR: Device firmware update is already running!"); - break; - } - - // Allocate the device context structure - length = sizeof(*ctx); - if (settings.debugFirmwareUpdate) - systemPrintf("Allocating %d bytes for device firmware update context\r\n", length); - ctx = (DEVICE_FIRMWARE_CTX *)rtkMalloc(length, "Device firmware context"); - if (ctx == nullptr) - { - systemPrintf("ERROR: Failed to allocate the device firmware context of %d bytes\r\n", length); - reportHeapNow(true); - break; - } - - // Initialize the context - memset(ctx, 0, length); - ctx->_doAll = doAll; - ctx->_debugVerbose = debugVerbose; - if (doAll) - { - ctx->_outputDeviceType = DFU_ODT_DEVICE; - ctx->_reboot = true; - } - - // Allocate the save data buffer - if (debugVerbose && saveDataLength) - { - length = saveDataLength; - if (settings.debugFirmwareUpdate) - systemPrintf("Allocating %d bytes for _saveData\r\n", length); - ctx->_saveData = (uint8_t *)rtkMalloc(length, "DFU: ctx->_saveData"); - if (ctx->_saveData == nullptr) - { - systemPrintf("ERROR: Failed to allocate ctx->_saveData of %d bytes\r\n", length); - rtkFree(ctx, "Device firmware context"); - reportHeapNow(true); - break; - } - ctx->_saveDataLength = length; - } - - // Set the initial state - deviceFirmwareStateSet(ctx, DFUS_INIT); - dfuContext = ctx; - - running = deviceFirmwareUpdate(millis()); - } while (0); - return running; -} - -//---------------------------------------- -// Verify the tables have the correct number of entries -//---------------------------------------- -void deviceFirmwareVerifyTables() -{ - if (DFUS_MAX != dfuStateNameCount) - reportFatalError("Fix _DEVICE_FIRMWARE_UPDATE_STATE and dfuStateName!"); -} - -//---------------------------------------- -// Wait for a network connection -//---------------------------------------- -bool deviceFirmwareWaitForNetwork(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - bool hasInternetAccess; - - do - { - hasInternetAccess = false; - - // Determine if the network is configured - if (ctx->_networkConfigured == false) - reportFatalError("deviceFirmwareWaitForNetwork when ctx->_networkConfigured = false"); - - // Wait for the link to come up - hasInternetAccess = networkHasInternet(); - if (hasInternetAccess == false) - { - // Don't wait forever - if ((currentMsec - ctx->_timerMsec) < WIFI_IP_ADDRESS_TIMEOUT_MSEC) - break; - - // Stop polling the network - ctx->_networkConfigured = false; - } - - // Done timing out the network connection - ctx->_timerMsec = 0; - - // Display the menu - deviceFirmwareStateSet(ctx, DFUS_GET_DEVICE); - deviceFirmwareDeviceListMenu(ctx); - } while (0); - return hasInternetAccess; -} - -//---------------------------------------- -// Perform the firmware update -//---------------------------------------- -void deviceFirmwareWrite(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - size_t bytesToWrite; - ssize_t bytesWritten; - bool done; - int percentage; - DEVICE_WRITE write; - - // Determine if there is enough data to write - write = ctx->_deviceInfo->_write; - bytesWritten = 0; - while (ctx->_validDataBytes - && ((ctx->_validDataBytes >= ctx->_bytesMax) - || (ctx->_validDataBytes == (ctx->_fileBytes - ctx->_bytesWritten)))) - { - // Determine how much firmware data can be written - bytesToWrite = min(ctx->_bytesMax, ctx->_fileBytes - ctx->_bytesWritten); - - // Use this value for testing - bytesWritten = ctx->_bytesMax; - - // Write the data to the device - if (write && (ctx->_outputDeviceType == DFU_ODT_DEVICE)) - { - bytesWritten = write(ctx, ctx->_data, bytesToWrite); - if (bytesWritten > bytesToWrite) - bytesWritten = bytesToWrite; - } - else if (ctx->_outputDeviceType == DFU_ODT_NVM) - bytesWritten = dfuNvmWrite(ctx, ctx->_data, bytesToWrite); - else if (ctx->_outputDeviceType == DFU_ODT_SD) - bytesWritten = dfuSdWrite(ctx, ctx->_data, bytesToWrite); - - // Handle the error case - if (bytesWritten <= 0) - break; - - // Account for the data written - ctx->_validDataBytes -= bytesWritten; - ctx->_data += bytesWritten; - ctx->_bytesWritten += bytesWritten; - if (ctx->_bytesWritten == ctx->_fileBytes) - ctx->_complete = true; - - // Display the number of bytes written - if (settings.debugFirmwareUpdate && ctx->_debugVerbose) - systemPrintf("bytesWritten: %d\r\n", bytesWritten); - - // Display the percentage changes - percentage = ctx->_bytesWritten * 100 / ctx->_fileBytes; - if (percentage != ctx->_percentage) - { - ctx->_percentage = percentage; - displayFirmwareUpdateProgress(percentage); - systemPrintf("\r[%s %d%%%s", - &dfuEqualSigns[strlen(dfuEqualSigns) - (percentage >> 1)], - percentage, - settings.debugFirmwareUpdate ? "\r\n" : ""); - } - } - - // Read more data - done = ctx->_complete || (bytesWritten <= 0); - if (ctx->_complete && (settings.debugFirmwareUpdate == false)) - systemPrintln(); - deviceFirmwareStateSet(ctx, done ? DFUS_DEVICE_CLOSE - : DFUS_READ_FIRMWARE_DATA); -} - -#endif // COMPILE_NETWORK - -#endif // COMPILE_MENU_FIRMWARE diff --git a/Firmware/RTK_Everywhere/Device_Update.h b/Firmware/RTK_Everywhere/Device_Update.h deleted file mode 100644 index 72ab1027b..000000000 --- a/Firmware/RTK_Everywhere/Device_Update.h +++ /dev/null @@ -1,337 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update.h - - Device firmware update data structures and declarations -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifndef __DEVICE_UPDATE_H__ -#define __DEVICE_UPDATE_H__ - -//---------------------------------------- -// Describe the volatile buffer description -//---------------------------------------- -typedef struct _DFU_BUFFER_DATA -{ - uint8_t * _address; - size_t _length; - size_t _offset; - char ** _nameArray; - int * _sortArray; -} DFU_BUFFER_DATA; - -//---------------------------------------- -// Allocate and forget buffer descriptions used during early initialization -//---------------------------------------- -typedef struct _DFU_BUFFER_INFO -{ - bool * _present; // nullptr or *_present = true, allocate buffer - size_t _sizeInBytes; // Initial buffer size - DFU_BUFFER_DATA * _bufferData; - const char * _description; // Text for rtkMalloc -} DFU_BUFFER_INFO; - -//---------------------------------------- -// Context for the firmware update processing -//---------------------------------------- -typedef struct _DEVICE_FIRMWARE_CTX -{ - void * _devCtx; // Device specific context address - const struct _DEVICE_FIRMWARE_INFO * _deviceInfo; // Selected device - int _state; // Current device firmware update state - bool _doAll; // Perform all of the device firmware updates - bool _debugVerbose; // Display the most amount of data - - // Input device - int _inputDeviceType; // Type of input device - bool _networkConfigured; // Is the network configured - -#ifdef COMPILE_NETWORK - HTTPClient * _https; // HTTPS object connected to web server - NetworkClientSecure * _httpsClient; // Secure HTTPS client - NetworkClient * _networkClient; // Network client object connected to web server -#endif // COMPILE_NETWORK - - String _url; // URL for network access - String _fileName; // File name for SD and NVM - size_t _fileBytes; // Length of the file in bytes - bool _crcNeeded; // Does CRC need to be computed - uint32_t _crc; // CRC value - uint32_t _crcSave; // CRC computed during deviceFirmwareCrcReadData - - // Buffer support - bool _dynamicAllocationFd; - bool _dynamicAllocationNet; - bool _dynamicAllocationNvm; - bool _dynamicAllocationSd; - - // Read support - // - // _buffer ---. .--- _data - // | | - // V V - // [----------------xxxxxxxxxxxxxxxxxxxxxxxx--------] - // | |<-- _validDataBytes -->| | - // |<-- _bufferLength ----------------------------->| - // - // |<--------------- _fileBytes ------------------->| - // [rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr---] - // |<---------------- _bytesRead -------------->| - // - uint8_t * _buffer; // Buffer to read in the firmware - uint8_t * _data; // Beginning of valid data - size_t _bufferLength; // Length of the buffer - size_t _validDataBytes; // Length of the valid data - size_t _bytesRead; // Total number of bytes read - - // File objects for input or output - File _nvmFile; // NVM file object - SdFile _sdFile; // SD file object - int _fileCountNet; // Number of network files - int _fileCountNvm; // Number of NVM files - int _fileCountSd; // Number of SD files - int _fileCount; // Total files - - // Write path support - // - // _buffer ---. .--- _data - // | | - // V V - // [----------------xxxxxxxxxxxxxxxxxxxxxxxx--------] - // | |<-- _bytesMax -->| | - // | |<-- _validDataBytes -->| | - // |<-- _bufferLength ----------------------------->| - // - // - // |<--------------- _fileBytes ------------------->| - // [wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwrrrrr---] - // |<-------- _bytesWritten -------------->| | - // |<---------------- _bytesRead -------------->| - // - int _outputDeviceType; // Type of output device - uint8_t * _writeBuffer; // Additional buffer for write operations - size_t _bytesMax; // Maximum bytes to write at one time - size_t _bytesWritten; // Number of bytes written to the output device - uint32_t _packetNumber; // Current firmware packet number - - // Verbose debug buffer - uint8_t * _saveData; // Buffer to receive input data from device - size_t _saveDataLength; // Size in bytes of the save buffer - - // Status values - uint32_t _attemptNumber; // Number of attempts - uint32_t _lastBlinkMsec; // Blinking LED to indicate activity - uint32_t _startMsec; // Starting time of file transfer - uint32_t _timerMsec; // General timer - int _percentage; // Write percentage - bool _complete; // Transfer complete (_bytesWritten == _fileBytes) - bool _reboot; // Reboot after firmware update -} DEVICE_FIRMWARE_CTX; - -//---------------------------------------- -// Declare the global device firmware update context -//---------------------------------------- -DEVICE_FIRMWARE_CTX * dfuContext; - -//---------------------------------------- -// Declare the device firmware update states (DFUS) -//---------------------------------------- -enum _DEVICE_FIRMWARE_UPDATE_STATE -{ - DFUS_DONE = 0, - DFUS_INIT, - DFUS_WAIT_NETWORK, - DFUS_GET_DEVICE, - DFUS_GET_NETWORK_FILES, - DFUS_GET_HTTP_FILE_LIST_REQ, - DFUS_GET_NETWORK_FILE_LIST, - DFUS_GET_NVM_FILE_LIST, - DFUS_GET_SD_FILE_LIST, - DFUS_SELECT_FILE, - DFUS_SELECT_ACTION, - DFUS_CRC_OPEN_INPUT, - DFUS_CRC_READ_DATA, - DFUS_CRC_CLOSE, - DFUS_DEVICE_OPEN_INPUT, - DFUS_DEVICE_FILL_BUFFER, - DFUS_DEVICE_RESET, - DFUS_DEVICE_OPEN_OUTPUT, - DFUS_DEVICE_PROGRAM_FIRMWARE, - DFUS_READ_FIRMWARE_DATA, - DFUS_DEVICE_CLOSE, - DFUS_NEXT_DEVICE, - DFUS_REBOOT, - // Add new states above this line - DFUS_MAX -}; - -//---------------------------------------- -// Input device containing the firmware file -//---------------------------------------- -enum DFU_INPUT_DEVICE_TYPE -{ - DFU_IDT_NONE = 0, - DFU_IDT_NETWORK, - DFU_IDT_NVM, - DFU_IDT_SD, -}; - -//---------------------------------------- -// Output device to which the firmware file will be copied -//---------------------------------------- -enum DFU_OUTPUT_DEVICE_TYPE -{ - DFU_ODT_NONE = 0, - DFU_ODT_TEST, - DFU_ODT_DEVICE, - DFU_ODT_NVM, - DFU_ODT_SD, -}; - -//---------------------------------------- -// Declare the generic device firmware update routines -//---------------------------------------- -typedef void (* DEVICE_CLOSE)(DEVICE_FIRMWARE_CTX * ctx); -typedef bool (* DEVICE_OPEN)(DEVICE_FIRMWARE_CTX * ctx); -typedef bool (* DEVICE_RESET)(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec); -typedef ssize_t (* DEVICE_WRITE)(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite); -typedef String (* GET_FIRMWARE_VERSION)(DEVICE_FIRMWARE_CTX * ctx); -typedef bool (* INIT_DEV_CTX)(DEVICE_FIRMWARE_CTX * ctx); - -//---------------------------------------- -// Describe a device that needs firmware updates -//---------------------------------------- -typedef struct _DEVICE_FIRMWARE_INFO -{ - // The following fields should be unique to each device - const char * _deviceName; // Name of this device - bool * _present; // Load firmware if (_present == nullptr) or (*_present == true) - const char * _directory; // Firmware directory - const char * _nameData; // Data in file name, may be nullptr - const char * _extension; // Data in file name (extension), may be nullptr - GET_FIRMWARE_VERSION _version; // Firmware version display routine - DEVICE_RESET _reset; // Reset the device before loading firmware - DEVICE_OPEN _open; // Prepare for firmware updates - DEVICE_WRITE _write; // Perform the firmware writes - DEVICE_CLOSE _close; // Perform firmware write cleanup - INIT_DEV_CTX _initDevCtx; // Initialize the device specific context - size_t _devContextBytes; // Size of device specific context buffer - bool _crcNeeded; // Is file CRC needed to do firmware update - bool _useNvm; // Allow copy to NVM - size_t _writeBufferBytes; // Number of bytes needed for the write buffer - size_t _maxWriteBytes; // Maximum write packet size - - // The following fields are used to parse the web page to locate the - // file name and to build the HTTP link to access the file. - // - // Note: Use the JSON based OTA to get a new ESP32 image when the - // parsing fails due to website changes on the servers below! - const char * _server; // Firmware server - const char * _branch; // Firmware branch - const char * _dirPrefix; // Data before directory listing, may be nullptr - const char * _dirPrefix2; // Data before directory listing, may be nullptr - const char * _dirSuffix; // Data after directory listing - const char * _entryPrefix; // Data before file name, may be nullptr - const char * _entrySuffix; // Data after file name - const char * _rawBranch; // Firmware raw tree branch -} DEVICE_FIRMWARE_INFO; - -//---------------------------------------- -// Device firmware update descriptions -//---------------------------------------- - -// File that is loaded from SD card at startup regardless of user input -const char * forceFirmwareFileName = "RTK_Everywhere_Firmware_Force.bin"; - -// GitHub web-page parsing for file lists -const char * dfuGithub = "https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware_Binaries"; -const char * dfuRawHead = "/raw/refs/heads/main"; -const char * dfuTree = "},\"tree"; -const char * dfuFileTree = ":{\"fileTree\":{\""; -const char * dfuItems = "\":{\"items\":["; -const char * dfuListEnd = "]"; -const char * dfuName = "\"name\":\""; -const char * dfuNameEnd = "\""; - -//---------------------------------------- -// Statically allocated buffers -//---------------------------------------- - -DFU_BUFFER_DATA dfuFirmwareData; -DFU_BUFFER_DATA dfuFirmwareFileNamesNet; -DFU_BUFFER_DATA dfuFirmwareFileNamesNvm; -DFU_BUFFER_DATA dfuFirmwareFileNamesSd; - -// Allocate buffer when (_present == nullptr) or (*_present == true) -// Delayed allocations must be detected by code using the buffer -const DFU_BUFFER_INFO dfuBufferInfo[] = -{ // _present _sizeInBytes _address _description - {nullptr, 16 * 1024, &dfuFirmwareData, "DFU Firmware data buffer"}, - {nullptr, 4 * 1024, &dfuFirmwareFileNamesNet, "DFU network file names buffer"}, - {nullptr, 4 * 1024, &dfuFirmwareFileNamesNvm, "DFU NVM file names buffer"}, - {&present.microSd, 4 * 1024, &dfuFirmwareFileNamesSd, "DFU SD card file names buffer"}, -}; -const int dfuBufferInfoCount = sizeof(dfuBufferInfo) / sizeof(dfuBufferInfo[0]); - -//---------------------------------------- -// Declare the device specific maximum write size -//---------------------------------------- - -// LG290P declarations -#ifdef COMPILE_LG290P -#define DFU_LG290P_MAX_PAYLOAD_SIZE (5 * 1024) -#define DFU_LG290P_BYTES (1 + 1 + 1 + 2 + 4 + DFU_LG290P_MAX_PAYLOAD_SIZE + 4 + 1) -#endif // COMPILE_LG290P - -//---------------------------------------- -// Declare the forward device support routines -//---------------------------------------- - -// Get firmware version -String dfuEsp32GetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx); -String dfuGnssGetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx); - -// Device reset -bool dfuLg290pReset(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec); - -// Device open, prepare for writing firmware -bool dfuEsp32Open(DEVICE_FIRMWARE_CTX * ctx); -bool dfuLg290pOpen(DEVICE_FIRMWARE_CTX * ctx); - -// Device write, perform the firmware update -ssize_t dfuEsp32Write(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite); -ssize_t dfuLg290pWrite(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite); - -// Device close, finalize the firmware update -void dfuEsp32Close(DEVICE_FIRMWARE_CTX * ctx); -void dfuLg290pClose(DEVICE_FIRMWARE_CTX * ctx); - -// Declare the begin routine -bool deviceFirmwareUpdateBegin(bool doAll, - bool debugVerbose, - size_t saveDataLength = 8 * 1024); - -//---------------------------------------- -// Describe the devices that support firmware update -//---------------------------------------- - -// Note: Use the JSON based OTA to get a new ESP32 image when the -// parsing fails due to website changes on the servers below! -const DEVICE_FIRMWARE_INFO deviceFirmwareInfo[] = -{// Name present Directory NameData Extension Firmware version Reset Open Write Close InitDevCtx Context Bytes CRC useNvm Buffer Bytes Max Write Bytes Server Branch dPrefix1 dPrefix2 dirEnd nPrefix nameEnd Raw Branch - {"ESP32", nullptr, nullptr, "Firmware_v", ".bin", dfuEsp32GetFirmwareVersion, nullptr, dfuEsp32Open, dfuEsp32Write, dfuEsp32Close, nullptr, 0, false, false, 0, 0, dfuGithub, nullptr, dfuTree, dfuItems, dfuListEnd, dfuName, dfuNameEnd, dfuRawHead}, - // ESP32 must be the first entry in the list, p command does list in reverse - - // GNSS devices -#ifdef COMPILE_LG290P - {"LG290P", &present.gnss_lg290p, "/gnss/lg290p", "LG290P", ".pkg", dfuGnssGetFirmwareVersion, dfuLg290pReset, dfuLg290pOpen, dfuLg290pWrite, dfuLg290pClose, nullptr, 0, true, false, DFU_LG290P_BYTES, DFU_LG290P_MAX_PAYLOAD_SIZE, dfuGithub, dfuRawHead, dfuFileTree, dfuItems, dfuListEnd, dfuName, dfuNameEnd, dfuRawHead}, -#endif // COMPILE_LG290P -}; -const int deviceFirmwareInfoCount = sizeof(deviceFirmwareInfo) / sizeof(deviceFirmwareInfo[0]); - -#endif // __DEVICE_UPDATE_H__ diff --git a/Firmware/RTK_Everywhere/Device_Update_ESP32.ino b/Firmware/RTK_Everywhere/Device_Update_ESP32.ino deleted file mode 100644 index 932cae615..000000000 --- a/Firmware/RTK_Everywhere/Device_Update_ESP32.ino +++ /dev/null @@ -1,104 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update_ESP32.ino - - Support routines to program the ESP32 firmware application area -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -//---------------------------------------- -// Determine if the ESP32 supports OTA -//---------------------------------------- -bool dfuEsp32AreFirmwareWritesSupported() -{ - int partitionCount; - - // We can do OTA if there are two APP partitions - partitionCount = countAppPartitions(); - if (partitionCount >= 2) - return true; - - // Warn the user - systemPrintf("WARNING: ESP32 updates require two APP paritions, found %d!\r\n", - partitionCount); - printPartitionTable(); - return false; -} - -//---------------------------------------- -// ESP32 firmware close -//---------------------------------------- -void dfuEsp32Close(DEVICE_FIRMWARE_CTX * ctx) -{ - if (Update.end(ctx->_complete)) - { - if (Update.isFinished()) - { - displayFirmwareUpdateProgress(100); - - // Clear all settings from LittleFS - LittleFS.format(); - - systemPrintln("ESP32 updated successfully."); - - if ((ctx->_inputDeviceType == DFU_IDT_SD) && ctx->_complete) - { - // If forced firmware is detected, do a full reset of config as well - if (strcmp(forceFirmwareFileName, ctx->_fileName.c_str()) == 0) - { - systemPrintln("Removing firmware file"); - - // Remove forced firmware file to prevent endless loading - sd->remove(ctx->_fileName.c_str()); - gnssFactoryReset(); - } - } - return; - } - else - systemPrintln("Update not finished? Something went wrong!"); - } - else - systemPrintf("Error Occurred. Error #: %s\r\n", String(Update.getError())); - displayMessage("Update Failed", 0); - systemPrintln("Firmware update failed. Please try again."); - ctx->_complete = false; -} - -//---------------------------------------- -// Get the current ESP32 firmware version -//---------------------------------------- -String dfuEsp32GetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx) -{ - char version[128]; - //firmwareVersionGet(version, sizeof(version), true); - return String(version); -} - -//---------------------------------------- -// ESP32 firmware open -//---------------------------------------- -bool dfuEsp32Open(DEVICE_FIRMWARE_CTX * ctx) -{ - return Update.begin(ctx->_fileBytes); -} - -//---------------------------------------- -// Reboot the ESP32 -//---------------------------------------- -void dfuEsp32Reboot() -{ - // Restart ESP32 to see changes - systemPrintf("Rebooting. Goodbye!\r\n"); - Serial.flush(); - delay(1000); - ESP.restart(); -} - -//---------------------------------------- -// ESP32 firmware write -//---------------------------------------- -ssize_t dfuEsp32Write(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite) -{ - return Update.write((uint8_t *)buffer, bytesToWrite); -} diff --git a/Firmware/RTK_Everywhere/Device_Update_GNSS.ino b/Firmware/RTK_Everywhere/Device_Update_GNSS.ino deleted file mode 100644 index 023c89ca9..000000000 --- a/Firmware/RTK_Everywhere/Device_Update_GNSS.ino +++ /dev/null @@ -1,13 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update_GNSS.ino - - Support routines for GNSS devices -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -//---------------------------------------- -// Get the GNSS firmware version -//---------------------------------------- -String dfuGnssGetFirmwareVersion(DEVICE_FIRMWARE_CTX * ctx) -{ - return String(gnssFirmwareVersion); -} diff --git a/Firmware/RTK_Everywhere/Device_Update_LG290P.ino b/Firmware/RTK_Everywhere/Device_Update_LG290P.ino deleted file mode 100644 index 667a812ff..000000000 --- a/Firmware/RTK_Everywhere/Device_Update_LG290P.ino +++ /dev/null @@ -1,485 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update_LG290P.ino - - Support routines to program the LG290P firmware -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifdef COMPILE_LG290P - -//---------------------------------------- -// Send a sync command -//---------------------------------------- -bool dfuLg290pBootloaderSync() -{ - uint32_t currentMsec; - uint8_t data; - uint32_t lastSyncMsec; - int offset; - uint32_t startMsec; - // Little endian: word 1: 0xAAFC3A4D word 2: 0x55FD5BA0 - const uint8_t responseByte[8] = {0x4D, 0x3A, 0xFC, 0xAA, 0xA0, 0x5B, 0xFD, 0x55}; - // Little endian: word 1: 0x514C1309 - const uint8_t sync1Byte[8] = {0x09, 0x13, 0x4C, 0x51}; - // Little endian: word 2: 0x1203A504 - const uint8_t sync2Byte[8] = {0x04, 0xA5, 0x03, 0x12}; - bool timeout; - uint32_t timeoutMsec; - - // Over the next 500 mSec send the sync sequence every 20 mSec - startMsec = millis(); - lastSyncMsec = startMsec - MILLISECONDS_IN_AN_HOUR; - offset = 0; - timeout = false; - timeoutMsec = startMsec + 500; - - // Wait for a response to the first sync word - do - { - // Wait 20 mSec before sending the first sync word - currentMsec = millis(); - if ((currentMsec - lastSyncMsec) >= 20) - { - lastSyncMsec = currentMsec; - - // Send sync word 1 - serialGNSS->write(sync1Byte, sizeof(sync1Byte)); - if (settings.debugFirmwareUpdate) - systemPrintf("%d mSec\r\n", currentMsec - startMsec); - offset = 0; - } - else - { - // Wait for a response from the boot loader - while (serialGNSS->available()) - { - // Data arrives at 4 characters per millisecond - // Delay a little to wait for the received data stream - // to complete before sending another sync word 1. - lastSyncMsec += 1; - - // Verify the received data - data = serialGNSS->read(); - if (responseByte[offset] != data) - // Continue scanning the incoming data - offset = 0; - else - { - // A matching character was found - offset += 1; - - // Determine if the word 1 response was received - if (offset == 4) - { - // Semd sync word 2 - serialGNSS->write(sync2Byte, sizeof(sync2Byte)); - lastSyncMsec = millis(); - } - // Determine if the word 2 response was received - if (offset == 8) - return true; - } - } - } - - // Check for timeout - timeout = ((int32_t)(currentMsec - timeoutMsec) > 0); - } while (timeout == false); - if (settings.debugFirmwareUpdate) - systemPrintf("%d mSec\r\n", currentMsec - startMsec); - - // Tell the caller about the bootloader sync failure - return false; -} - -//---------------------------------------- -// Perform the cleanup after the firmware download -//---------------------------------------- -void dfuLg290pClose(DEVICE_FIRMWARE_CTX * ctx) -{ - dfuLg290pCmdReset(ctx->_debugVerbose); - delay(1 * MILLISECONDS_IN_A_SECOND); -} - -//---------------------------------------- -// Send the firmware erase command to the LG290P -//---------------------------------------- -bool dfuLg290pCmdErase(bool debugVerbose) -{ - uint8_t command[10]; - int retryCount; - - // Construct the command - command[0] = 0xaa; // Head - command[1] = 2; // Class ID - command[2] = 3; // Message ID - command[3] = 0; // Payload length (big endian) - command[4] = 0; - command[9] = 0x55; // Tail - - // Compute the CRC - dfuLg290pInsertCrc(0, &command[1], 4, &command[5]); - - // Retry the command if necesary - retryCount = 0; - do - { - // Send the command to the LG290P - if ((serialGNSS->write(command, sizeof(command)) == sizeof(command)) - // Verify the response - && (dfuLg290pCmdResponse(command, debugVerbose) == 0)) - { - if (settings.debugFirmwareUpdate) - systemPrintf("Successfully erased the LG290P firmware\r\n"); - return true; - } - } while (retryCount++ < 3); - return false; -} - -//---------------------------------------- -// Send the firmware infomation command to the LG290P -//---------------------------------------- -bool dfuLg290pCmdFirmwareInfo(ssize_t firmwareBytes, - uint32_t firmwareCrc, - bool debugVerbose) -{ - uint8_t command[26]; - uint32_t crc32; - - // Construct the command - command[0] = 0xaa; // Head - command[1] = 2; // Class ID - command[2] = 2; // Message ID - command[3] = 0; // Payload length (big endian) - command[4] = 0x10; - command[5] = (uint8_t)(firmwareBytes >> 24); // Firmware length in bytes (big endian) - command[6] = (uint8_t)(firmwareBytes >> 16); - command[7] = (uint8_t)(firmwareBytes >> 8); - command[8] = (uint8_t)firmwareBytes; - command[9] = (uint8_t)(firmwareCrc >> 24); // Firmware CRC in bytes (big endian) - command[10] = (uint8_t)(firmwareCrc >> 16); - command[11] = (uint8_t)(firmwareCrc >> 8); - command[12] = (uint8_t)firmwareCrc; - command[13] = 0; // Base address (big endian) - command[14] = 0; - command[15] = 0; - command[16] = 0; - command[17] = 0; // Reserved - command[18] = 0; - command[19] = 0; - command[20] = 0; - command[25] = 0x55; // Tail - - // Compute the CRC - dfuLg290pInsertCrc(0, &command[1], 20, &command[21]); - - // Send the command to the LG290P - return ((serialGNSS->write(command, sizeof(command)) == sizeof(command)) - // Verify the response - && (dfuLg290pCmdResponse(command, debugVerbose) == 0)); -} - -//---------------------------------------- -// Send the firmware reset command to the LG290P -//---------------------------------------- -bool dfuLg290pCmdReset(bool debugVerbose) -{ - uint8_t command[10]; - - // Construct the command - command[0] = 0xaa; // Head - command[1] = 2; // Class ID - command[2] = 0x31; // Message ID - command[3] = 0; // Payload length (big endian) - command[4] = 0; - command[9] = 0x55; // Tail - - // Compute the CRC - dfuLg290pInsertCrc(0, &command[1], 4, &command[5]); - - // Send the command to the LG290P - return ((serialGNSS->write(command, sizeof(command)) == sizeof(command)) - // Verify the response - && (dfuLg290pCmdResponse(command, debugVerbose) == 0)); -} - -//---------------------------------------- -// Get the response to a bootloader command -// -// Response Status -// 0x0000 Message received and executed successfully -// 0x0001 Unknown error -// 0x0002 CRC32 checksum error -// 0x0003 Timeout -// 0x0004 Unsupported message -// 0x0005 Message package error -// 0x0020 Firmware area erase error -// 0x0021 Firmware write Flash error -//---------------------------------------- -int32_t dfuLg290pCmdResponse(uint8_t * command, bool debugVerbose) -{ - uint8_t data; - size_t offset; - uint8_t response[14]; - int32_t responseStatus; - - // Get the response - offset = 0; - while (offset < sizeof(response)) - { - if (serialGNSS->available()) - { - data = serialGNSS->read(); - if ((offset == 0) && (data != 0xaa)) - continue; - response[offset++] = data; - } - } - - // Dump the response - if (settings.debugFirmwareUpdate && ((responseStatus != 0) || debugVerbose)) - dumpBuffer(0, response, sizeof(response)); - - // Validate the response - if ((response[0] != 0xaa) // Head - || (response[1] != 2) // Class ID - || (response[2] != 0) // Message ID - || (response[3] != 0) // Payload length (big endian) - || (response[4] != 4) - || (response[5] != command[1]) // Class ID - || (response[6] != command[2]) // Message ID - || (response[13] != 0x55)) // Tail - { - responseStatus = -1; - } - else - // Get the response status - responseStatus = (response[8] << 8) | response[7]; - - // Display the response status - if (settings.debugFirmwareUpdate && ((responseStatus != 0) || debugVerbose)) - { - switch (responseStatus) - { - default: - systemPrintf("Unspecified error\r\n"); - break; - - case -1: - systemPrintf("Invalid response received\r\n"); - break; - - case 0: - systemPrintf("Message received and executed successfully\r\n"); - break; - - case 1: - systemPrintf("Unknown error\r\n"); - break; - - case 2: - systemPrintf("CRC32 checksum error\r\n"); - break; - - case 3: - systemPrintf("Timeout\r\n"); - break; - - case 4: - systemPrintf("Unsupported message\r\n"); - break; - - case 5: - systemPrintf("Message package error\r\n"); - break; - - case 20: - systemPrintf("Firmware area erase error\r\n"); - break; - - case 21: - systemPrintf("Firmware write Flash error\r\n"); - break; - } - } - - // Get the response value (convert big endian to little endian) - return responseStatus; -} - -//---------------------------------------- -// Send a firmware packet to the LG290P -//---------------------------------------- -uint32_t dfuLg290pCmdWritePacket(uint8_t * command, - uint8_t * firmware, - uint32_t firmwareBytes, - uint32_t packetNumber, - bool debugVerbose) -{ - size_t commandLength; - size_t payloadBytes; - int retryCount; - - // Construct the command - command[0] = 0xaa; // Head - command[1] = 2; // Class ID - command[2] = 4; // Message ID - payloadBytes = 4 + firmwareBytes; - command[3] = payloadBytes >> 8; // Payload length (big endian) - command[4] = payloadBytes & 0xff; - command[5] = (uint8_t)(packetNumber >> 24); // Packet number (bigEndian) - command[6] = (uint8_t)(packetNumber >> 16); - command[7] = (uint8_t)(packetNumber >> 8); - command[8] = (uint8_t)packetNumber; - command[9 + payloadBytes + 4] = 0x55; // Tail - - // Move the payload into place - memcpy(&command[9], firmware, firmwareBytes); - - // Verify the packet length - commandLength = 1 + 1 + 1 + 2 + payloadBytes + 4 + 1; - if (commandLength > DFU_LG290P_BYTES) - { - systemPrintf("DFU_LG290P_BYTES: %d must be >= commandLength: %d\r\n", - DFU_LG290P_BYTES, commandLength); - reportFatalError("Fix LG290P_BYTES!"); - } - - // Compute the CRC - dfuLg290pInsertCrc(0, - &command[1], - commandLength - 1 - 4 - 1, - &command[commandLength - 4 - 1]); - - // Retry the command if necesary - retryCount = 0; - do - { - // Send the command to the LG290P - if ((serialGNSS->write(command, commandLength) == commandLength) - // Verify the response - && (dfuLg290pCmdResponse(command, debugVerbose) == 0)) - return firmwareBytes; - } while (retryCount++ < 3); - return -1; -} - -//---------------------------------------- -// Compute and insert the CRC -//---------------------------------------- -void dfuLg290pInsertCrc(uint32_t crcInitial, - uint8_t * start, - size_t bytes, - uint8_t * crcLocation) -{ - uint32_t crc; - - // Compute the CRC over the specified bytes - crc = crc32Compute(crcInitial, start, bytes); - - // Insert the CRC as a big endian value - crcLocation[0] = (uint8_t)(crc >> 24); - crcLocation[1] = (uint8_t)(crc >> 16); - crcLocation[2] = (uint8_t)(crc >> 8); - crcLocation[3] = (uint8_t)crc; -} - -//---------------------------------------- -// LG290P firmware open -//---------------------------------------- -bool dfuLg290pOpen(DEVICE_FIRMWARE_CTX * ctx) -{ - // Erase the previous firmware - return dfuLg290pCmdErase(ctx->_debugVerbose) - && dfuLg290pCmdFirmwareInfo(ctx->_fileBytes, ctx->_crcSave, ctx->_debugVerbose); -} - -//---------------------------------------- -// Reset the LG290P -//---------------------------------------- -bool dfuLg290pReset(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - return dfuLg290pReset(); -} - -//---------------------------------------- -// Reset the LG290P -//---------------------------------------- -bool dfuLg290pReset() -{ - // Prevent garbage caused during LG290P reset - if (serialGNSS) - serialGNSS->end(); - - // Perform a hardware reset - digitalWrite(pin_GNSS_Reset, LOW); - delay(100); - digitalWrite(pin_GNSS_Reset, HIGH); - - // Restart the serial port after the data becomes stable - delay(10); - serialGNSS->begin(460800, - SERIAL_8N1, - pin_GnssUart_RX, - pin_GnssUart_TX); - - // Attempt to synchronize with the LG290P bootloader - return dfuLg290pBootloaderSync(); -} - -//---------------------------------------- -// LG290P firmware write -//---------------------------------------- -ssize_t dfuLg290pWrite(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite) -{ - size_t commandLength; - size_t payloadBytes; - int retryCount; - uint8_t * writeBuffer; - - // Construct the command - writeBuffer = ctx->_writeBuffer; - writeBuffer[0] = 0xaa; // Head - writeBuffer[1] = 2; // Class ID - writeBuffer[2] = 4; // Message ID - payloadBytes = 4 + bytesToWrite; - writeBuffer[3] = payloadBytes >> 8; // Payload length (big endian) - writeBuffer[4] = payloadBytes & 0xff; - writeBuffer[5] = (uint8_t)(ctx->_packetNumber >> 24); // Packet number (bigEndian) - writeBuffer[6] = (uint8_t)(ctx->_packetNumber >> 16); - writeBuffer[7] = (uint8_t)(ctx->_packetNumber >> 8); - writeBuffer[8] = (uint8_t)ctx->_packetNumber; - writeBuffer[5 + payloadBytes + 4] = 0x55; // Tail - - // Move the payload into place - memcpy(&writeBuffer[9], buffer, bytesToWrite); - - // Compute the CRC - commandLength = 1 + 1 + 1 + 2 + payloadBytes + 4 + 1; - dfuLg290pInsertCrc(0, - &writeBuffer[1], - commandLength - 1 - 4 - 1, - &writeBuffer[commandLength - 4 - 1]); - - // Retry the command if necesary - retryCount = 0; - do - { - // Send the command to the LG290P - if (serialGNSS->write(writeBuffer, commandLength) == commandLength) - { - // Verify the response - if (dfuLg290pCmdResponse(writeBuffer, ctx->_debugVerbose) == 0) - { - // Account for this packet - ctx->_packetNumber += 1; - return bytesToWrite; - } - } - } while (retryCount++ < 3); - return 0; -} - -#endif // COMPILE_LG290P diff --git a/Firmware/RTK_Everywhere/Device_Update_NVM.ino b/Firmware/RTK_Everywhere/Device_Update_NVM.ino deleted file mode 100644 index 3d0394d16..000000000 --- a/Firmware/RTK_Everywhere/Device_Update_NVM.ino +++ /dev/null @@ -1,198 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update_NVM.ino - - Support routines to use NVM for input or output -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -//---------------------------------------- -// Close the NVM file -//---------------------------------------- -bool dfuNvmClose(DEVICE_FIRMWARE_CTX * ctx) -{ - ctx->_nvmFile.close(); - return true; -} - -//---------------------------------------- -// Delete the NVM file -//---------------------------------------- -void dfuNvmDelete(const char * fileName) -{ - // Delete the file - if (LittleFS.exists(fileName) && (LittleFS.remove(fileName) == false)) - systemPrintf("ERROR: Failed to delete the NVM file!\r\n"); -} - -//---------------------------------------- -// Scan the NVM for matching firmware files -//---------------------------------------- -void dfuNvmGetFiles(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int bufferIndex; - DFU_BUFFER_DATA * bufferData; - bool directory; - const char * extension; - File file; - char * fileName; - const char * namePart; - File rootDir; - - do - { - bufferData = &dfuFirmwareFileNamesNvm; - bufferIndex = bufferGetIndex(bufferData); - - // Start at the beginning of the directory - rootDir = LittleFS.open("/", FILE_READ); - if (rootDir == false) - { - systemPrintf("ERROR: Failed to open NVM root directory!\r\n"); - break; - } - - // Get the firmware file name attributes - namePart = ctx->_deviceInfo->_nameData; - extension = ctx->_deviceInfo->_extension; - - // Count available firmware files - do - { - // Expand the buffer if necessary - if (bufferData->_length < (bufferData->_offset + 256)) - { - if (bufferExpand(bufferIndex) == false) - { - // Expansion failed - systemPrintf("ERROR: Failed to expand the file name buffer!\r\n"); - - // There maybe some file names in the buffer but there - // may be more. Display the ones that were found - // and skip the rest. - break; - } - } - - // Open the next file - file = rootDir.openNextFile(); - if (!file) - break; - - // Get the file name, don't overflow the buffer - fileName = (char *)&bufferData->_address[bufferData->_offset]; - strncpy(fileName, file.name(), bufferData->_length - bufferData->_offset - 1); - - // Make sure the end of the buffer (last entry) is terminated. - bufferData->_address[bufferData->_length - 1] = 0; - - // Determine if this file is a directory - directory = file.isDirectory(); - - // Done with this file - file.close(); - - // Skip over directories - if (directory) - continue; - - // Display the file name - if (settings.debugFirmwareUpdate && ctx->_debugVerbose) - systemPrintf("File: NVM:/%s\r\n", fileName); - - // Determine if this file should be in the list - if (((namePart == nullptr) || strstr(fileName, namePart)) - && ((extension == nullptr) || strstr(fileName, extension))) - { - // Account for this file - ctx->_fileCountNvm += 1; - bufferData->_offset += strlen(fileName) + 1; - } - } while (1); - } while (0); - - // Sort the file list - if (ctx->_fileCountNvm > 0) - { - if (bufferNameSortAllocate(bufferIndex, ctx->_fileCountNvm)) - { - deviceFirmwareFileSort(bufferIndex, ctx->_fileCountNvm); - ctx->_fileCount += ctx->_fileCountNvm; - } - else - // Don't have space to sort and list the network files - ctx->_fileCountNvm = 0; - } - - // Get the SD file list - if (present.microSd && online.microSD) - deviceFirmwareStateSet(ctx, DFUS_GET_SD_FILE_LIST); - else if (ctx->_doAll) - deviceFirmwareStateSet(ctx, DFUS_DEVICE_RESET); - else - { - // Start timing out the user input - deviceFirmwareStateSet(ctx, DFUS_SELECT_FILE); - deviceFirmwareFileListMenu(ctx); - } -} - -//---------------------------------------- -// Open the NVM file -//---------------------------------------- -bool dfuNvmOpen(DEVICE_FIRMWARE_CTX * ctx, bool createFile) -{ - const char * operation; - - // Create the file - if (createFile) - { - operation = "create"; - ctx->_nvmFile = LittleFS.open(ctx->_fileName.c_str(), FILE_WRITE, true); - } - else - { - operation = "open"; - ctx->_nvmFile = LittleFS.open(ctx->_fileName.c_str(), FILE_READ, false); - } - if (ctx->_nvmFile == false) - { - systemPrintf("ERROR - Failed to %s %s in NVM!\r\n", operation, ctx->_fileName.c_str()); - return false; - } - - // Get the input file size - if (createFile == false) - { - ctx->_fileBytes = ctx->_nvmFile.size(); - if (ctx->_fileBytes == 0) - { - systemPrintf("ERROR: NVM file size is zero bytes!\r\n"); - return false; - } - } - return true; -} - -//---------------------------------------- -// Read data from the NVM file -//---------------------------------------- -ssize_t dfuNvmRead(DEVICE_FIRMWARE_CTX * ctx, - uint8_t * buffer, - size_t bytesToRead) -{ - ssize_t bytesRead; - - bytesRead = ctx->_nvmFile.read(buffer, bytesToRead); - if (bytesRead < 0) - systemPrintf("ERROR: Failed to read firmware from NVM!\r\n"); - return bytesRead; -} - -//---------------------------------------- -// Write firmware data to an NVM file -//---------------------------------------- -ssize_t dfuNvmWrite(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite) -{ - return ctx->_nvmFile.write(buffer, bytesToWrite); -} diff --git a/Firmware/RTK_Everywhere/Device_Update_Network.ino b/Firmware/RTK_Everywhere/Device_Update_Network.ino deleted file mode 100644 index 2a5e06c1f..000000000 --- a/Firmware/RTK_Everywhere/Device_Update_Network.ino +++ /dev/null @@ -1,321 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update_Network.ino - - Support routines to use the network for firmware input -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifdef COMPILE_NETWORK - -//---------------------------------------- -// Done with the network link -//---------------------------------------- -void dfuNetworkCleanup(DEVICE_FIRMWARE_CTX *ctx, - DFU_BUFFER_DATA * bufferData) -{ - // Restore access to the data buffer - deviceFirmwareBufferRestore(ctx, bufferData); - - // Free the network resources - if (ctx->_networkClient) - { - ctx->_networkClient->stop(); - ctx->_networkClient = nullptr; - } - - if (ctx->_https) - { - ctx->_https->end(); - delete(ctx->_https); - ctx->_https = nullptr; - } - - // Done with the secure client - if (ctx->_httpsClient) - { - delete ctx->_httpsClient; - ctx->_httpsClient = nullptr; - } - - // Display the transfer data - if (settings.debugFirmwareUpdate && bufferData && bufferData->_offset) - { - // Finish the header - uint32_t deltaMsec = millis() - ctx->_startMsec; - if (deltaMsec) - { - uint32_t milliseconds = deltaMsec; - uint32_t seconds = milliseconds / 1000; - milliseconds -= seconds * 1000; - uint32_t bytesPerSecond = (bufferData->_offset * 1000) / deltaMsec; - systemPrintf("Useful data: %d bytes in %d.%03d seconds, %d bytes/second\r\n", - bufferData->_offset, seconds, milliseconds, bytesPerSecond); - } - else - systemPrintf("Useful data: %d bytes\r\n", bufferData->_offset); - } -} - -//---------------------------------------- -// Request the web page containing the file specifications -//---------------------------------------- -void dfuNetworkFileListBuildUrl(DEVICE_FIRMWARE_CTX * ctx) -{ - const DEVICE_FIRMWARE_INFO * deviceInfo; - - // Build the URL - deviceInfo = ctx->_deviceInfo; - ctx->_url = deviceInfo->_server; - if (deviceInfo->_branch) - ctx->_url += deviceInfo->_branch; - if (deviceInfo->_directory) - ctx->_url += deviceInfo->_directory; - if (settings.debugFirmwareUpdate) - systemPrintf("URL: %s\r\n", ctx->_url.c_str()); - - ctx->_attemptNumber = 0; - - // Attempt the HTTP request - deviceFirmwareStateSet(ctx, DFUS_GET_HTTP_FILE_LIST_REQ); -} - -//---------------------------------------- -// Get the next network file name -//---------------------------------------- -void dfuNetworkFileListGetFileName(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - DFU_BUFFER_DATA * bufferData; - int bufferIndex; - const char * dirSuffix; - const char * extension; - char * fileName; - const char * filePrefix; - const char * fileSuffix; - const char * namePart; - size_t offset; - - do - { - // Get the delimiters - bufferData = &dfuFirmwareFileNamesNet; - bufferIndex = bufferGetIndex(bufferData); - dirSuffix = ctx->_deviceInfo->_dirSuffix; - filePrefix = ctx->_deviceInfo->_entryPrefix; - fileSuffix = ctx->_deviceInfo->_entrySuffix; - - // Expand the buffer if necessary - bufferData->_offset = ctx->_validDataBytes; - if (bufferData->_length < (bufferData->_offset + 256)) - { - if (bufferExpand(bufferIndex) == false) - { - // Expansion failed - systemPrintf("ERROR: Failed to expand the file name buffer!\r\n"); - - // There are some file names in the buffer but there - // may be more. Display the ones that were found - // and skip the rest. - break; - } - } - ctx->_buffer = bufferData->_address; - ctx->_bufferLength = bufferData->_length; - - // Read in the file name - offset = ctx->_validDataBytes; - fileName = (char *)&ctx->_buffer[offset]; - while (ctx->_networkClient->available()) - { - // Build up the file name one character at a time - ctx->_buffer[offset] = ctx->_networkClient->read(); - if (ctx->_buffer[offset] == fileSuffix[0]) - break; - offset += 1; - } - - // Get more data if necessary - if (ctx->_buffer[offset] != fileSuffix[0]) - return; - - // Zero terminate the file name string - ctx->_buffer[offset++] = 0; - - // Display the file name - if (settings.debugFirmwareUpdate && ctx->_debugVerbose) - systemPrintf("File: NET:/%s\r\n", fileName); - - // Determine if this file should be in the list - namePart = ctx->_deviceInfo->_nameData; - extension = ctx->_deviceInfo->_extension; - if (((namePart == nullptr) || strstr(fileName, namePart)) - && ((extension == nullptr) || strstr(fileName, extension))) - { - // Account for this file - ctx->_validDataBytes = offset; - ctx->_fileCountNet += 1; - } - - // Locate the next file name - if (ctx->_networkClient->findUntil(filePrefix, dirSuffix)) - return; - - // End of file list - } while (0); - - // Restore access to the data buffer - dfuNetworkCleanup(ctx, bufferData); - - // Sort the file list - if (ctx->_fileCountNet > 0) - { - if (bufferNameSortAllocate(bufferIndex, ctx->_fileCountNet)) - { - deviceFirmwareFileSort(bufferIndex, ctx->_fileCountNet); - ctx->_fileCount += ctx->_fileCountNet; - } - else - // Don't have space to sort and list the network files - ctx->_fileCountNet = 0; - } - - // Get any local files - if (ctx->_doAll) - deviceFirmwareStateSet(ctx, DFUS_SELECT_FILE); - else if (ctx->_deviceInfo->_useNvm) - deviceFirmwareStateSet(ctx, DFUS_GET_NVM_FILE_LIST); - else if (present.microSd && online.microSD) - deviceFirmwareStateSet(ctx, DFUS_GET_SD_FILE_LIST); - else - { - // Start timing out the user input - deviceFirmwareStateSet(ctx, DFUS_SELECT_FILE); - deviceFirmwareFileListMenu(ctx); - } -} - -//---------------------------------------- -// Display the error message and exit -//---------------------------------------- -void dfuNetworkFileListError(DEVICE_FIRMWARE_CTX * ctx, const char * message) -{ - DFU_BUFFER_DATA * bufferData; - - // Display the error message - systemPrintf("ERROR: %s\r\n", message); - - // Restore access to the data buffer - bufferData = &dfuFirmwareFileNamesNet; - dfuNetworkCleanup(ctx, bufferData); - - // No files available - deviceFirmwareStateSet(ctx, DFUS_GET_NVM_FILE_LIST); -} - -//---------------------------------------- -// Request the web page containing the file specifications -//---------------------------------------- -void dfuNetworkFileListHtmlRequest(DEVICE_FIRMWARE_CTX * ctx, - uint32_t currentMsec) -{ - DFU_BUFFER_DATA * bufferData; - const char * dirPrefix; - const char * dirSuffix; - const char * filePrefix; - const char * fileListPrefix; - int httpResponseCode; - - do - { - // Connect to the remote web page - ctx->_startMsec = currentMsec; - ctx->_https = new HTTPClient; - ctx->_https->begin(ctx->_url); - ctx->_https->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - - // Send HTTP GET request - httpResponseCode = ctx->_https->GET(); - - // Display the error - if (httpResponseCode != 200) - { - // Display the response - if (settings.debugFirmwareUpdate) - systemPrintf("HTTP Response code: %d (%s)\r\n", - httpResponseCode, - ctx->_https->errorToString(httpResponseCode)); - - // Done with the HTTP link - dfuNetworkCleanup(ctx, nullptr); - - // Stop with known error or too many retries - if ((httpResponseCode != -1) || (ctx->_attemptNumber++ >= 3)) - { - systemPrintf("Failed to open url: %s\r\n", ctx->_url.c_str()); - deviceFirmwareStateSet(ctx, DFUS_GET_NVM_FILE_LIST); - } - else - { - // Retry accessing the web server - } - break; - } - - // Get TCP stream - ctx->_networkClient = ctx->_https->getStreamPtr(); - - // Temporarily use the network name buffer - bufferData = &dfuFirmwareFileNamesNet; - ctx->_buffer = bufferData->_address; - ctx->_bufferLength = bufferData->_length; - ctx->_validDataBytes = 0; - - // Get the parsing strings - dirPrefix = ctx->_deviceInfo->_dirPrefix; - dirSuffix = ctx->_deviceInfo->_dirSuffix; - fileListPrefix = ctx->_deviceInfo->_dirPrefix2; - filePrefix = ctx->_deviceInfo->_entryPrefix; - - // Locate the beginning of the directory listing - if (dirPrefix && (ctx->_networkClient->find(dirPrefix) == false)) - { - dfuNetworkFileListError(ctx, "Directory prefix not found!"); - break; - } - - if (fileListPrefix && (ctx->_networkClient->find(fileListPrefix) == false)) - { - dfuNetworkFileListError(ctx, "File list prefix not found!"); - break; - } - - // Locate the first file name - if (ctx->_networkClient->findUntil(filePrefix, dirSuffix) == false) - { - dfuNetworkFileListError(ctx, "File not found!"); - break; - } - - // Get the list of files - deviceFirmwareStateSet(ctx, DFUS_GET_NETWORK_FILE_LIST); - } while (0); -} - -//---------------------------------------- -// Read firmware data from the web server -//---------------------------------------- -ssize_t dfuNetworkRead(DEVICE_FIRMWARE_CTX * ctx, - uint8_t * buffer, - size_t bytesToRead) -{ - ssize_t bytesRead; - - bytesRead = 0; - if (ctx->_networkClient->available()) - { - bytesRead = ctx->_networkClient->read(buffer, bytesToRead); - if (bytesRead < 0) - systemPrintf("ERROR: Failed to read firmware from NVM!\r\n"); - } - return bytesRead; -} - -#endif // COMPILE_NETWORK diff --git a/Firmware/RTK_Everywhere/Device_Update_SD.ino b/Firmware/RTK_Everywhere/Device_Update_SD.ino deleted file mode 100644 index 640c95f89..000000000 --- a/Firmware/RTK_Everywhere/Device_Update_SD.ino +++ /dev/null @@ -1,168 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Device_Update_SD.ino - - Support routines to use the microSD card for input or output -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -//---------------------------------------- -// Close the SD file -//---------------------------------------- -bool dfuSdClose(DEVICE_FIRMWARE_CTX * ctx) -{ - ctx->_sdFile.close(); - return true; -} - -//---------------------------------------- -// Delete the SD card file -//---------------------------------------- -void dfuSdDelete(const char * fileName) -{ - // Delete the file - if (sd->exists(fileName) && (sd->remove(fileName) == false)) - systemPrintf("ERROR: Failed to delete the SD file!\r\n"); -} - -//---------------------------------------- -// Scan the SD card for matching firmware files -//---------------------------------------- -void dfuSdGetFiles(DEVICE_FIRMWARE_CTX * ctx, uint32_t currentMsec) -{ - int bufferIndex; - DFU_BUFFER_DATA * bufferData; - SdFile dir; - const char * extension; - SdFile file; - char * fileName; - const char * namePart; - - do - { - bufferData = &dfuFirmwareFileNamesSd; - bufferIndex = bufferGetIndex(bufferData); - - // Get the firmware file name attributes - namePart = ctx->_deviceInfo->_nameData; - extension = ctx->_deviceInfo->_extension; - - // Open the root directory - dir.open("/"); // Open root - - // Count available firmware files - bufferData->_offset = 0; - while (file.openNext(&dir, O_READ)) - { - // Expand the buffer if necessary - while (bufferData->_length < (bufferData->_offset + 256)) - { - if (bufferExpand(bufferIndex) == false) - { - systemPrintf("ERROR: Failed to expand the file name buffer!\r\n"); - break; - } - } - - if (file.isFile()) - { - // Get the file name, don't overflow the buffer - fileName = (char *)&bufferData->_address[bufferData->_offset]; - file.getName(fileName, bufferData->_length - bufferData->_offset - 1); - - // Make sure the end of the buffer (last entry) is terminated. - bufferData->_address[bufferData->_length - 1] = 0; - - // Display the file name - if (settings.debugFirmwareUpdate && ctx->_debugVerbose) - systemPrintf("File: SD:/%s\r\n", fileName); - - // Determine if this file should be in the list - if (((namePart == nullptr) || strstr(fileName, namePart)) - && ((extension == nullptr) || strstr(fileName, extension))) - { - // Account for this file - ctx->_fileCountSd += 1; - bufferData->_offset += strlen(fileName) + 1; - } - } - file.close(); - } - } while (0); - - // Sort the file list - if (ctx->_fileCountSd > 0) - { - if (bufferNameSortAllocate(bufferIndex, ctx->_fileCountSd)) - { - deviceFirmwareFileSort(bufferIndex, ctx->_fileCountSd); - ctx->_fileCount += ctx->_fileCountSd; - } - else - // Don't have space to sort and list the network files - ctx->_fileCountSd = 0; - } - - // Select the firmware file - deviceFirmwareStateSet(ctx, DFUS_SELECT_FILE); - deviceFirmwareFileListMenu(ctx); -} - -//---------------------------------------- -// Create an SD file for the firmware -//---------------------------------------- -bool dfuSdOpen(DEVICE_FIRMWARE_CTX * ctx, bool createFile) -{ - if (createFile) - { - // Create the file - if (ctx->_sdFile.open(ctx->_fileName.c_str(), O_WRONLY | O_CREAT | O_TRUNC) == false) - { - systemPrintf("ERROR - Failed to create %s on the microSD card!\r\n", - ctx->_fileName.c_str()); - return false; - } - } - else - { - // Open an existing file - if (ctx->_sdFile.open(ctx->_fileName.c_str(), O_RDONLY) == false) - { - systemPrintf("ERROR - Failed to open %s on the microSD card!\r\n", - ctx->_fileName.c_str()); - return false; - } - - // Get the input file size - ctx->_fileBytes = ctx->_sdFile.size(); - if (ctx->_fileBytes == 0) - { - systemPrintf("ERROR: SD file size is zero bytes!\r\n"); - return false; - } - } - return true; -} - -//---------------------------------------- -// Read data from the SD file -//---------------------------------------- -ssize_t dfuSdRead(DEVICE_FIRMWARE_CTX * ctx, - uint8_t * buffer, - size_t bytesToRead) -{ - ssize_t bytesRead; - - bytesRead = ctx->_sdFile.read(buffer, bytesToRead); - if (bytesRead < 0) - systemPrintf("ERROR: Failed to read firmware from SD card!\r\n"); - return bytesRead; -} - -//---------------------------------------- -// Copy firmware into the file -//---------------------------------------- -ssize_t dfuSdWrite(DEVICE_FIRMWARE_CTX * ctx, - const uint8_t * buffer, - size_t bytesToWrite) -{ - return ctx->_sdFile.write(buffer, bytesToWrite); -} diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index c54d1a030..72f8d2297 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -661,6 +661,8 @@ unsigned long minSplashFor = 100; // Display SparkFun Logo for at least 1/10 of int binCount; const int maxBinFiles = 10; char binFileNames[maxBinFiles][50]; +const char *forceFirmwareFileName = + "RTK_Everywhere_Firmware_Force.bin"; // File that will be loaded at startup regardless of user input int binBytesLastUpdate; // Allows websocket notification to be sent every 100k bytes //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -864,12 +866,6 @@ char *latestEASessionData; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// Global variables -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -#include "Device_Update.h" - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Global variables //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- uint8_t wifiMACAddress[6]; // Display this address in the system menu @@ -1365,9 +1361,6 @@ void setup() DMW_b("beginPsram"); beginPsram(); // Initialize PSRAM (if available). Needs to occur before beginGnssUart and other malloc users. - DMW_b("beginBuffers"); - beginBuffers(); // Allocate permanent buffers from PSRAM - DMW_b("beginMux"); beginMux(); // Must come before I2C activity to avoid external devices from corrupting the bus. See issue 474 // https://github.com/sparkfun/SparkFun_RTK_Firmware/issues/474 diff --git a/Firmware/RTK_Everywhere/support.ino b/Firmware/RTK_Everywhere/support.ino index 2c7d5e9f7..c2886a501 100644 --- a/Firmware/RTK_Everywhere/support.ino +++ b/Firmware/RTK_Everywhere/support.ino @@ -1332,196 +1332,6 @@ const char *printMinuteSecondFromMilliseconds(uint32_t msToConvert) return (const char *)theTime; } -//---------------------------------------- -// Dynamically allocate a buffer -//---------------------------------------- -bool bufferDynamicallyAllocate(DFU_BUFFER_DATA *bufferData) -{ - const char *description; - bool dynamicAllocation; - size_t length; - - // Determine if the buffer needs to be dynamically allocated - dynamicAllocation = (bufferData->_address == nullptr); - if (dynamicAllocation) - { - // Attempt to allocate the buffer - description = bufferGetDescription(bufferData); - length = bufferGetLength(bufferData); - bufferData->_address = (uint8_t *)rtkMalloc(length, description); - if (bufferData->_address == nullptr) - systemPrintf("ERROR: Failed to allocate the '%s, %d bytes' buffer!\r\n", - description, length); - else - bufferData->_length = length; - } - return dynamicAllocation; -} - -//---------------------------------------- -// Expand an existing buffer -//---------------------------------------- -bool bufferExpand(int bufferIndex) -{ - // Locate the buffer data - DFU_BUFFER_DATA *bufferData = dfuBufferInfo[bufferIndex]._bufferData; - uint8_t *newBuffer; - size_t newLength; - - // Determine the new buffer size - newLength = bufferData->_length + 2048; - - // Allocate the new buffer - newBuffer = (uint8_t *)rtkMalloc(newLength, dfuBufferInfo[bufferIndex]._description); - if (newBuffer == nullptr) - { - systemPrintf("ERROR: Failed to allocate the new buffer of %d bytes!\r\n", newLength); - return false; - } - - // Copy the existing file names into the new buffer - memcpy(newBuffer, bufferData->_address, bufferData->_offset); - - // Free the old buffer - free((void *)bufferData->_address); - - // Switch to using the new buffer - bufferData->_address = newBuffer; - bufferData->_length = newLength; - - // Zero terminate any strings in the new buffer - memset(&newBuffer[bufferData->_offset], 0, bufferData->_length - bufferData->_offset); - return true; -} - -//---------------------------------------- -// Free a dynamically allocated buffer -//---------------------------------------- -void bufferFree(DFU_BUFFER_DATA *bufferData) -{ - const char *description; - - // Free the buffer - if (bufferData->_address) - { - description = bufferGetDescription(bufferData); - rtkFree(bufferData->_address, description); - bufferData->_address = nullptr; - } -} - -//---------------------------------------- -// Get the buffer description -//---------------------------------------- -const char *bufferGetDescription(DFU_BUFFER_DATA *bufferData) -{ - // Walk the list of buffers - for (int index = 0; index < dfuBufferInfoCount; index++) - { - if (bufferData == dfuBufferInfo[index]._bufferData) - return dfuBufferInfo[index]._description; - } - - // Buffer not found - return nullptr; -} - -//---------------------------------------- -// Get the buffer index -//---------------------------------------- -int bufferGetIndex(DFU_BUFFER_DATA *bufferData) -{ - // Walk the list of buffers - for (int index = 0; index < dfuBufferInfoCount; index++) - { - if (bufferData == dfuBufferInfo[index]._bufferData) - return index; - } - - // Buffer not found - return -1; -} - -//---------------------------------------- -// Get the buffer length -//---------------------------------------- -size_t bufferGetLength(DFU_BUFFER_DATA *bufferData) -{ - // Walk the list of buffers - for (int index = 0; index < dfuBufferInfoCount; index++) - { - if (bufferData == dfuBufferInfo[index]._bufferData) - return dfuBufferInfo[index]._sizeInBytes; - } - - // Buffer not found - return 0; -} - -//---------------------------------------- -// Allocate the name and sort arrays, return true if successful -//---------------------------------------- -bool bufferNameSortAllocate(int bufferIndex, int fileCount) -{ - DFU_BUFFER_DATA *bufferData = dfuBufferInfo[bufferIndex]._bufferData; - char *fileName; - size_t length; - - // Allocate the sortArray - length = sizeof(*bufferData->_sortArray) * fileCount; - bufferData->_sortArray = (int *)rtkMalloc(length, "Sort Array"); - if (bufferData->_sortArray == nullptr) - systemPrintf("ERROR: Failed to allocate sortArray, %d bytes!\r\n", length); - else - { - // Allocate the nameArray - length = sizeof(*bufferData->_nameArray) * fileCount; - bufferData->_nameArray = (char **)rtkMalloc(length, "Name Array"); - if (bufferData->_nameArray == nullptr) - { - bufferNameSortFree(bufferIndex); - systemPrintf("ERROR: Failed to allocate nameArray, %d bytes!\r\n", length); - } - else - { - // Initialize the sortArray - for (int index = 0; index < fileCount; index++) - bufferData->_sortArray[index] = index; - - // Initialize the nameArray - fileName = (char *)bufferData->_address; - for (int index = 0; index < fileCount; index++) - { - bufferData->_nameArray[index] = fileName; - fileName += strlen(fileName) + 1; - } - } - } - return (bufferData->_nameArray != nullptr); -} - -//---------------------------------------- -// Free the arrays -//---------------------------------------- -void bufferNameSortFree(int bufferIndex) -{ - DFU_BUFFER_DATA *bufferData = dfuBufferInfo[bufferIndex]._bufferData; - - // Free nameArray - if (bufferData->_nameArray != nullptr) - { - free(bufferData->_nameArray); - bufferData->_nameArray = nullptr; - } - - // Free sortArray - if (bufferData->_sortArray != nullptr) - { - free(bufferData->_sortArray); - bufferData->_sortArray = nullptr; - } -} - //---------------------------------------- // Configure UART2 serial port //----------------------------------------