air101#
本章介绍LuatOS的sfud库使用方式
简介#
SFUD 是一款开源的串行 SPI Flash 通用驱动库,LuatOS中集成了该库,可以调用sfud的api实现对各类SPI Flash的读写操作
硬件准备#
air101开发板
SPI FLASH,这里使用
W25Q128
接线示意
SPI_CS/GPIO20 ----- CS
SPI_MISO/GPIO19 ----- DO
SPI_MOSI/GPIO21 ----- DI
air101 SPI_CLK/GPIO18 ----- CLK SPI_FLASH
3.3V ----- VCC
GND ----- GND
软件部分#
接口文档可参考:sfud库
初始化sfud#
使用SPI ID初始化#
代码如下
local spiID, csPin = 0, 20
local initRes = sfud.init(spiID, csPin, 20 * 1000 * 1000)
if initRes == false then
log.error(PROJECT .. ".init", "ERROR")
return
end
使用SPI DEVICE初始化#
代码如下
local spiID, csPin = 0, 20
-- 最后一个参数工作模式选择半双工
local spiFlash = spi.deviceSetup(spiID, csPin, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)
local initRes = sfud.init(spiFlash)
if initRes == false then
log.error(PROJECT .. ".init", "ERROR")
return
end
初始化过程会有类似如下日志输出
D/sfud Start initialize Serial Flash Universal Driver(SFUD) V1.1.0.
D/sfud You can get the latest version on https://github.com/armink/SFUD .
D/sfud The flash device manufacturer ID is 0xEF, memory type ID is 0x40, capacity ID is 0x18.
D/sfud Check SFDP header is OK. The reversion is V1.5, NPN is 0.
D/sfud Check JEDEC basic flash parameter header is OK. The table id is 0, reversion is V1.5, length is 16, parameter table pointer is 0x000080.
D/sfud JEDEC basic flash parameter table info:
D/sfud MSB-LSB 3 2 1 0
D/sfud [0001] 0xFF 0xF9 0x20 0xE5
D/sfud [0002] 0x07 0xFF 0xFF 0xFF
D/sfud [0003] 0x6B 0x08 0xEB 0x44
D/sfud [0004] 0xBB 0x42 0x3B 0x08
D/sfud [0005] 0xFF 0xFF 0xFF 0xFE
D/sfud [0006] 0x00 0x00 0xFF 0xFF
D/sfud [0007] 0xEB 0x40 0xFF 0xFF
D/sfud [0008] 0x52 0x0F 0x20 0x0C
D/sfud [0009] 0x00 0x00 0xD8 0x10
D/sfud 4 KB Erase is supported throughout the device. Command is 0x20.
D/sfud Write granularity is 64 bytes or larger.
D/sfud Target flash status register is non-volatile.
D/sfud 3-Byte only addressing.
D/sfud Capacity is 16777216 Bytes.
D/sfud Flash device supports 4KB block erase. Command is 0x20.
D/sfud Flash device supports 32KB block erase. Command is 0x52.
D/sfud Flash device supports 64KB block erase. Command is 0xD8.
D/sfud Find a Winbond flash chip. Size is 16777216 bytes.
D/sfud Flash device reset success.
D/sfud LuatOS-sfud flash device is initialize success.
获取flash设备信息表#
初始化sfud成功后,需要获取flash设备信息表,这也是一个抽象的flash对象,在后续的读写中需要传递这个flash对象
代码如下
local sfudDevice = sfud.getDeviceTable()
读写Flash#
成功初始化sfud之后,我们有两种方式对Flash进行读写,一种是直接对Flash的特定地址进行读写数据,一种是将挂载sfud lfs文件系统,然后使用Lua io api对挂载位置进行读写
直接对特定地址进行读写#
代码如下
-- 向地址1024写入字符串
local data = "LuatOS"
log.info(PROJECT .. ".write", sfud.writ(sfudDevice, 1024, data))
log.info(PROJECT .. ".read", sfud.read(sfudDevice,1024, string.len(data)))
日志如下
I/user.sfud.write 0
I/user.sfud.read LuatOS
挂载sfud lfs文件系统#
代码如下
log.info(PROJECT .. ".mount", sfud.moun(sfudDevice, "/sfud"))
log.info(PROJECT .. ".fsstat", fs.fsstat("/sfud"))
日志如下
D/sfud lfs_mount 0
I/user.sfud.mount true
I/user.sfud.fsstat true 4096 5 4096 lfs
可以看到,/sfud
挂载点 的Flash容量为 4096*4096/1024/1024 = 16MB
之后就可以使用Lua中的io api在/sfud下进行读写操作了
我们可以创建一个文件写入再读出
代码如下
local writeFile = io.open("/sfud/test.txt", "w")
if writeFile then
writeFile:write("LuatOS")
writeFile:close()
else
log.error(PROJECT .. ".writeFile", "文件创建失败")
return
end
local readFile = io.open("/sfud/test.txt", "r")
if readFile then
local res = readFile:read("*all")
readFile:close()
log.info(PROJECT .. ".readFile", res)
else
log.error(tag .. ".readFile", "文件不存在或文件输入格式不正确")
return
end
日志如下
-- 可以正常读出我们之前写入的内容
I/user.sfud.readFile LuatOS
完整代码#
PROJECT = "sfud"
VERSION = "1.0.0"
sys = require("sys")
USE_SPIID_INIT = true
MOUNT_FLASH = true
local function test()
local spiID, csPin = 0, 20
if USE_SPIID_INIT == true then
-- 使用SPI ID初始化
local initRes = sfud.init(spiID, csPin, 20 * 1000 * 1000)
if initRes == false then
log.error(PROJECT .. ".init", "ERROR")
return
end
else
-- 使用SPI DEVICE初始化
-- 最后一个参数工作模式选择半双工
local spiFlash = spi.deviceSetup(spiID, csPin, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)
local initRes = sfud.init(spiFlash)
if initRes == false then
log.error(PROJECT .. ".init", "ERROR")
return
end
end
local sfudDevice = sfud.getDeviceTable()
if MOUNT_FLASH == false then
-- 向地址1024写入字符串
local data = "LuatOS"
log.info(PROJECT .. ".write", sfud.write(sfudDevice, 1024, data))
log.info(PROJECT .. ".read", sfud.read(sfudDevice, 1024, string.len(data)))
else
log.info(PROJECT .. ".mount", sfud.mount(sfudDevice, "/sfud"))
log.info(PROJECT .. ".fsstat", fs.fsstat("/sfud"))
local writeFile = io.open("/sfud/test.txt", "w")
if writeFile then
writeFile:write("LuatOS")
writeFile:close()
else
log.error(PROJECT .. ".writeFile", "文件创建失败")
return
end
local readFile = io.open("/sfud/test.txt", "r")
if readFile then
local res = readFile:read("a")
readFile:close()
log.info(PROJECT .. ".readFile", res)
else
log.error(tag .. ".readFile", "文件不存在或文件输入格式不正确")
return
end
end
end
sys.taskInit(test)
sys.run()