You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSP430上LittleFS适配FRAM内存遇超级块不可写问题

问题

在MSP430微控制器的外部FRAM内存上适配LittleFS时,格式化阶段出现超级块不可写错误(错误码-28,提示无可用空间)。单独测试FRAM读写操作正常,但LittleFS初始化失败。

已实现的块接口代码如下:

lfs_t lfs;
lfs_file_t file;

#pragma PERSISTENT(read_cache)
static uint8_t read_cache[512] = {0};  

#pragma PERSISTENT(write_cache)
static uint8_t write_cache[512] = {0};      

#pragma PERSISTENT(lookahead_buffer)
static uint8_t lookahead_buffer[64] = {0};  

const struct lfs_config cfg = {
    // block device operations
    .read  = block_device_read,
    .prog  = block_device_write,
    .erase = block_device_erase,
    .sync  = block_device_sync,

    // block device configuration
    .read_size = 512,
    .prog_size = 512,
    .block_size = 512,
    .block_count = 6144,
    .cache_size = 512,
    .lookahead_size = 64,
    .block_cycles = -1,

    // buffers
    .read_buffer = read_cache,  
    .prog_buffer = write_cache,  
    .lookahead_buffer = lookahead_buffer,
};

// Erase function (Not needed for FRAM, just return 0)
int block_device_erase(const struct lfs_config *c, lfs_block_t block) {
    return 0;
}

// Sync function (Not needed for FRAM, just return 0)
int block_device_sync(const struct lfs_config *c) {
    return 0;
}

int block_device_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, uint8_t *buffer, lfs_size_t size) {
    // Convert LittleFS block and offset to FRAM address
    uint32_t addr = (block * BLOCK_SIZE) + off;

    // Read data from FRAM
    if (!mem_get_size()) {
        debug_printf("Memory size equal 0");
        return LFS_ERR_IO;  // Check if FRAM is available
    }
    int result = mem_read(addr, buffer, size);
    
    if(result == 0) {
        return 0;
    } else {
        return LFS_ERR_IO;
    }
}

int block_device_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const uint8_t *buffer, lfs_size_t size) {
    // Convert LittleFS block and offset to FRAM address
    uint32_t addr = (block * BLOCK_SIZE) + off;

    // Write data to FRAM
    if (!mem_get_size()) {
        debug_printf("Memory size equal 0");
        return LFS_ERR_IO;  // Check if FRAM is available
    }
    int result = mem_write(addr, buffer, size);
    if(result == 0) {
        return 0;
    } else {
        return LFS_ERR_IO;
    }
}

补充测试信息:

  • FRAM读写驱动验证正常:用LittleFS的CRC功能测试随机数据写入/读取,CRC一致,无数据错误。
  • 错误定位:LittleFS初始化时触发superblock 0xx has become unwritable警告,最终在CRC校验代码处返回LFS_ERR_CORRUPT:
// make sure to check crc in case we happen to pick
// up an unrelated crc (frozen block?)
err = lfs_bd_crc(lfs,
        NULL, &lfs->rcache, sizeof(uint32_t),
        commit->block, off1, sizeof(uint32_t), &crc);
if (err) {
    return err;
}
if (crc != 0) {
    return LFS_ERR_CORRUPT;
}

需求:无需修改LittleFS库的前提下,解决FRAM适配问题,明确问题原因和修复方向。


解决方案

1. 修正擦除函数的实现逻辑

LittleFS的擦除函数并非仅用于Flash物理擦除,它还负责标记块为可写入状态。FRAM无需物理擦除,但需要让LittleFS认为块已被"擦除"(即块内数据为全0,符合LittleFS对擦除块的预期)。

当前直接返回0的方式会导致LittleFS无法确认块是否可用,修改建议:

int block_device_erase(const struct lfs_config *c, lfs_block_t block) {
    // FRAM无需物理擦除,但需将块填充为全0以符合LittleFS擦除状态定义
    uint32_t addr = block * c->block_size;
    // 若块大小过大,可改为静态数组或分批次写入避免栈溢出
    uint8_t zero_buf[512];
    memset(zero_buf, 0, sizeof(zero_buf));
    
    if (!mem_get_size()) {
        debug_printf("Memory size equal 0");
        return LFS_ERR_IO;
    }
    
    int result = mem_write(addr, zero_buf, c->block_size);
    return result == 0 ? 0 : LFS_ERR_IO;
}

2. 统一地址计算中的块大小定义

代码中block * BLOCK_SIZE的BLOCK_SIZE必须与LittleFS配置的.block_size = 512完全一致,否则会出现地址计算错位,进而引发CRC校验失败。建议直接使用配置结构体中的值替代硬编码:

uint32_t addr = (block * c->block_size) + off;

3. 调整block_cycles参数

虽然FRAM没有Flash的擦写寿命限制,但block_cycles = -1会让LittleFS进入"无限寿命"模式,部分逻辑会发生变化。可先尝试将其设置为较大固定值(如100000),验证是否解决CRC校验问题:

.block_cycles = 100000,

4. 清除FRAM残留数据

若FRAM之前存储过其他数据,残留内容可能干扰超级块的创建。建议在初始化LittleFS前,手动擦除整个FRAM区域(全0填充),确保初始环境干净。

5. 验证FRAM容量匹配

配置的.block_count = 6144对应总容量为6144 * 512 = 3MB,需确认外部FRAM的实际容量大于等于该值,避免写入越界引发不可预期错误。

内容的提问来源于stack exchange,提问作者Kuba Jjj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:47:20