air101#
This chapter describes how to use the sfud library for LuatOS
Introduction#
SFUD It is an open source serial SPI Flash universal driver library, which is integrated in LuatOS and can call sfud api to read and write various SPI Flash
Hardware preparation#
air101 Development Board
SPI FLASH,Use here
W25Q128
Wiring Schematic
SPI_CS/GPIO20 ----- CS
SPI_MISO/GPIO19 ----- DO
SPI_MOSI/GPIO21 ----- DI
air101 SPI_CLK/GPIO18 ----- CLK SPI_FLASH
3.3V ----- VCC
GND ----- GND
Software part#
Interface documentation can be referred to:sfud library
Initialization sfud#
Initialize with SPI ID#
The code is as follows
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
Initialization using SPI DEVICE#
The code is as follows
local spiID, csPin = 0, 20
-- Last parameter Operating mode selection Half duplex
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
The initialization process will have a log output similar to the following
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.
obtain the flash device information table.#
After sfud is initialized successfully, you need to obtain the flash device information table, which is also an abstract flash object, and this flash object needs to be passed in subsequent reading and writing.
The code is as follows
local sfudDevice = sfud.getDeviceTable()
Read and write Flash#
After sfud is successfully initialized, we have two ways to read and write Flash, one is to directly read and write data to the specific address of Flash, the other is to mount the sfud lfs file system, and then use Lua io api to read and write the mount location.
Read and write directly to a specific address#
The code is as follows
-- Write a string to an address 1024
local data = "LuatOS"
log.info(PROJECT .. ".write", sfud.writ(sfudDevice, 1024, data))
log.info(PROJECT .. ".read", sfud.read(sfudDevice,1024, string.len(data)))
The log is as follows
I/user.sfud.write 0
I/user.sfud.read LuatOS
mount the sfud lfs file system#
The code is as follows
log.info(PROJECT .. ".mount", sfud.moun(sfudDevice, "/sfud"))
log.info(PROJECT .. ".fsstat", fs.fsstat("/sfud"))
The log is as follows
D/sfud lfs_mount 0
I/user.sfud.mount true
I/user.sfud.fsstat true 4096 5 4096 lfs
As you can see, the Flash capacity of the /sfud
mount point is 4096*4096/1024/1024 = 16MB
After that, you can use io api in Lua to read and write under/sfud
We can create a file to write and read
The code is as follows
local writeFile = io.open("/sfud/test.txt", "w")
if writeFile then
writeFile:write("LuatOS")
writeFile:close()
else
log.error(PROJECT .. ".writeFile", "File creation failed")
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", "File does not exist or file input format is incorrect")
return
end
The log is as follows
-- We can read what we wrote before normally.
I/user.sfud.readFile LuatOS
Full Code#
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
-- Initialize with SPI ID
local initRes = sfud.init(spiID, csPin, 20 * 1000 * 1000)
if initRes == false then
log.error(PROJECT .. ".init", "ERROR")
return
end
else
-- Initialization using SPI DEVICE
-- Last parameter Operating mode selection Half duplex
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
-- Write a string to an address 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", "File creation failed")
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", "File does not exist or file input format is incorrect")
return
end
end
end
sys.taskInit(test)
sys.run()