FAL: Flash Abstraction Layer

FAL: Flash Abstraction Layer, In V4.1.0, the fal package is redefined as an internal component of RT-Thread. The usage is different from before: (1) Originally, to use fal, you had to select and download it in the RT-Thread package manager; (2) Now you only need to open it in the component to use it. The following is a detailed introduction.

FAL (Flash Abstraction Layer) Flash abstraction layer is an abstraction layer for managing and operating Flash and Flash-based partitions. It unifies the Flash and partition operation APIs of the upper layer (the framework diagram is shown below) and has the following features:

  • Supports statically configurable partition tables and can associate multiple Flash devices;

  • The partition table supports automatic loading . This avoids the problem of partition tables being defined multiple times in multiple firmware projects.

  • The code is concise and has no dependency on the operating system . It can run on bare metal platforms, such as bootloaders that have certain resource requirements.

  • Unified operation interface. Ensures the reusability of the underlying Flash driver for components that have a certain dependency on Flash, such as the file system, OTA, and NVM (e.g. EasyFlash );

  • It comes with Finsh/MSH-based test commands, which can operate (read, write, erase) Flash or partitions in byte-addressing mode through Shell, making it convenient for developers to debug and test;

Open and use in the component:

The configuration instructions for each function are as follows:

  • Enable debug log output (enabled by default);

  • Whether the partition table fal_cfg.his defined in (enabled by default). If this option is disabled, fal will automatically retrieve and load the partition table from the specified location of the specified Flash. For detailed configuration, see the following two options;

    • Flash device storing the partition table;

    • The end address of the partition table is located at the offset on the Flash device. fal will retrieve the partition table from this address and read directly to the top of the Flash. If you are not sure about the exact location of the partition table, you can also configure it as the end address of the Flash. fal will retrieve the entire Flash, and the retrieval time may increase.

  • Enable FAL porting files for SFUD (off by default);

    • The FLASH device name passed in when calling the function should be entered rt_sfud_flash_probe(you can also obtain it by viewing the Block Device name through the list_device command). This name corresponds to the Flash name in the partition table. Only by setting the device name correctly can the read and write operations on the FLASH be completed.

Then let the RT-Thread package manager automatically update, or use pkgs --updatethe command to update the package to the BSP.

name

illustrate

inc

Header file directory

src

Source code directory

samples

Routine Directory

The FAL-related API is shown in the figure. Click here to view the detailed explanation of API parameters .

The basic steps for using FAL are as follows:

  1. Open FAL: Open the fal package from Env and download it to the project.

  2. FAL transplantation: define flash device, define flash device table, define flash partition table. The following mainly explains step 2.

  3. Call fal_init() to initialize the library: After the porting is completed, it can be called in the application layer, such as in the main function.

Before defining the Flash device table, you need to define the Flash device first. It can be on-chip flash or off-chip spi flash based on SFUD:

Define a specific Flash device object. Users need to implement init,,, readand these operation functions according writeto their own Flash situation:erase

  • static int init(void): Optional initialization operation.

  • static int read(long offset, uint8_t *buf, size_t size): Read operation.

parameter

describe

offset

Flash offset address to read data from

buf

Buffer for storing data to be read

size

The size of the data to be read

return

Returns the actual size of the data read

  • static int write(long offset, const uint8_t *buf, size_t size): Write operation.

parameter

describe

offset

Flash offset address to write data to

buf

Buffer for storing data to be written

size

The size of the data to be written

return

Returns the actual size of the data written

  • static int erase(long offset, size_t size): Erase operation.

parameter

describe

offset

Flash offset address of erase area

size

Size of the erase area

return

Returns the size of the area actually erased

Users need to implement these operation functions according to their own Flash situation. The specific Flash device object is defined at the bottom of the file. The following example defines the stm32f2 on-chip flash: stm32f2_onchip_flash

