LittleFS Corruption Issue Report – nRF5340 (External QSPI Flash)
1. Introduction
This document outlines a filesystem corruption issue encountered while using LittleFS on an external QSPI flash (64 MiB) with the nRF5340 platform (Zephyr RTOS). The issue occurs during high-volume file creation within a single directory and results in filesystem corruption and, in some cases, complete flash erasure upon reboot.
2. Error Description
Observed Logs
<err> littlefs: lfs.c:1374: Corrupted dir pair at {0x1, 0x0}
<err> fs: file open error (-14)
File Open Err: -14
Interpretation
-
Error code
-14indicates filesystem inconsistency. -
“Corrupted dir pair” suggests failure in LittleFS metadata integrity (directory structure).
3. Hardware Configuration
| Component | Specification |
|---|---|
| MCU | nRF5340 |
| External Flash | MX25L51245G |
| Interface | QSPI |
| Capacity | 64 MiB (67,108,864 bytes) |
4. Device Tree Configuration
4.1 LittleFS Mount Configuration
fstab {
compatible = "zephyr,fstab";
lfs1: lfs1 {
compatible = "zephyr,fstab,littlefs";
mount-point = "/external";
partition = <&external_partition>;
read-size = <16>;
prog-size = <16>;
cache-size = <64>;
lookahead-size = <32>;
block-cycles = <0>;
};
};
4.2 QSPI Flash Configuration
&qspi {
pinctrl-0 = <&qspi_default>;
pinctrl-1 = <&qspi_sleep>;
pinctrl-names = "default", "sleep";
mx25l512: mx25l51245g@0 {
compatible = "nordic,qspi-nor";
reg = <0>;
writeoc = "pp4io";
readoc = "read4io";
sck-frequency = <8000000>;
jedec-id = [c2 20 1A];
size = <0x20000000>; // 64 MiB
has-dpd;
t-enter-dpd = <10000>;
t-exit-dpd = <30000>;
external_partition: partition {
label = "external";
};
};
};
5. Project Configuration (prj.conf)
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_SETTINGS=y
CONFIG_IMG_MANAGER=y
CONFIG_STREAM_FLASH=y
CONFIG_NET_BUF=y
CONFIG_ZCBOR=y
CONFIG_JSON_LIBRARY=y
CONFIG_THREAD_NAME=y
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_HEAP_MEM_POOL_SIZE=20480
CONFIG_MBEDTLS_HEAP_SIZE=16384
CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192
CONFIG_BT_RX_STACK_SIZE=12288
CONFIG_BT_HCI_TX_STACK_SIZE=8192
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=14288
6. Observed Behavior
6.1 Scenario A – Single Directory File Creation
-
~2500–3000 files written in a single directory
-
Each file size ≈ 1.1 KB
-
Write operation appears successful
-
Upon reboot:
-
Filesystem becomes corrupted
-
Entire external flash is erased/reset
-
6.2 Scenario B – Mixed File Operations
-
Combination of:
-
File creation (Method 1)
-
File update with seek (Method 2)
-
-
Failure occurs around ~1500 files
-
Same corruption error observed
7. File Write Implementations
7.1 Method 1 – File Creation
int __fs_write_bytes_to_file(struct fs_mount_t *fs_mount_point,
const char *abs_path,
const char *data,
int len,
int *write_count)
{
int rc;
struct fs_file_t file;
file.mp = fs_external_mount_point;
file.flags = FS_O_CREATE;
char fname[MAX_PATH_LEN];
fs_file_t_init(&file);
snprintf(fname, sizeof(fname), "%s/%s",
fs_mount_point->mnt_point, abs_path);
rc = fs_open(&file, fname, FS_O_CREATE | FS_O_WRITE);
if (rc < 0) {
printf("fs_open error (%d)", rc);
return rc;
}
if (rc != 0) {
printf("fs_seek error (%d)", rc);
return rc;
}
rc = fs_write(&file, data, len);
fs_sync(&file);
fs_close(&file);
printf("File write > %s, size = %d, result = %d\n",
fname, len, rc);
*write_count = rc;
return rc < 0;
}
7.2 Method 2 – File Update with Seek
int8_t fs_write_current_ble_session_command_guids_data_on_file(uint8_t *data_to_write,
uint8_t len)
{
int8_t rc;
struct fs_file_t file;
fs_file_t_init(&file);
char fname[MAX_PATH_LEN];
snprintf(fname, sizeof(fname), "%s/%s",
fs_external_mount_point->mnt_point,
TRANSACTIONS_BLE_SESSION_DATA_FILE);
rc = fs_open(&file, fname, FS_O_CREATE | FS_O_WRITE);
if (rc < 0) {
return -1;
}
int32_t location_index =
g_current_ble_session_transaction_counter * len;
rc = fs_seek(&file, location_index, FS_SEEK_SET);
if (rc != 0) {
return rc;
}
rc = fs_write(&file, data_to_write, len);
if (rc != len) {
// Log partial write
}
fs_close(&file);
g_current_ble_session_transaction_counter++;
if (g_current_ble_session_transaction_counter >=
MAX_CURRENT_SESSION_TRANSACTIONS_COUNT) {
g_current_ble_session_transaction_counter = 0;
}
return rc;
}
8. Key Observations
-
Filesystem corruption occurs under high file count in a single directory
-
Failure threshold:
-
~3000 files (single operation)
-
~1500 files (mixed operations)
-
-
Starts giving -14 Error on runtime and File corruption manifests:
-
On reboot
-
During subsequent file operations
-
-
Entire flash partition may be erased after corruption
9. Summary
| Parameter | Value |
|---|---|
| Flash Size | 64 MiB |
| File Size | ~1.1 KB |
| Max Files (Observed) | 1500–3000 |
| Failure Type | Directory corruption |
| Error Code | -14 |
| Trigger Condition | High file count + ops |
10. Conclusion
The issue is reproducible under conditions involving:
-
High file count within a single directory
-
Frequent file creation and modification
-
Combined write patterns across multiple files
The corruption originates from instability in LittleFS directory metadata under heavy usage patterns. The problem is not directly related to flash capacity but rather to filesystem behavior under scaling conditions.