Description
When using the example for HTTPUpdate->HttpUpdate example I get the following error reported from the callbacks:
CALLBACK: HTTP update process started
CALLBACK: HTTP update fatal error code 0
HTTP_UPDATE_FAILD Error (0):
I assumed that a "fatal" error should have a valid reason other than 0 - UPDATE_ERROR_OK.
Turned on debug, saw that data was arriving and written to the underlying LittleFS file of "firmware.bin". Eventually found a cryptic message of lfs_write reported a -28. -28 in the lfs.h file is no space remaining.
In the Updater.cpp file I find the following call to LittleFS write
bool UpdaterClass::_writeBuffer() {
if (_command == U_FLASH) {
if (_bufferLen != _fp.write(_buffer, _bufferLen)) {
return false;
}
} else {
_fp.write is returning a value of 0, a value != to _bufferLen and takes the return false path . Returning false ripples up to a the failed download message but not reporting source of the error. Noticing similar checks for not sufficient flash space I suggest the following fix.
bool UpdaterClass::_writeBuffer() {
if (_command == U_FLASH) {
if (_bufferLen != _fp.write(_buffer, _bufferLen)) {
_setError(UPDATE_ERROR_SPACE);
return false;
}
} else {
and the expected error message:
CALLBACK: HTTP update process at 49152 of 577508 bytes...
_fp.write returns 4096
CALLBACK: HTTP update process at 53248 of 577508 bytes...
_fp.write returns 0
CALLBACK: HTTP update fatal error code 4
HTTP_UPDATE_FAILD Error (4): Update error: ERROR[4]: Not Enough Space
To duplicate this problem one must send a sufficiently large update file that is bigger than the configured flash size. I set it to FS: 64kb.
In the process of verification of this fix, I configured the flash size for (no FS) and I get the same problem from a different location in the code also from Updater.cpp:
if (command == U_FLASH) {
LittleFS.begin();
_fp = LittleFS.open("firmware.bin", "w+");
if (!_fp) {
#ifdef DEBUG_UPDATER
DEBUG_UPDATER.println(F("[begin] unable to create file"));
#endif
return false;
}
updateStartAddress = 0; // Not used
} else if (command == U_FS) {
if (&_FS_start + size > &_FS_end) {
_setError(UPDATE_ERROR_SPACE);
return false;
}
which fails the file open test, optionally prints the DEBUG_UPDATER message and returns false. Same incorrect error code is reported. Adding the _setError(UPDATE_ERROR_SPACE); function call after the check for (!fp) fixes this error path too.
Unlike the ESP32 partition table, the pico does not currently have the ability to have separate spiffs and littlefs flash locations. Both U_FLASH and U_FS use the same flash memory locations. I think I saw in another discussion a mention that 2MB is barely sufficient as it is. Based on this assumption for the pico, the same test comparing FS_start + size > _FS_end test could be applied before attempting even the LittleFS.begin for the earliest possible error. For future proofing and the possibility of larger flash sizes and the addition of a partition table similar to ESP32, it might not be the best idea to add this particular test,
I've tested the following snippet with correct behaviour with all flash size variations.
if (command == U_FLASH) {
+ if (&_FS_start + size > &_FS_end) {
+ _setError(UPDATE_ERROR_SPACE);
+ return false;
+ }
LittleFS.begin();
_fp = LittleFS.open("firmware.bin", "w+");
if (!_fp) {
#ifdef DEBUG_UPDATER
DEBUG_UPDATER.println(F("[begin] unable to create file"));
#endif
+ _setError(UPDATE_ERROR_SPACE);
return false;
}
updateStartAddress = 0; // Not used
} else if (command == U_FS) {
if (&_FS_start + size > &_FS_end) {
_setError(UPDATE_ERROR_SPACE);
return false;
}