mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-01 02:09:57 +00:00
Reboot before formatting LittleFS (#5900)
Some checks are pending
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32-s3 (push) Blocked by required conditions
CI / build-esp32-c3 (push) Blocked by required conditions
CI / build-esp32-c6 (push) Blocked by required conditions
CI / build-nrf52 (push) Blocked by required conditions
CI / build-rpi2040 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / package-raspbian (push) Waiting to run
CI / package-raspbian-armv7l (push) Waiting to run
CI / package-native (push) Waiting to run
CI / build-debian-src (push) Waiting to run
CI / test-native (push) Waiting to run
CI / build-docker (push) Waiting to run
CI / after-checks (push) Blocked by required conditions
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
Flawfinder Scan / Flawfinder (push) Waiting to run
Some checks are pending
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32-s3 (push) Blocked by required conditions
CI / build-esp32-c3 (push) Blocked by required conditions
CI / build-esp32-c6 (push) Blocked by required conditions
CI / build-nrf52 (push) Blocked by required conditions
CI / build-rpi2040 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / package-raspbian (push) Waiting to run
CI / package-raspbian-armv7l (push) Waiting to run
CI / package-native (push) Waiting to run
CI / build-debian-src (push) Waiting to run
CI / test-native (push) Waiting to run
CI / build-docker (push) Waiting to run
CI / after-checks (push) Blocked by required conditions
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
Flawfinder Scan / Flawfinder (push) Waiting to run
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
parent
0f981153eb
commit
c4fcbad372
@ -49,24 +49,6 @@ void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool lfs_assert_failed =
|
|
||||||
false; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our modified lfs_util.h)
|
|
||||||
|
|
||||||
extern "C" void lfs_assert(const char *reason)
|
|
||||||
{
|
|
||||||
LOG_ERROR("LFS assert: %s", reason);
|
|
||||||
lfs_assert_failed = true;
|
|
||||||
|
|
||||||
#ifndef ARCH_PORTDUINO
|
|
||||||
#ifdef FSCom
|
|
||||||
// CORRUPTED FILESYSTEM. This causes bootloop so
|
|
||||||
// might as well try formatting now.
|
|
||||||
LOG_ERROR("Trying FSCom.format()");
|
|
||||||
FSCom.format();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copies a file from one location to another.
|
* @brief Copies a file from one location to another.
|
||||||
*
|
*
|
||||||
@ -348,10 +330,16 @@ void rmDir(const char *dirname)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some platforms (nrf52) might need to do an extra step before FSBegin().
|
||||||
|
*/
|
||||||
|
__attribute__((weak, noinline)) void preFSBegin() {}
|
||||||
|
|
||||||
void fsInit()
|
void fsInit()
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
spiLock->lock();
|
concurrency::LockGuard g(spiLock);
|
||||||
|
preFSBegin();
|
||||||
if (!FSBegin()) {
|
if (!FSBegin()) {
|
||||||
LOG_ERROR("Filesystem mount failed");
|
LOG_ERROR("Filesystem mount failed");
|
||||||
// assert(0); This auto-formats the partition, so no need to fail here.
|
// assert(0); This auto-formats the partition, so no need to fail here.
|
||||||
@ -362,7 +350,6 @@ void fsInit()
|
|||||||
LOG_DEBUG("Filesystem files:");
|
LOG_DEBUG("Filesystem files:");
|
||||||
#endif
|
#endif
|
||||||
listDir("/", 10);
|
listDir("/", 10);
|
||||||
spiLock->unlock();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,4 +387,4 @@ void setupSDCard()
|
|||||||
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
||||||
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
@ -57,7 +57,4 @@ bool renameFile(const char *pathFrom, const char *pathTo);
|
|||||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
||||||
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
||||||
void rmDir(const char *dirname);
|
void rmDir(const char *dirname);
|
||||||
void setupSDCard();
|
void setupSDCard();
|
||||||
|
|
||||||
extern bool lfs_assert_failed; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our
|
|
||||||
// modified lfs_util.h)
|
|
@ -8,7 +8,6 @@ static File openFile(const char *filename, bool fullAtomic)
|
|||||||
concurrency::LockGuard g(spiLock);
|
concurrency::LockGuard g(spiLock);
|
||||||
LOG_DEBUG("Opening %s, fullAtomic=%d", filename, fullAtomic);
|
LOG_DEBUG("Opening %s, fullAtomic=%d", filename, fullAtomic);
|
||||||
#ifdef ARCH_NRF52
|
#ifdef ARCH_NRF52
|
||||||
lfs_assert_failed = false;
|
|
||||||
File file = FSCom.open(filename, FILE_O_WRITE);
|
File file = FSCom.open(filename, FILE_O_WRITE);
|
||||||
file.seek(0);
|
file.seek(0);
|
||||||
return file;
|
return file;
|
||||||
@ -20,7 +19,6 @@ static File openFile(const char *filename, bool fullAtomic)
|
|||||||
filenameTmp += ".tmp";
|
filenameTmp += ".tmp";
|
||||||
|
|
||||||
// clear any previous LFS errors
|
// clear any previous LFS errors
|
||||||
lfs_assert_failed = false;
|
|
||||||
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
|
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +94,6 @@ bool SafeFile::close()
|
|||||||
bool SafeFile::testReadback()
|
bool SafeFile::testReadback()
|
||||||
{
|
{
|
||||||
concurrency::LockGuard g(spiLock);
|
concurrency::LockGuard g(spiLock);
|
||||||
bool lfs_failed = lfs_assert_failed;
|
|
||||||
lfs_assert_failed = false;
|
|
||||||
|
|
||||||
String filenameTmp = filename;
|
String filenameTmp = filename;
|
||||||
filenameTmp += ".tmp";
|
filenameTmp += ".tmp";
|
||||||
@ -119,7 +115,7 @@ bool SafeFile::testReadback()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !lfs_failed;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,6 +1,7 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Adafruit_TinyUSB.h>
|
#include <Adafruit_TinyUSB.h>
|
||||||
#include <Adafruit_nRFCrypto.h>
|
#include <Adafruit_nRFCrypto.h>
|
||||||
|
#include <InternalFileSystem.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -130,6 +131,54 @@ int printf(const char *fmt, ...)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr uint8_t NRF52_MAGIC_LFS_IS_CORRUPT = 0xF5;
|
||||||
|
constexpr uint32_t MULTIPLE_CORRUPTION_DELAY_MILLIS = 20 * 60 * 1000;
|
||||||
|
static unsigned long millis_until_formatting_again = 0;
|
||||||
|
|
||||||
|
// Report the critical error from loop(), giving a chance for the screen to be initialized first.
|
||||||
|
inline void reportLittleFSCorruptionOnce()
|
||||||
|
{
|
||||||
|
static bool report_corruption = !!millis_until_formatting_again;
|
||||||
|
if (report_corruption) {
|
||||||
|
report_corruption = false;
|
||||||
|
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void preFSBegin()
|
||||||
|
{
|
||||||
|
// The GPREGRET register keeps its value across warm boots. Check that this is a warm boot and, if GPREGRET
|
||||||
|
// is set to NRF52_MAGIC_LFS_IS_CORRUPT, format LittleFS.
|
||||||
|
if (!(NRF_POWER->RESETREAS == 0 && NRF_POWER->GPREGRET == NRF52_MAGIC_LFS_IS_CORRUPT))
|
||||||
|
return;
|
||||||
|
NRF_POWER->GPREGRET = 0;
|
||||||
|
millis_until_formatting_again = millis() + MULTIPLE_CORRUPTION_DELAY_MILLIS;
|
||||||
|
InternalFS.format();
|
||||||
|
LOG_INFO("LittleFS format complete; restoring default settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void lfs_assert(const char *reason)
|
||||||
|
{
|
||||||
|
LOG_ERROR("LittleFS corruption detected: %s", reason);
|
||||||
|
if (millis_until_formatting_again > millis()) {
|
||||||
|
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE);
|
||||||
|
const long millis_remain = millis_until_formatting_again - millis();
|
||||||
|
LOG_WARN("Pausing %d seconds to avoid wear on flash storage", millis_remain / 1000);
|
||||||
|
delay(millis_remain);
|
||||||
|
}
|
||||||
|
LOG_INFO("Rebooting to format LittleFS");
|
||||||
|
delay(500); // Give the serial port a bit of time to output that last message.
|
||||||
|
// Try setting GPREGRET with the SoftDevice first. If that fails (perhaps because the SD hasn't been initialize yet) then set
|
||||||
|
// NRF_POWER->GPREGRET directly.
|
||||||
|
if (!(sd_power_gpregret_clr(0, 0xFF) == NRF_SUCCESS && sd_power_gpregret_set(0, NRF52_MAGIC_LFS_IS_CORRUPT) == NRF_SUCCESS)) {
|
||||||
|
NRF_POWER->GPREGRET = NRF52_MAGIC_LFS_IS_CORRUPT;
|
||||||
|
}
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
void checkSDEvents()
|
void checkSDEvents()
|
||||||
{
|
{
|
||||||
if (useSoftDevice) {
|
if (useSoftDevice) {
|
||||||
@ -154,6 +203,7 @@ void checkSDEvents()
|
|||||||
void nrf52Loop()
|
void nrf52Loop()
|
||||||
{
|
{
|
||||||
checkSDEvents();
|
checkSDEvents();
|
||||||
|
reportLittleFSCorruptionOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SEMIHOSTING
|
#ifdef USE_SEMIHOSTING
|
||||||
@ -309,4 +359,4 @@ void enterDfuMode()
|
|||||||
#else
|
#else
|
||||||
enterUf2Dfu();
|
enterUf2Dfu();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user