快速移植 SPIFFS

简介

Spiffs是一种用于嵌入式目标上 SPI NOR flash 的文件系统

Spiffs的设计考虑到以下特点:

  • 小型(嵌入式)系统,极少的 RAM
  • 只能擦除大面积的数据(块)
  • 擦除会将块中的所有位重置为1
  • 写将1置为0
  • 0只能通过擦除置为1
  • 磨损平衡

下载源码

使用最新的 Tag: 0.3.7 (https://github.com/pellepl/spiffs/tree/0.3.7)

复制文件,添加工程

复制以下 8 个文件到你的工程目录,大部分文件在 /src 目录下,spiffs_config.h 在 /src/default 目录下。并添加当前目录到 include 搜索目录。

spiffs.h

spiffs_cache.c

spiffs_check.c

spiffs_config.h

spiffs_gc.c

spiffs_hydrogen.c

spiffs_nucleus.c

spiffs_nucleus.h

修改配置文件

spiffs_config.h

注释掉 #include "params_test.h"

//#include "params_test.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <unistd.h>

 修改以下两个宏为 1,有利于加快访问速度

#define SPIFFS_USE_MAGIC                (1)

#define SPIFFS_USE_MAGIC_LENGTH         (1)

// Enable this to have an identifiable spiffs filesystem. This will look for
// a magic in all sectors to determine if this is a valid spiffs system or
// not on mount point. If not, SPIFFS_format must be called prior to mounting
// again.
#ifndef SPIFFS_USE_MAGIC
#define SPIFFS_USE_MAGIC                (1)
#endif

#if SPIFFS_USE_MAGIC
// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is
// enabled, the magic will also be dependent on the length of the filesystem.
// For example, a filesystem configured and formatted for 4 megabytes will not
// be accepted for mounting with a configuration defining the filesystem as 2
// megabytes.
#ifndef SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_USE_MAGIC_LENGTH         (1)
#endif
#endif

通常都只使用一个SPIFFS文件系统,所以可以修改 #define SPIFFS_SINGLETON 1,可以简化后续传递的参数。

// Enable if only one spiffs instance with constant configuration will exist
// on the target. This will reduce calculations, flash and memory accesses.
// Parts of configuration must be defined below instead of at time of mount.
#ifndef SPIFFS_SINGLETON
#define SPIFFS_SINGLETON 1
#endif

以下为你使用的具体 SPI flash 相关的参数

SPIFFS_CFG_PHYS_SZ:flash 的物理存储空间大小,可以是 flash 的全部容量,也可以是部分,我这里使用的W25Q128,修改为 16MB (1024*1024*16)

SPIFFS_CFG_PHYS_ERASE_SZ:flash 的物理擦除的最小存储空间大小,参考芯片手册,为 4KB (4096)

SPIFFS_CFG_PHYS_ADDR:flash 的物理起始地址,通常为0,如果是分配部分空间,按实际需求设置

SPIFFS_CFG_LOG_PAGE_SZ:逻辑页,单次写入的最小空间,即使文件只有1个字节,也会占用整个逻辑页

SPIFFS_CFG_LOG_BLOCK_SZ:逻辑块,多个逻辑页组成逻辑块

#if SPIFFS_SINGLETON
// Instead of giving parameters in config struct, singleton build must
// give parameters in defines below.
#ifndef SPIFFS_CFG_PHYS_SZ
#define SPIFFS_CFG_PHYS_SZ(ignore)        (1024*1024*2)
#endif
#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore)  (4096)
#endif
#ifndef SPIFFS_CFG_PHYS_ADDR
#define SPIFFS_CFG_PHYS_ADDR(ignore)      (0)
#endif
#ifndef SPIFFS_CFG_LOG_PAGE_SZ
#define SPIFFS_CFG_LOG_PAGE_SZ(ignore)    (256)
#endif
#ifndef SPIFFS_CFG_LOG_BLOCK_SZ
#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore)   (65536)
#endif
#endif

视具体的编译器类型,可能需要添加几种数据类型的别名 

typedef uint32_t  u32_t;
typedef uint16_t u16_t;
typedef uint8_t  u8_t;

typedef int32_t  s32_t;
typedef int16_t s16_t;
typedef int8_t  s8_t;

更详细的配置和使用方法,可以参考原作者的 wiki (Home · pellepl/spiffs Wiki · GitHub)

添加初始化文件

spiffs.c

添加文件系统的全局变量 fs,已经文件系统需要使用的几个 buffer

#include <spiffs.h>
#include "w25q.h"
#include "common/log.h"

static spiffs fs;

static u8_t spiffs_work_buf[SPIFFS_CFG_LOG_PAGE_SZ() * 2];
static u8_t spiffs_fds[32 * 4];
static u8_t spiffs_cache_buf[(SPIFFS_CFG_LOG_PAGE_SZ() + 32) * 4];

 实现 SPI flash 都、写、擦除功能的函数,并放入 cfg 结构体,实际实现跟 flash 型号相关,这里就没有具体展示了

static s32_t spiffs_flash_read(u32_t addr, u32_t size, u8_t* dst)
{
  w25q_read(addr, dst, size);
  return 0;
}

static s32_t spiffs_flash_write(u32_t addr, u32_t size, u8_t* src)
{
  w25q_writeNoCheck(addr, src, size);
  return 0;
}
static s32_t spiffs_flash_erase(u32_t addr, u32_t size)
{
  u16_t sec_start = addr / W25Q_SCT_SIZE;
  u16_t sec_end = size / W25Q_SCT_SIZE + sec_start;

  for (int i = sec_start; i < sec_end; i++)
  {
    w25q_eraseSector(i);
  }
  return 0;
}

spiffs_config cfg =
{
  .hal_read_f = spiffs_flash_read,
  .hal_write_f = spiffs_flash_write,
  .hal_erase_f = spiffs_flash_erase,
};

实现文件系统的初始化,调用 SPIFFS_mount mount 文件系统。

由于打开了宏 SPIFFS_USE_MAGIC,空白的 flash 是不能被识别成功的,返回 SPIFFS_ERR_NOT_A_FS,所以需要调用 SPIFFS_format 先格式化一次,然后就可以使用了。

s32_t spiffs_init(void)
{
  int res = SPIFFS_mount(&fs,
                         &cfg,
                         spiffs_work_buf,
                         spiffs_fds,
                         sizeof(spiffs_fds),
                         spiffs_cache_buf,
                         sizeof(spiffs_cache_buf),
                         0);

  if (SPIFFS_ERR_NOT_A_FS == res)
  {
    SPIFFS_unmount(&fs);
    SPIFFS_format(&fs);

    res = SPIFFS_mount(&fs,
                       &cfg,
                       spiffs_work_buf,
                       spiffs_fds,
                       sizeof(spiffs_fds),
                       spiffs_cache_buf,
                       sizeof(spiffs_cache_buf),
                       0);
  }

  return res;
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值