const struct fal_flash_dev stm32f2_onchip_flash =
{
    .name       = "stm32_onchip",
    .addr       = 0x08000000,
    .len        = 1024*1024,
    .blk_size   = 128*1024,
    .ops        = {init, read, write, erase},
    .write_gran = 8
};copymistakeCopy Success
  • "stm32_onchip": The name of the Flash device.

  • 0x08000000: The starting address for Flash operation.

  • 1024*1024: Total size of the Flash (1MB).

  • 128*1024: Flash block/sector size (because the sizes of STM32F2 blocks are uneven, the erase granularity is the size of the largest block: 128K).

  • {init, read, write, erase}:Flash operation function. If there is no init initialization process, the first operation function position can be left blank.

  • 8: Set the write granularity, unit is bit, 0 means it is not effective (the default value is 0). This member is a new member of the fal version greater than 0.4.0. The write granularity of each flash is different, and it can be set through this member. The following are some common flash write granularities:

    • nor flash: 1 bit

    • stm32f4: 8 bits

    • stm32f1: 32 bit

    • stm32l4: 64 bit

The Flash device table is defined in fal_cfg.hthe header file. Before defining the partition table, you need to create a new fal_cfg.hfile . Please put the file in the port folder of the corresponding BSP or project directory and add the header file path to the project. fal_cfg.h can be completed by referring to the sample file fal/samples/porting/fal_cfg.h .

Device table example:

/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32f2_onchip_flash;
extern struct fal_flash_dev nor_flash0;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &stm32f2_onchip_flash,                                           \
    &nor_flash0,                                                     \
}copymistakeCopy Success

In the Flash device table, there are two Flash objects, one is the on-chip Flash of STM32F2, and the other is the off-chip Nor Flash.

The partition table is also defined in fal_cfg.hthe header file. Flash partitions are based on Flash devices. Each Flash device can have N partitions. The collection of these partitions is the partition table. Before configuring the partition table, make sure that the Flash device and device table have been defined . fal_cfg.h can be completed by referring to the sample file fal/samples/porting/fal_cfg.h .

Partition table example:

