基础资料
基于Air105开发板:Air105 - LuatOS 文档
探讨重点
官方SFUD库操作-外置flash demo相关内容的学习及探讨。
扩展:
合宙Air103|SDIO (扩展) |LuatOS-SOC接口|官方demo|学习(15-3):SDIO - 文件读写操作_打酱油的工程师的博客-CSDN博客
参考博文
https://blog.csdn.net/Medlar_CN/article/details/128181736
软件版本
AIR105:LuatOS@AIR105 base 22.12 bsp V0014 32bit
硬件准备
- air105开发板
- SPI FLASH 这里选择W25Q128
软件使用
接口文档可参考:https://wiki.luatos.com/api/sfud.html
接线方式:
-- 接线AIR105--------W25QXX
--[[SPI2_CSN/GPIO19 -- CS
SPI2_MISO/GPIO21 ----- DO
SPI2_MOSI/GPIO20 ----- DI
SPI2_CLK/GPIO18 ----- CLK
+3.3V ----- VCC
GND ----- GND]]
demo代码及解析:
local spi_flash = spi.deviceSetup(2,pin.PB03,0,0,8,10*1000*1000,spi.MSB,1,0)--PB03
--[[sfud.init(spi_id, spi_cs, spi_bandrate)/sfud.init(spi_device)
初始化sfud
参数
传入值类型 解释
int spi_id SPI的ID/userdata spi_device
int spi_cs SPI的片选
int spi_bandrate SPI的频率
返回值
返回值类型 解释
bool 成功返回true,否则返回false
]]
local ret = sfud.init(spi_flash)
if ret then
log.info("sfud.init ok")
else
log.info("sfud.init Error")
return
end
--eraseWrite
--sfud.getDeviceNum() 返回值: int 返回设备总数
log.info("sfud.getDeviceNum",sfud.getDeviceNum())
--返回值类型 userdata 成功返回一个数据结构,该结构(flash结构体)无法直接显示,专用于后续的sfud操作。不成功则返回nil
--userdata可看做为sfud各类操作的基本模板。
local sfud_device = sfud.getDeviceTable()
--[[
sfud.eraseWrite(flash, addr,data)
先擦除再往 Flash 写数据
参数
传入值类型 解释
userdata flash Flash 设备对象 sfud.get_device_table()返回的数据结构
int addr 起始地址
string data 待写入的数据
返回值
返回值类型 解释
int 成功返回0
]]
local str="sfud is a little filesystem(lfs)"
log.info("sfud.eraseWrite",sfud.eraseWrite(sfud_device,1024,str))
log.info("sfud.read",sfud.read(sfud_device,1024,string.len(str)))
--[[sfud.mount(flash, mount_point, offset, maxsize)
挂载sfud lfs文件系统
参数
传入值类型 解释
userdata flash Flash 设备对象 sfud.get_device_table()返回的数据结构
string mount_point 挂载目录名
int 起始偏移量,默认0
int 总大小, 默认是整个flash
返回值
返回值类型 解释
bool 成功返回true
]]
log.info("sfud.mount",sfud.mount(sfud_device,"/sfud"))
--获取文件系统信息,传入值类型string,路径,默认”/”,可选,
--返回值:boolean获取成功返回true,否则返回false,int,总的block数量;int,已使用的block数量;int,block的大小,单位字节;string,文件系统类型,例如lfs代表littlefs
-- 打印根分区的信息
log.info("fsstat", fs.fsstat("/")) -- I/user.fsstat true 128 4 4096 lfs
-- 打印挂载的sfud分区的信息
log.info("fsstat", fs.fsstat("/sfud")) -- I/user.fsstat true 2048 2 4096 lfs
LOG:
[2023-02-10 23:17:00.867] __y__Z_Remote_Upgrade 441:no ota info
[2023-02-10 23:17:00.867] no bl encrypt
[2023-02-10 23:17:00.867] main 672:bootloader build release Feb 1 2023 20:19:29!
[2023-02-10 23:17:00.867] Jump_AppRun 76:jump to 0x01010400 !
[2023-02-10 23:17:00.876] main 188:APP Build release Feb 9 2023 22:01:02!
[2023-02-10 23:17:00.876] I/main LuatOS@AIR105 base 22.12 bsp V0014 32bit
[2023-02-10 23:17:00.876] I/main ROM Build: Feb 10 2023 20:58:08
[2023-02-10 23:17:00.876] D/main loadlibs luavm 204792 15376 15376
[2023-02-10 23:17:00.876] D/main loadlibs sys 406456 51032 51616
[2023-02-10 23:17:00.876] I/user.main sfuddemo 1.0.0
[2023-02-10 23:17:00.876] I/sfud Find a Winbond flash chip. Size is 8388608 bytes.
[2023-02-10 23:17:00.876] I/sfud LuatOS-sfud flash device is initialize success.
[2023-02-10 23:17:00.876] I/user.sfud.init ok
[2023-02-10 23:17:00.876] I/user.sfud.getDeviceNum 1
[2023-02-10 23:17:00.944] I/user.sfud.eraseWrite 0
[2023-02-10 23:17:00.944] I/user.sfud.read sfud is a little filesystem(lfs)
[2023-02-10 23:17:00.944] D/sfud lfs_mount 0
[2023-02-10 23:17:00.944] D/sfud vfs mount /sfud ret 0
[2023-02-10 23:17:00.944] I/user.sfud.mount true
[2023-02-10 23:17:00.944] I/user.fsstat true 128 4 4096 lfs
[2023-02-10 23:17:00.944] I/user.fsstat true 2048 2 4096 lfs
PS: SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库
项目地址: https://github.com/armink/SFUD
SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SFUD 就是为了解决这些 Flash 的差异现状而设计,让我们的产品能够支持不同品牌及规格的 Flash,提高了涉及到 Flash 功能的软件的可重用性及可扩展性,同时也可以规避 Flash 缺货或停产给产品所带来的风险。
- 主要特点:支持 SPI/QSPI 接口、面向对象(同时支持多个 Flash 对象)、可灵活裁剪、扩展性强、支持 4 字节地址
- 资源占用
- 标准占用:RAM:0.2KB ROM:5.5KB
- 最小占用:RAM:0.1KB ROM:3.6KB
- 设计思路:
- 什么是 SFDP :它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B (点击这里查看)。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数。
- 不支持 SFDP 怎么办 :如果该 Flash 不支持 SFDP 标准,SFUD 会查询配置文件 ( /sfud/inc/sfud_flash_def.h ) 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 2.5 添加库目前不支持的 Flash)。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。
sfud - SPI FLASH sfud软件包
已适配 Air101/Air103 Air105 ESP32C3 Air780
备注
本页文档由这个文件自动生成。如有错误,请提交issue或帮忙修改后pr,谢谢!
小技巧
本库有专属demo,点此链接查看sfud的demo例子
sfud.init(spi_id, spi_cs, spi_bandrate)/sfud.init(spi_device)
初始化sfud
参数
传入值类型 | 解释 |
int | spi_id SPI的ID/userdata spi_device |
int | spi_cs SPI的片选 |
int | spi_bandrate SPI的频率 |
返回值
返回值类型 | 解释 |
bool | 成功返回true,否则返回false |
例子
--spi
log.info("sfud.init",sfud.init(0,20,20 * 1000 * 1000))
--spi_device
local spi_device = spi.deviceSetup(0,17,0,0,8,2000000,spi.MSB,1,0)
log.info("sfud.init",sfud.init(spi_device))
sfud.getDeviceNum()
获取flash设备信息表中的设备总数
参数
无
返回值
返回值类型 | 解释 |
int | 返回设备总数 |
例子
log.info("sfud.getDeviceNum",sfud.getDeviceNum())
sfud.getDevice(index)
通过flash信息表中的索引获取flash设备
参数
传入值类型 | 解释 |
int | index flash信息表中的索引 |
返回值
返回值类型 | 解释 |
userdata | 成功返回一个数据结构,否则返回nil |
例子
local sfud_device = sfud.getDevice(1)
sfud.getDeviceTable()
获取flash设备信息表
参数
无
返回值
返回值类型 | 解释 |
userdata | 成功返回一个数据结构,否则返回nil |
例子
local sfud_device = sfud.getDeviceTable()
sfud.chipErase(flash)
擦除 Flash 全部数据
参数
传入值类型 | 解释 |
userdata | flash Flash 设备对象 sfud.get_device_table()返回的数据结构 |
返回值
返回值类型 | 解释 |
int | 成功返回0 |
例子
sfud.chipErase(flash)
sfud.erase(flash,add,size)
擦除 Flash 指定地址指定大小
参数
传入值类型 | 解释 |
userdata | flash Flash 设备对象 sfud.get_device_table()返回的数据结构 |
number | add 擦除地址 |
number | size 擦除大小 |
返回值
返回值类型 | 解释 |
int | 成功返回0 |
例子
sfud.erase(flash,add,size)
sfud.read(flash, addr, size)
读取 Flash 数据
参数
传入值类型 | 解释 |
userdata | flash Flash 设备对象 sfud.get_device_table()返回的数据结构 |
int | addr 起始地址 |
int | size 从起始地址开始读取数据的总大小 |
返回值
返回值类型 | 解释 |
string | data 读取到的数据 |
例子
log.info("sfud.read",sfud.read(sfud_device,1024,4))
sfud.write(flash, addr,data)
向 Flash 写数据
参数
传入值类型 | 解释 |
userdata | flash Flash 设备对象 sfud.get_device_table()返回的数据结构 |
int | addr 起始地址 |
string | data 待写入的数据 |
返回值
返回值类型 | 解释 |
int | 成功返回0 |
例子
log.info("sfud.write",sfud.write(sfud_device,1024,"sfud"))
sfud.eraseWrite(flash, addr,data)
先擦除再往 Flash 写数据
参数
传入值类型 | 解释 |
userdata | flash Flash 设备对象 sfud.get_device_table()返回的数据结构 |
int | addr 起始地址 |
string | data 待写入的数据 |
返回值
返回值类型 | 解释 |
int | 成功返回0 |
例子
log.info("sfud.eraseWrite",sfud.eraseWrite(sfud_device,1024,"sfud"))
sfud.mount(flash, mount_point, offset, maxsize)
挂载sfud lfs文件系统
参数
传入值类型 | 解释 |
userdata | flash Flash 设备对象 sfud.get_device_table()返回的数据结构 |
string | mount_point 挂载目录名 |
int | 起始偏移量,默认0 |
int | 总大小, 默认是整个flash |
返回值
返回值类型 | 解释 |
bool | 成功返回true |
例子
log.info("sfud.mount",sfud.mount(sfud_device,"/sfud"))
log.info("fsstat", fs.fsstat("/"))
log.info("fsstat", fs.fsstat("/sfud"))