Skip to content
9 changes: 5 additions & 4 deletions src/FSCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ bool renameFile(const char *pathFrom, const char *pathTo)
{
#ifdef FSCom

#ifdef ARCH_ESP32
#if defined(ARCH_ESP32) || defined(ARCH_STM32WL)
// take SPI Lock
spiLock->lock();
// rename was fixed for ESP32 IDF LittleFS in April
// ESP32: rename was fixed for IDF LittleFS in April
// STM32WL: STM32_LittleFS::rename() calls lfs_rename() which is atomic
bool result = FSCom.rename(pathFrom, pathTo);
spiLock->unlock();
return result;
Expand Down Expand Up @@ -271,8 +272,8 @@ void rmDir(const char *dirname)

#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
listDir(dirname, 10, true);
#elif defined(ARCH_NRF52)
// nRF52 implementation of LittleFS has a recursive delete function
#elif defined(ARCH_NRF52) || defined(ARCH_STM32WL)
// nRF52 and STM32WL implementations of LittleFS have a recursive delete function
FSCom.rmdir_r(dirname);
#endif

Expand Down
5 changes: 4 additions & 1 deletion src/mesh/NodeDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,8 @@ bool NodeDB::saveToDisk(int saveWhat)

if (!success) {
LOG_ERROR("Failed to save to disk, retrying");
#ifdef ARCH_NRF52 // @geeksville is not ready yet to say we should do this on other platforms. See bug #4184 discussion
#if defined(ARCH_NRF52) || \
defined(ARCH_STM32WL) // @geeksville is not ready yet to say we should do this on other platforms. See bug #4184 discussion
spiLock->lock();
FSCom.format();
spiLock->unlock();
Expand Down Expand Up @@ -2189,6 +2190,7 @@ bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_pub
}
#endif

#if !MESHTASTIC_EXCLUDE_BACKUP
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
{
bool success = false;
Expand Down Expand Up @@ -2276,6 +2278,7 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
#endif
return success;
}
#endif // !MESHTASTIC_EXCLUDE_BACKUP

/// Record an error that should be reported via analytics
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
Expand Down
10 changes: 8 additions & 2 deletions src/mesh/NodeDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ static constexpr const char *configFileName = "/prefs/config.proto";
static constexpr const char *uiconfigFileName = "/prefs/uiconfig.proto";
static constexpr const char *moduleConfigFileName = "/prefs/module.proto";
static constexpr const char *channelFileName = "/prefs/channels.proto";
#if !MESHTASTIC_EXCLUDE_BACKUP
static constexpr const char *backupFileName = "/backups/backup.proto";
#endif

/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
Expand Down Expand Up @@ -316,9 +318,11 @@ class NodeDB
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
#endif

#if !MESHTASTIC_EXCLUDE_BACKUP
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
#endif

/// Notify observers of changes to the DB
void notifyObservers(bool forceUpdate = false)
Expand All @@ -331,9 +335,11 @@ class NodeDB
private:
bool duplicateWarned = false;
bool localPositionUpdatedSinceBoot = false;
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
#if !MESHTASTIC_EXCLUDE_BACKUP
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
uint32_t lastSort = 0; // When last sorted the nodeDB
#endif
uint32_t lastSort = 0; // When last sorted the nodeDB
/// Find a node in our DB, create an empty NodeInfoLite if missing
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);

Expand Down
2 changes: 2 additions & 0 deletions src/modules/AdminModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
#endif
break;
}
#if !MESHTASTIC_EXCLUDE_BACKUP
case meshtastic_AdminMessage_backup_preferences_tag: {
LOG_INFO("Client requesting to backup preferences");
if (nodeDB->backupPreferences(r->backup_preferences)) {
Expand Down Expand Up @@ -535,6 +536,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
#endif
break;
}
#endif // !MESHTASTIC_EXCLUDE_BACKUP
case meshtastic_AdminMessage_send_input_event_tag: {
LOG_INFO("Client requesting to send input event");
handleSendInputEvent(r->send_input_event);
Expand Down
34 changes: 21 additions & 13 deletions src/platform/stm32wl/LittleFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,31 +83,36 @@ static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, l

LFS_UNUSED(c);

// STM32WL HAL minimum write unit is one 64-bit doubleword (8 bytes)
if (size % 8 != 0) {
return LFS_ERR_INVAL;
}

_LFS_DBG("Programming %d bytes/%d doublewords at address 0x%08x/block %d, offset %d.", size, dw_count, address, block, off);

// Validate the full write range before touching flash
lfs_block_t addr_end = address + (lfs_block_t)(dw_count * 8) - 1;
if ((address < LFS_FLASH_ADDR_BASE) || (addr_end > LFS_FLASH_ADDR_END)) {
_LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x-0x%08x.\n", address, addr_end);
return LFS_ERR_INVAL;
}

if (HAL_FLASH_Unlock() != HAL_OK) {
return LFS_ERR_IO;
}
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
for (uint32_t i = 0; i < dw_count; i++) {
if ((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) {
_LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x.\n", address);
HAL_FLASH_Lock();
return LFS_ERR_INVAL;
}
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *bufp);
if (hal_rc != HAL_OK) {
/* Error occurred while writing data in Flash memory.
* User can add here some code to deal with this error.
*/
_LFS_DBG("Program error at (0x%08x), 0x%X, error: 0x%08x\n", address, hal_rc, HAL_FLASH_GetError());
break; // Do not continue programming after a failure
}
address += 8;
bufp += 1;
}
if (HAL_FLASH_Lock() != HAL_OK) {
return LFS_ERR_IO;
}
HAL_FLASH_Lock();

return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO;
}

// Erase a block. A block must be erased before being programmed.
Expand All @@ -130,7 +135,10 @@ static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
/* calculate the absolute page, i.e. what the ST wants */
EraseInitStruct.Page = (address - STM32WL_FLASH_BASE) / STM32WL_PAGE_SIZE;
_LFS_DBG("Erasing block %d at 0x%08x... ", block, address);
HAL_FLASH_Unlock();
if (HAL_FLASH_Unlock() != HAL_OK) {
return LFS_ERR_IO;
}
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
HAL_FLASH_Lock();

Expand Down
1 change: 1 addition & 0 deletions variants/stm32/stm32.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ build_flags =
-DMESHTASTIC_EXCLUDE_BLUETOOTH=1
-DMESHTASTIC_EXCLUDE_WIFI=1
-DMESHTASTIC_EXCLUDE_TZ=1 ; Exclude TZ to save some flash space.
-DMESHTASTIC_EXCLUDE_BACKUP=1 ; Backup preferences require 2 flash blocks (4 KB); not useful on a flash-constrained node.
-DSERIAL_RX_BUFFER_SIZE=256 ; For GPS - the default of 64 is too small.
-DHAS_SCREEN=0 ; Always disable screen for STM32, it is not supported.
;-DPIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF ; Enable this if enabling debugg logging. It is REQUIRED for at least traceroute debug prints - without it the length returned by printf ends up uninitialized.
Expand Down