#define NOR_FLASH_DEV_NAME             "norflash0"
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                               \
{                                                                                    \
    {FAL_PART_MAGIC_WORD,        "bl",     "stm32_onchip",         0,   64*1024, 0}, \
    {FAL_PART_MAGIC_WORD,       "app",     "stm32_onchip",   64*1024,  704*1024, 0}, \
    {FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME,         0, 1024*1024, 0}, \
    {FAL_PART_MAGIC_WORD,  "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */copymistakeCopy Success

The above partition table describes the information in detail as follows:

Partition name

Flash device name

Offset Address

size

illustrate

"bl"

"stm32_onchip"

0

64KB

Bootloader

"app"

"stm32_onchip"

64*1024

704KB

app

"easyflash"

"norflash0"

0

1MB

EasyFlash parameter storage

"download"

"norflash0"

1024*1024

1MB

OTA Download Area

The partition parameters that users need to modify include: partition name, associated Flash device name, offset address (relative to the Flash device), size, and the following points should be noted:

  • Partition names must not be repeated ;

  • The associated Flash device must have been defined in the Flash device table and have the same name , otherwise an error will occur that the Flash device cannot be found;

  • The starting address and size of the partition cannot exceed the address range of the Flash device , otherwise it will cause package initialization errors;

Note: When defining each partition, in addition to filling in the parameter attributes described above, you need to add FAL_PART_MAGIC_WORDthe attribute at the front and add the attribute at the end 0(currently used to retain the function)

fal provides a variety of test commands. All the project needs to do is enable the MSH function on RT-Thread. These commands are very useful when developing and debugging Flash-based applications. It can accurately write or read the original Flash data at a specified location, quickly verify the integrity of the Flash driver, and even perform performance tests on Flash.

The specific functions are as follows: Enter fal to see a complete list of commands

msh />fal
Usage:
fal probe [dev_name|part_name]   - probe flash device or partition by given name
fal read addr size               - read 'size' bytes starting at 'addr'
fal write addr data1 ... dataN   - write some bytes 'data' starting at 'addr'
fal erase addr size              - erase 'size' bytes starting at 'addr'
fal bench <blk_size>             - benchmark test with per block size

msh />copymistakeCopy Success

When you use the fall command for the first time, directly inputting fal probe will display the partition table information. You can specify the object to be operated as a partition in the partition table or a Flash device.

After the partition or Flash is successfully selected, some of its properties will be displayed. The general effect is as follows:

msh />fal probe    
No flash device or partition was probed.
Usage: fal probe [dev_name|part_name]   - probe flash device or partition by given name.
[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name      | flash_dev    |   offset   |    length  |
[I/FAL] -------------------------------------------------------------
[I/FAL] | bl        | stm32_onchip | 0x00000000 | 0x00010000 |
[I/FAL] | app       | stm32_onchip | 0x00010000 | 0x000b0000 |
[I/FAL] | ef        | norflash0    | 0x00000000 | 0x00100000 |
[I/FAL] | download  | norflash0    | 0x00100000 | 0x00100000 |
[I/FAL] =============================================================
msh />
msh />fal probe download
Probed a flash partition | download | flash_dev: norflash0 | offset: 1048576 | len: 1048576 |.
msh />copymistakeCopy Success

Enter first fal erase, followed by the starting address and length of the data to be erased. The following command is: Erase 4096 bytes of data starting from address 0 (relative to Flash or partition)

Note: According to the Flash characteristics, the erase operation will be processed according to the sector alignment. Therefore, if the erase operation address or length is not aligned with the Flash sector, the entire sector data associated with it will be erased.

msh />fal erase 0 4096
Erase data success. Start from 0x00000000, size is 4096.
msh />copymistakeCopy Success

Enter first fal write, followed by N data to be written, separated by spaces. The following command is: Write 1, 2, 3, 4, 5 bytes of data in sequence starting from address 8

msh />fal write 8 1 2 3 4 5
Write data success. Start from 0x00000008, size is 5.
Write data: 1 2 3 4 5 .
msh />copymistakeCopy Success

Enter first fal read, followed by the starting address and length of the data to be read. The following command is: read 64 bytes of data starting from address 0

msh />fal read 0 64
Read data success. Start from 0x00000000, size is 64. The data is:
Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[00000000] FF FF FF FF FF FF FF FF 01 02 03 04 05 FF FF FF 
[00000010] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
[00000020] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
[00000030] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 

msh />copymistakeCopy Success

The performance test will test the erasing, writing and reading speed of the Flash, and will also test the accuracy of the written and read data to ensure the consistency of the written and read data of the entire Flash or the entire partition.

Enter first fal bench, followed by the sector size of the Flash to be tested (please check the corresponding Flash manual, SPI Nor Flash is generally 4096). Since the performance test will cause the data of the entire Flash or the entire partition to be lost, the command must be followed at the end yes.

msh />fal bench 4096 yes
Erasing 1048576 bytes data, waiting...
Erase benchmark success, total time: 2.674S.
Writing 1048576 bytes data, waiting...
Write benchmark success, total time: 7.107S.
Reading 1048576 bytes data, waiting...
Read benchmark success, total time: 2.716S.
msh />copymistakeCopy Success

fal_cfg.h1. Unable to find header file when using FAL

fal_cfg.hThis is the configuration file of the fal package. It needs to be created manually by the user and define the relevant partition table information. Please put this file in the port folder of the BSP or the port folder of the project directory (if it does not exist, create a new port folder) and add the header file path to the project. For details, see the " 2.2、定义 flash 设备表" section of this article.

After adding the file, check the file contents fal_cfg.hin the folder where the file is located or in the folder above it . For example, if the file is in the folder, check whether the file has the following contents:SConscriptfal_cfg.hstm32f072-st-nucleo/board/portsstm32f072-st-nucleo\board\SConscript

path =  [cwd]
path += [cwd + '/ports']copymistakeCopy Success

The above is used to fal_cfg.hadd the file path to the project.

Last updated

Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University