air103#

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#

  • air103 Development Board

  • SPI FLASH,Use hereW25Q128

Wiring Schematic

        HSPI_CSN/GPIO46   -----  CS
        HSPI_MISO/GPIO44  -----  DO
        HSPI_MOSI/GPIO45  -----  DI
air103  HSPI_CLK/GPIO47   -----  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 = 5, 46
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 = 5, 46
-- 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()