[port/fal] Update the FAL to latest version.

This commit is contained in:
armink
2022-02-11 11:39:34 +08:00
parent fd062f7053
commit 24544704ed
16 changed files with 906 additions and 799 deletions
+201 -504
View File
File diff suppressed because it is too large Load Diff
+134 -130
View File
@@ -1,145 +1,149 @@
# FALFlash 抽象层
# FALFlash Abstraction Layer
## 1、FAL介绍
[Chinese](./README_ZH.md) | English
FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:
## 1. Introduction to FAL
- 支持静态可配置的分区表,并可关联多个 Flash 设备;
- 分区表支持 **自动装载** 。避免在多固件项目,分区表被多次定义的问题;
- 代码精简,对操作系统 **无依赖** ,可运行于裸机平台,比如对资源有一定要求的 Bootloader
- 统一的操作接口。保证了文件系统、OTA、NVM(例如:[EasyFlash](https://github.com/armink-rtt-pkgs/EasyFlash)) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;
- 自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;
The Flash abstraction layer is an abstraction layer for the management and operation of Flash and Flash-based partitions. The upper layer unifies the Flash and partition operation API (the framework diagram is shown below), and has the following characteristics:
![FAL framework](docs/figures/fal_framework.png)
- Supports static and configurable partition table and can associate multiple Flash devices;
- The partition table supports **automatic loading**. Avoid the problem that the partition table is defined multiple times in multiple firmware projects;
- The code is streamlined, **no dependency** on the operating system, and can run on bare metal platforms, such as Bootloader that has certain requirements for resources;
- Unified operation interface. Ensure the file system, OTA, NVM (for example: [EasyFlash](https://github.com/armink-rtt-pkgs/EasyFlash)) and other components that have certain dependencies on Flash, and the reusability of the underlying Flash driver;
- Comes with Finsh/MSH-based test commands, which can be operated in byte addressing mode (read, write, and erase) Flash or partition through Shell, which is convenient for developers to debug and test;
### 1.1、打开 FAL
![FAL framework](docs/figures/fal_framework-en.png)
使用 fal package 需要在 RT-Thread 的包管理器中选择它,具体路径如下:
### 1.1,Open FAL
To use fal package, you need to select it in the RT-Thread package manager. The specific path is as follows:
```
RT-Thread online packages
system packages --->
--- fal: Flash Abstraction Layer implement. Manage flash device and partition.
[*] Enable debug log output
[*] FAL partition table config has defined on 'fal_cfg.h'
[*] Enable debug log output
[*] FAL partition table config has defined on'fal_cfg.h'
(onchip) The flash device which saving partition table
(65536) The patition table end address relative to flash device offset.
[ ] FAL uses SFUD drivers
[ ] FAL uses SFUD drivers
(norflash0) The name of the device used by FAL (NEW)
version (latest) --->
version (latest) --->
```
每个功能的配置说明如下:
The configuration instructions for each function are as follows:
- 开启调试日志输出(默认开启);
- 分区表是否在 `fal_cfg.h` 中定义(默认开启)。如果关闭此选项,fal 将会自动去指定 Flash 的指定位置去检索并装载分区表,具体配置详见下面两个选项;
- 存放分区表的 Flash 设备;
- 分区表的 **结束地址** 位于 Flash 设备上的偏移。fal 将从此地址开始往回进行检索分区表,直接读取到 Flash 顶部。如果不确定分区表具体位置,这里也可以配置为 Flash 的结束地址,fal 将会检索整个 Flash,检索时间可能会增加。
- 启用 FAL 针对 SFUD 的移植文件(默认关闭);
- 应输入调用 `rt_sfud_flash_probe` 函数时传入的 FLASH 设备名称(也可以通过 list_device 命令查看 Block Device 的名字获取)。该名称与分区表中的 Flash 名称对应,只有正确设置设备名字,才能完成对 FLASH 的读写操作。
- Enable debug log output (enabled by default);
- Whether the partition table is defined in `fal_cfg.h` (enabled by default). If you turn off this option, fal will automatically go to the specified location of the designated Flash to retrieve and load the partition table. For the specific configuration, see the following two options;
然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。
- 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 it directly to the top of the Flash. If you are not sure about the specific 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 migration files for SFUD (closed by default);
- The name of the FLASH device passed in when calling the `rt_sfud_flash_probe` function should be entered (you can also check the name of the Block Device through the list_device command). This name corresponds to the Flash name in the partition table. Only when the device name is set correctly can the read and write operations on FLASH be completed.
### 1.2、FAL 目录
Then let the RT-Thread package manager automatically update, or use the `pkgs --update` command to update the package to the BSP.
| 名称 | 说明 |
### 1.2, FAL directory
| Name | Description |
| ------- | ---------- |
| inc | 头文件目录 |
| src | 源代码目录 |
| samples | 例程目录 |
| inc | Header file directory |
| src | Source Code Directory |
| samples | Sample catalog |
### 1.3FAL API
### 1.3, FAL API
FAL 相关的 API 如图所示,[点击此处查看 API 参数详解](docs/fal_api.md)
The FAL-related API is shown in the figure, [click here to view the detailed API parameters](docs/fal_api_en.md).
![FAL API](docs/figures/fal-api.png)
![FAL API](docs/figures/fal-api-en.png)
### 1.4、许可证
### 1.4, License
fal package 遵循 LGPLv2.1 许可,详见 `LICENSE` 文件。
The fal package complies with the Apache-2.0 license, see the `LICENSE` file for details.
### 1.5、依赖
### 1.5, Dependency
对 RT-Thread 无依赖,也可用于裸机。
It has no dependence on RT-Thread and can also be used on bare metal.
> 测试命令功能需要依赖 RT-Thread Finsh/MSH
> Test command function needs to rely on RT-Thread FinSH/MSH
## 2、使用 FAL
## 2. Use FAL
使用 FAL 的基本步骤如下所示:
The basic steps for using FAL are as follows:
1. 打开 FAL:从 Env 中打开 fal 软件包并下载到工程。
2. FAL 移植:定义 flash 设备、定义 flash 设备表、定义 flash 分区表。以下主要对步骤 2 展开讲解。
3. 调用 fal_init() 初始化该库:移植完成后,可在应用层调用,如在 main 函数中调用。
1. Open FAL: Open the fal software package from Env and download it to the project.
2. FAL migration: define flash device, define flash device table, define flash partition table. Step 2 is mainly explained below.
3. Call fal_init() to initialize the library: After the migration is completed, it can be called in the application layer, such as in the main function.
![fal 移植](docs/figures/fal-port.png)
![fal port](docs/figures/fal-port-en.png)
### 2.1、定义 flash 设备
### 2.1, Define flash device
在定义 Flash 设备表前,需要先定义 Flash 设备。可以是片内 flash, 也可以是片外基于 SFUD 的 spi flash
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:
- 定义片内 flash 设备可以参考 [`fal_flash_sfud_port.c`](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_flash_sfud_port.c)
- 定义片外 spi flash 设备可以参考 [`fal_flash_stm32f2_port.c`](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_flash_stm32f2_port.c)
- Refer to [`fal_flash_stm32f2_port.c`](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_flash_stm32f2_port.c) to define the on-chip flash device.
- Refer to [`fal_flash_sfud_port.c`](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_flash_sfud_port.c) to define off-chip spi flash device.
定义具体的 Flash 设备对象,用户需要根据自己的 Flash 情况分别实现 `init` `read` `write` `erase` 这些操作函数:
To define specific Flash device objects, users need to implement the operation functions of `init`, `read`, `write`, and `erase` according to their own Flash conditions:
- `static int init(void)`**可选** 的初始化操作。
- `static int read(long offset, uint8_t *buf, size_t size)`:读取操作。
- `static int init(void)`: **Optional** initialization operation.
- `static int read(long offset, uint8_t *buf, size_t size)`: read operation.
| 参数 | 描述 |
| Parameters | Description |
| ------ | ------------------------- |
| offset | 读取数据的 Flash 偏移地址 |
| buf | 存放待读取数据的缓冲区 |
| size | 待读取数据的大小 |
| return | 返回实际读取的数据大小 |
| offset | Flash offset address for reading data |
| buf | Buffer to store the data to be read |
| size | The size of the data to be read |
| return | Return the actual read data size |
- `static int write(long offset, const uint8_t *buf, size_t size)` :写入操作。
- `static int write(long offset, const uint8_t *buf, size_t size)`: write operation.
| 参数 | 描述 |
| Parameters | Description |
| ------ | ------------------------- |
| offset | 写入数据的 Flash 偏移地址 |
| buf | 存放待写入数据的缓冲区 |
| size | 待写入数据的大小 |
| return | 返回实际写入的数据大小 |
| offset | Flash offset address for writing data |
| buf | Buffer to store data to be written |
| size | The size of the data to be written |
| return | Return the actual written data size |
- `static int erase(long offset, size_t size)` :擦除操作。
- `static int erase(long offset, size_t size)`: erase operation.
| 参数 | 描述 |
| Parameters | Description |
| ------ | ------------------------- |
| offset | 擦除区域的 Flash 偏移地址 |
| size | 擦除区域的大小 |
| return | 返回实际擦除的区域大小 |
| offset | Flash offset address of erase area |
| size | The size of the erased area |
| return | Return the actual erased area size |
用户需要根据自己的 Flash 情况分别实现这些操作函数。在文件最底部定义了具体的 Flash 设备对象 ,如下示例定义了 stm32f2 片上 flashstm32f2_onchip_flash
Users need to implement these operation functions according to their own Flash conditions. A specific Flash device object is defined at the bottom of the file. The following example defines stm32f2 on-chip flash: stm32f2_onchip_flash
```c
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},
.name = "stm32_onchip",
.addr = 0x08000000,
.len = 1024*1024,
.blk_size = 128*1024,
.ops = {init, read, write, erase},
.write_gran = 8
};
```
- `"stm32_onchip"` : Flash 设备的名字。
- `0x08000000`: 对 Flash 操作的起始地址。
- `1024*1024`Flash 的总大小(1MB)。
- `128*1024`Flash 块/扇区大小(因为 STM32F2 各块大小不均匀,所以擦除粒度为最大块的大小:128K)。
- `{init, read, write, erase}` Flash 的操作函数。 如果没有 init 初始化过程,第一个操作函数位置可以置空。
- `8` : 设置写粒度,单位 bit 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度:
- nor flash: 1 bit
- stm32f4: 8 bit
- stm32f1: 32 bit
- stm32l4: 64 bit
- `"stm32_onchip"`: the name of the flash device.
- `0x08000000`: Start address for flash operation.
- `1024*1024`: Total size of Flash (1MB).
- `128*1024`: Flash block/sector size (because the STM32F2 blocks have uneven sizes, the erase granularity is the largest block size: 128K).
- `{init, read, write, erase}`: Flash operation functions. If there is no init initialization process, the first operation function position can be left blank.
- `8`: Set the write granularity, the unit is bit, 0 means not effective (the default value is 0), this member is a new member whose fal version is greater than 0.4.0. Each flash write granularity is not the same, it can be set through this member, the following are several common Flash write granularities:
- nor flash: 1 bit
- stm32f2/f4: 8 bit
- stm32f1: 32 bit
- stm32l4: 64 bit
### 2.2、定义 flash 设备表
### 2.2, Define the flash device table
Flash 设备表定义在 `fal_cfg.h` 头文件中,定义分区表前需 **新建 `fal_cfg.h` 文件** ,请将该文件统一放在对应 BSP 或工程目录的 port 文件夹下,并将该头文件路径加入到工程。fal_cfg.h 可以参考 [示例文件 fal/samples/porting/fal_cfg.h](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_cfg.h) 完成。
The Flash device table is defined in the header file `fal_cfg.h`, you need to **create a new `fal_cfg.h` file** before defining the partition table. Please place this 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 refer to [Sample file fal/samples/porting/fal_cfg.h](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_cfg.h) to complete.
Flash device table example:
设备表示例:
```c
/* ===================== Flash device Configuration ========================= */
@@ -154,13 +158,13 @@ extern struct fal_flash_dev nor_flash0;
}
```
Flash 设备表中,有两个 Flash 对象,一个为 STM32F2 的片内 Flash ,一个为片外的 Nor Flash
In the Flash device table, there are two Flash objects, one is the STM32F2 on-chip Flash, and the other is the off-chip Nor Flash.
### 2.3、定义 flash 分区表
### 2.3, Define flash partition table
分区表也定义在 `fal_cfg.h` 头文件中。Flash 分区基于 Flash 设备,每个 Flash 设备又可以有 N 个分区,这些分区的集合就是分区表。在配置分区表前,务必保证已定义好 **Flash 设备** **设备表**。fal_cfg.h 可以参考 [示例文件 fal/samples/porting/fal_cfg.h](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_cfg.h) 完成。
The partition table is also defined in the `fal_cfg.h` 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 refer to [Sample file fal/samples/porting/fal_cfg.h](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_cfg.h) to complete.
分区表示例:
Example of partition table:
```c
#define NOR_FLASH_DEV_NAME "norflash0"
@@ -177,28 +181,28 @@ Flash 设备表中,有两个 Flash 对象,一个为 STM32F2 的片内 Flash
#endif /* FAL_PART_HAS_TABLE_CFG */
```
上面这个分区表详细描述信息如下:
The detailed description of the above partition table is as follows:
| 分区名 | Flash 设备名 | 偏移地址 | 大小 | 说明 |
| Partition name | Flash device name | Offset address | Size | Description |
| ----------- | -------------- | --------- | ----- | ------------------ |
| "bl" | "stm32_onchip" | 0 | 64KB | 引导程序 |
| "app" | "stm32_onchip" | 64*1024 | 704KB | 应用程序 |
| "easyflash" | "norflash0" | 0 | 1MB | EasyFlash 参数存储 |
| "download" | "norflash0" | 1024*1024 | 1MB | OTA 下载区 |
| "bl" | "stm32_onchip" | 0 | 64KB | Bootloader |
| "app" | "stm32_onchip" | 64*1024 | 704KB | Application |
| "easyflash" | "norflash0" | 0 | 1MB | EasyFlash parameter storage |
| "download" | "norflash0" | 1024*1024 | 1MB | OTA download area |
用户需要修改的分区参数包括:分区名称、关联的 Flash 设备名、偏移地址(相对 Flash 设备内部)、大小,需要注意以下几点:
The partition parameters that users need to modify include: partition name, associated Flash device name, offset address (relative to the internal Flash device), and size. Pay attention to the following points:
- 分区名保证 **不能重复**
- 关联的 Flash 设备 **务必已经在 Flash 设备表中定义好** ,并且 **名称一致** ,否则会出现无法找到 Flash 设备的错误;
- 分区的起始地址和大小 **不能超过 Flash 设备的地址范围** ,否则会导致包初始化错误;
- Partition name guarantee **cannot be repeated**;
- The associated Flash device **must have been defined in the Flash device table**, and the **name is the same**, otherwise there will be an error 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 packet initialization errors;
> 注意:每个分区定义时,除了填写上面介绍的参数属性外,需在前面增加 `FAL_PART_MAGIC_WORD` 属性,末尾增加 `0` (目前用于保留功能)
> Note: When defining each partition, in addition to filling in the parameter attributes described above, you need to add the attribute `FAL_PART_MAGIC_WORD` at the front and add `0` at the end (currently used for reserved functions)
## 3Finsh/MSH 测试命令
## 3. FinSH/MSH test command
fal 提供了丰富的测试命令,项目只要在 RT-Thread 上开启 Finsh/MSH 功能即可。在做一些基于 Flash 的应用开发、调试时,这些命令会非常实用。它可以准确的写入或者读取指定位置的原始 Flash 数据,快速的验证 Flash 驱动的完整性,甚至可以对 Flash 进行性能测试。
FAL provides a wealth of test commands, and the project only needs to enable the Finsh/MSH function on RT-Thread. These commands will be very useful when doing some Flash-based application development and debugging. It can accurately write or read the original Flash data at the specified location, quickly verify the integrity of the Flash driver, and even perform performance tests on the Flash.
具体功能如下:输入 fal 可以看到完整的命令列表
The specific functions are as follows: enter `fal` to see the complete command list
```
msh />fal
@@ -212,11 +216,11 @@ fal bench <blk_size> - benchmark test with per block size
msh />
```
### 3.1、指定待操作的 Flash 设备或 Flash 分区
### 3.1, Specify the Flash device or Flash partition to be operated
当第一次使用 fal 命令时,直接输入 `fal probe` 将会显示分区表信息。可以指定待操作的对象为分区表里的某个分区,或者某个 Flash 设备。
When using the fal 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.
分区或者 Flash 被成功选中后,还将会显示它的一些属性情况。大致效果如下:
After the partition or Flash is successfully selected, some of its attributes will be displayed. The general effect is as follows:
```
msh />fal probe
@@ -236,11 +240,11 @@ Probed a flash partition | download | flash_dev: norflash0 | offset: 1048576 | l
msh />
```
### 3.2、擦除数据
### 3.2, Erase data
先输入 `fal erase` ,后面跟着待擦除数据的起始地址以及长度。以下命令为:从 0 地址(相对 Flash 或分区)开始擦除 4096 字节数据
Enter `fal erase` first, followed by the starting address and length of the data to be erased. The following command is: erase 4096 bytes of data from address 0 (relative to Flash or partition)
> 注意:根据 Flash 特性,擦除动作将按扇区对齐进行处理。所以,如果擦除操作地址或长度未按照 Flash 的扇区对齐,将会擦除掉与其关联的整个扇区数据。
> Note: According to the Flash characteristics, the erase action will be processed according to 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
@@ -248,38 +252,38 @@ Erase data success. Start from 0x00000000, size is 4096.
msh />
```
### 3.3、写入数据
### 3.3, Write data
先输入 `fal write` ,后面跟着 N 个待写入的数据,并以空格隔开。以下命令为:从地址 8 的位置依次开始写入 1、2、3、4 、 5 这 5 个字节数据
Enter `fal write` first, followed by N pieces of data to be written, separated by spaces. The following command is: Write 1, 2, 3, 4, 5, 5 bytes of data 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 .
Write data: 1 2 3 4 5.
msh />
```
### 3.4、读取数据
### 3.4, Read data
先输入 `fal read` ,后面跟着待读取数据的起始地址以及长度。以下命令为:从 0 地址开始读取 64 字节数据
Enter `fal read` first, followed by the starting address and length of the data to be read. The following command is: read 64 bytes of data 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
[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 />
```
### 3.5、性能测试
### 3.5, Performance test
性能测试将会测试 Flash 的擦除、写入及读取速度,同时将会测试写入及读取数据的准确性,保证整个 Flash 或整个分区的 写入与读取 数据的一致性。
The performance test will test the erasing, writing and reading speed of the Flash. At the same time, the accuracy of writing and reading data will be tested to ensure the consistency of the writing and reading data of the entire Flash or the entire partition.
先输入 `fal bench` ,后面跟着待测试 Flash 的扇区大小(请查看对应的 Flash 手册,SPI Nor Flash 一般为 4096)。由于性能测试将会让整个 Flash 或者整个分区的数据丢失,所以命令最后必须跟 `yes`
Enter `fal bench` first, 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 lose the data of the entire Flash or the entire partition, the command must be followed by `yes` at the end.
```
msh />fal bench 4096 yes
@@ -292,19 +296,19 @@ Read benchmark success, total time: 2.716S.
msh />
```
## 4、常见应用
## 4. Common applications
- [基于 FAL 分区的 fatfs 文件系统例程](https://github.com/RT-Thread/IoT_Board/tree/master/examples/15_component_fs_flash)
- [基于 FAL 分区的 littlefs 文件系统应用笔记](https://www.rt-thread.org/document/site/application-note/components/dfs/an0027-littlefs/)
- [基于 FAL 分区的 EasyFlash 移植说明](https://github.com/armink-rtt-pkgs/EasyFlash/tree/master/ports)
- [Example of fatfs file system based on FAL partition](https://github.com/RT-Thread/IoT_Board/tree/master/examples/15_component_fs_flash)
- [Application note of littlefs file system based on FAL partition](https://www.rt-thread.org/document/site/application-note/components/dfs/an0027-littlefs/)
- [EasyFlash porting instructions based on FAL partition](https://github.com/armink-rtt-pkgs/EasyFlash/tree/master/ports)
## 5、常见问题
## 5. Common problems
**1、使用 FAL 时,无法找到 `fal_cfg.h` 头文件**
**1. When using FAL, the header file `fal_cfg.h` cannot be found**
`fal_cfg.h` 为 fal 软件包的配置文件,需要用户手动新建,并定义相关的分区表信息。请将该文件统一放在 BSP 的 port 文件夹下或工程目录的 port 文件夹下(若没有则新建 port 文件夹),并将该头文件路径加入到工程,详见 "`2.2、定义 flash 设备表`" 小节。
`fal_cfg.h` is the configuration file of the fal software package, which needs to be created manually by the user and defines the relevant partition table information. Please place the file in the port folder of the BSP or the port folder of the project directory (if not, create a new port folder), and add the path of the header file to the project, see "`2.2. Define the Flash Device Table `" section.
## 6、联系方式
## 6. Contact
* 维护:[armink](https://github.com/armink)
* 主页:https://github.com/RT-Thread-packages/fal
* Maintenance: [armink](https://github.com/armink)
* Homepage: https://github.com/RT-Thread-packages/fal
+312
View File
@@ -0,0 +1,312 @@
# FALFlash 抽象层
中文页 | [英文页](./README.md)
## 1、FAL介绍
FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:
- 支持静态可配置的分区表,并可关联多个 Flash 设备;
- 分区表支持 **自动装载** 。避免在多固件项目,分区表被多次定义的问题;
- 代码精简,对操作系统 **无依赖** ,可运行于裸机平台,比如对资源有一定要求的 Bootloader
- 统一的操作接口。保证了文件系统、OTA、NVM(例如:[EasyFlash](https://github.com/armink-rtt-pkgs/EasyFlash)) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;
- 自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;
![FAL framework](docs/figures/fal_framework.png)
### 1.1、打开 FAL
使用 fal package 需要在 RT-Thread 的包管理器中选择它,具体路径如下:
```
RT-Thread online packages
system packages --->
--- fal: Flash Abstraction Layer implement. Manage flash device and partition.
[*] Enable debug log output
[*] FAL partition table config has defined on 'fal_cfg.h'
(onchip) The flash device which saving partition table
(65536) The patition table end address relative to flash device offset.
[ ] FAL uses SFUD drivers
(norflash0) The name of the device used by FAL (NEW)
version (latest) --->
```
每个功能的配置说明如下:
- 开启调试日志输出(默认开启);
- 分区表是否在 `fal_cfg.h` 中定义(默认开启)。如果关闭此选项,fal 将会自动去指定 Flash 的指定位置去检索并装载分区表,具体配置详见下面两个选项;
- 存放分区表的 Flash 设备;
- 分区表的 **结束地址** 位于 Flash 设备上的偏移。fal 将从此地址开始往回进行检索分区表,直接读取到 Flash 顶部。如果不确定分区表具体位置,这里也可以配置为 Flash 的结束地址,fal 将会检索整个 Flash,检索时间可能会增加。
- 启用 FAL 针对 SFUD 的移植文件(默认关闭);
- 应输入调用 `rt_sfud_flash_probe` 函数时传入的 FLASH 设备名称(也可以通过 list_device 命令查看 Block Device 的名字获取)。该名称与分区表中的 Flash 名称对应,只有正确设置设备名字,才能完成对 FLASH 的读写操作。
然后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。
### 1.2、FAL 目录
| 名称 | 说明 |
| ------- | ---------- |
| inc | 头文件目录 |
| src | 源代码目录 |
| samples | 例程目录 |
### 1.3、FAL API
FAL 相关的 API 如图所示,[点击此处查看 API 参数详解](docs/fal_api.md)。
![FAL API](docs/figures/fal-api.png)
### 1.4、许可证
fal package 遵循 Apache-2.0 许可,详见 `LICENSE` 文件。
### 1.5、依赖
对 RT-Thread 无依赖,也可用于裸机。
> 测试命令功能需要依赖 RT-Thread FinSH/MSH
## 2、使用 FAL
使用 FAL 的基本步骤如下所示:
1. 打开 FAL:从 Env 中打开 fal 软件包并下载到工程。
2. FAL 移植:定义 flash 设备、定义 flash 设备表、定义 flash 分区表。以下主要对步骤 2 展开讲解。
3. 调用 fal_init() 初始化该库:移植完成后,可在应用层调用,如在 main 函数中调用。
![fal 移植](docs/figures/fal-port.png)
### 2.1、定义 flash 设备
在定义 Flash 设备表前,需要先定义 Flash 设备。可以是片内 flash, 也可以是片外基于 SFUD 的 spi flash
- 定义片内 flash 设备可以参考 [`fal_flash_stm32f2_port.c`](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_flash_stm32f2_port.c) 。
- 定义片外 spi flash 设备可以参考 [`fal_flash_sfud_port.c`](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_flash_sfud_port.c) 。
定义具体的 Flash 设备对象,用户需要根据自己的 Flash 情况分别实现 `init``read``write``erase` 这些操作函数:
- `static int init(void)`**可选** 的初始化操作。
- `static int read(long offset, uint8_t *buf, size_t size)`:读取操作。
| 参数 | 描述 |
| ------ | ------------------------- |
| offset | 读取数据的 Flash 偏移地址 |
| buf | 存放待读取数据的缓冲区 |
| size | 待读取数据的大小 |
| return | 返回实际读取的数据大小 |
- `static int write(long offset, const uint8_t *buf, size_t size)` :写入操作。
| 参数 | 描述 |
| ------ | ------------------------- |
| offset | 写入数据的 Flash 偏移地址 |
| buf | 存放待写入数据的缓冲区 |
| size | 待写入数据的大小 |
| return | 返回实际写入的数据大小 |
- `static int erase(long offset, size_t size)` :擦除操作。
| 参数 | 描述 |
| ------ | ------------------------- |
| offset | 擦除区域的 Flash 偏移地址 |
| size | 擦除区域的大小 |
| return | 返回实际擦除的区域大小 |
用户需要根据自己的 Flash 情况分别实现这些操作函数。在文件最底部定义了具体的 Flash 设备对象 ,如下示例定义了 stm32f2 片上 flashstm32f2_onchip_flash
```c
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
};
```
- `"stm32_onchip"` : Flash 设备的名字。
- `0x08000000`: 对 Flash 操作的起始地址。
- `1024*1024`Flash 的总大小(1MB)。
- `128*1024`:Flash 块/扇区大小(因为 STM32F2 各块大小不均匀,所以擦除粒度为最大块的大小:128K)。
- `{init, read, write, erase}` :Flash 的操作函数。 如果没有 init 初始化过程,第一个操作函数位置可以置空。
- `8` : 设置写粒度,单位 bit, 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度:
- nor flash: 1 bit
- stm32f2/f4: 8 bit
- stm32f1: 32 bit
- stm32l4: 64 bit
### 2.2、定义 flash 设备表
Flash 设备表定义在 `fal_cfg.h` 头文件中,定义分区表前需 **新建 `fal_cfg.h` 文件** ,请将该文件统一放在对应 BSP 或工程目录的 port 文件夹下,并将该头文件路径加入到工程。fal_cfg.h 可以参考 [示例文件 fal/samples/porting/fal_cfg.h](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_cfg.h) 完成。
设备表示例:
```c
/* ===================== 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, \
}
```
Flash 设备表中,有两个 Flash 对象,一个为 STM32F2 的片内 Flash ,一个为片外的 Nor Flash。
### 2.3、定义 flash 分区表
分区表也定义在 `fal_cfg.h` 头文件中。Flash 分区基于 Flash 设备,每个 Flash 设备又可以有 N 个分区,这些分区的集合就是分区表。在配置分区表前,务必保证已定义好 **Flash 设备****设备表**。fal_cfg.h 可以参考 [示例文件 fal/samples/porting/fal_cfg.h](https://github.com/RT-Thread-packages/fal/blob/master/samples/porting/fal_cfg.h) 完成。
分区表示例:
```c
#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 */
```
上面这个分区表详细描述信息如下:
| 分区名 | Flash 设备名 | 偏移地址 | 大小 | 说明 |
| ----------- | -------------- | --------- | ----- | ------------------ |
| "bl" | "stm32_onchip" | 0 | 64KB | 引导程序 |
| "app" | "stm32_onchip" | 64*1024 | 704KB | 应用程序 |
| "easyflash" | "norflash0" | 0 | 1MB | EasyFlash 参数存储 |
| "download" | "norflash0" | 1024*1024 | 1MB | OTA 下载区 |
用户需要修改的分区参数包括:分区名称、关联的 Flash 设备名、偏移地址(相对 Flash 设备内部)、大小,需要注意以下几点:
- 分区名保证 **不能重复**
- 关联的 Flash 设备 **务必已经在 Flash 设备表中定义好** ,并且 **名称一致** ,否则会出现无法找到 Flash 设备的错误;
- 分区的起始地址和大小 **不能超过 Flash 设备的地址范围** ,否则会导致包初始化错误;
> 注意:每个分区定义时,除了填写上面介绍的参数属性外,需在前面增加 `FAL_PART_MAGIC_WORD` 属性,末尾增加 `0` (目前用于保留功能)
## 3、Finsh/MSH 测试命令
fal 提供了丰富的测试命令,项目只要在 RT-Thread 上开启 Finsh/MSH 功能即可。在做一些基于 Flash 的应用开发、调试时,这些命令会非常实用。它可以准确的写入或者读取指定位置的原始 Flash 数据,快速的验证 Flash 驱动的完整性,甚至可以对 Flash 进行性能测试。
具体功能如下:输入 fal 可以看到完整的命令列表
```
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 />
```
### 3.1、指定待操作的 Flash 设备或 Flash 分区
当第一次使用 fal 命令时,直接输入 `fal probe` 将会显示分区表信息。可以指定待操作的对象为分区表里的某个分区,或者某个 Flash 设备。
分区或者 Flash 被成功选中后,还将会显示它的一些属性情况。大致效果如下:
```
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 />
```
### 3.2、擦除数据
先输入 `fal erase` ,后面跟着待擦除数据的起始地址以及长度。以下命令为:从 0 地址(相对 Flash 或分区)开始擦除 4096 字节数据
> 注意:根据 Flash 特性,擦除动作将按扇区对齐进行处理。所以,如果擦除操作地址或长度未按照 Flash 的扇区对齐,将会擦除掉与其关联的整个扇区数据。
```
msh />fal erase 0 4096
Erase data success. Start from 0x00000000, size is 4096.
msh />
```
### 3.3、写入数据
先输入 `fal write` ,后面跟着 N 个待写入的数据,并以空格隔开。以下命令为:从地址 8 的位置依次开始写入 1、2、3、4 、 5 这 5 个字节数据
```
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 />
```
### 3.4、读取数据
先输入 `fal read` ,后面跟着待读取数据的起始地址以及长度。以下命令为:从 0 地址开始读取 64 字节数据
```
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 />
```
### 3.5、性能测试
性能测试将会测试 Flash 的擦除、写入及读取速度,同时将会测试写入及读取数据的准确性,保证整个 Flash 或整个分区的 写入与读取 数据的一致性。
先输入 `fal bench` ,后面跟着待测试 Flash 的扇区大小(请查看对应的 Flash 手册,SPI Nor Flash 一般为 4096)。由于性能测试将会让整个 Flash 或者整个分区的数据丢失,所以命令最后必须跟 `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 />
```
## 4、常见应用
- [基于 FAL 分区的 fatfs 文件系统例程](https://github.com/RT-Thread/IoT_Board/tree/master/examples/15_component_fs_flash)
- [基于 FAL 分区的 littlefs 文件系统应用笔记](https://www.rt-thread.org/document/site/application-note/components/dfs/an0027-littlefs/)
- [基于 FAL 分区的 EasyFlash 移植说明](https://github.com/armink-rtt-pkgs/EasyFlash/tree/master/ports)
## 5、常见问题
**1、使用 FAL 时,无法找到 `fal_cfg.h` 头文件**
`fal_cfg.h` 为 fal 软件包的配置文件,需要用户手动新建,并定义相关的分区表信息。请将该文件统一放在 BSP 的 port 文件夹下或工程目录的 port 文件夹下(若没有则新建 port 文件夹),并将该头文件路径加入到工程,详见 "`2.2、定义 flash 设备表`" 小节。
## 6、联系方式
* 维护:[armink](https://github.com/armink)
* 主页:https://github.com/RT-Thread-packages/fal
+1 -1
View File
@@ -132,7 +132,7 @@ struct rt_device *fal_mtd_nor_device_create(const char *parition_name)
## 创建字符设备
该函数可以根据指定的分区名称,创建对应的字符设备,以便于通过 deivice 接口或 devfs 接口操作分区,开启了 POSIX 后,还可以通过 oepn/read/write 函数操作分区。
该函数可以根据指定的分区名称,创建对应的字符设备,以便于通过 deivice 接口或 devfs 接口操作分区,开启了 POSIX 后,还可以通过 open/read/write 函数操作分区。
```C
struct rt_device *fal_char_device_create(const char *parition_name)
+144
View File
@@ -0,0 +1,144 @@
# FAL API
## Find Flash device
```C
const struct fal_flash_dev *fal_flash_device_find(const char *name)
```
| Parameters | Description |
| :----- | :----------------------- |
| name | Flash device name |
| return | If the search is successful, the Flash device object will be returned, and if the search fails, it will return NULL |
## Find Flash Partition
```C
const struct fal_partition *fal_partition_find(const char *name)
```
| Parameters | Description |
| :----- | :----------------------- |
| name | Flash partition name |
| return | If the search is successful, the Flash partition object will be returned, and if the search fails, it will return NULL |
## Get the partition table
```C
const struct fal_partition *fal_get_partition_table(size_t *len)
```
| Parameters | Description |
| :----- | :----------------------- |
| len | The length of the partition table |
| return | Partition table |
## Temporarily set the partition table
The default partition table will be automatically loaded when FAL is initialized. Using this setting will temporarily modify the partition table and will **lost** this setting after restarting
```C
void fal_set_partition_table_temp(struct fal_partition *table, size_t len)
```
| Parameters | Description |
| :----- | :----------------------- |
| table | Partition table |
| len | Length of the partition table |
## Read data from partition
```C
int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size)
```
| Parameters | Description |
| :----- | :----------------------- |
| part | Partition object |
| addr | Relative partition offset address |
| buf | Buffer to store the data to be read |
| size | The size of the data to be read |
| return | Return the actual read data size |
## Write data to partition
```C
int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size)
```
| Parameters | Description |
| :----- | :----------------------- |
| part | Partition object |
| addr | Relative partition offset address |
| buf | Buffer to store data to be written |
| size | The size of the data to be written |
| return | Return the actual written data size |
## Erase partition data
```C
int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size)
```
| Parameters | Description |
| :----- | :----------------------- |
| part | Partition object |
| addr | Relative partition offset address |
| size | The size of the erased area |
| return | Return the actual erased area size |
## Erase the entire partition data
```C
int fal_partition_erase_all(const struct fal_partition *part)
```
| Parameters | Description |
| :----- | :----------------------- |
| part | Partition object |
| return | Return the actual erased area size |
## Print partition table
```c
void fal_show_part_table(void)
```
## Create block device
This function can create the corresponding block device according to the specified partition name, so as to mount the file system on the specified partition
```C
struct rt_device *fal_blk_device_create(const char *parition_name)
```
| Parameters | Description |
| :----- | :----------------------- |
| parition_name | partition name |
| return | If the creation is successful, the corresponding block device will be returned, and if it fails, empty |
## Create MTD Nor Flash device
This function can create the corresponding MTD Nor Flash device according to the specified partition name, so as to mount the file system on the specified partition
```C
struct rt_device *fal_mtd_nor_device_create(const char *parition_name)
```
| Parameters | Description |
| :------------ | :---------------------------------- ------------------ |
| parition_name | Partition name |
| return | If the creation is successful, the corresponding MTD Nor Flash device will be returned, otherwise empty |
## Create a character device
This function can create the corresponding character device according to the specified partition name to facilitate the operation of the partition through the deivice interface or the devfs interface. After POSIX is turned on, the partition can also be operated through the open/read/write function.
```C
struct rt_device *fal_char_device_create(const char *parition_name)
```
| Parameters | Description |
| :------------ | :---------------------------------- ------- |
| parition_name | partition name |
| return | If the creation is successful, the corresponding character device will be returned, otherwise empty |
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+2 -16
View File
@@ -1,21 +1,7 @@
/*
* File : fal.h
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
+4 -18
View File
@@ -1,21 +1,7 @@
/*
* File : fal_def.h
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2019, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
@@ -28,7 +14,7 @@
#include <stdint.h>
#include <stdio.h>
#define FAL_SW_VERSION "0.5.0"
#define FAL_SW_VERSION "0.5.99"
#ifdef __RTTHREAD__ /* for RT-Thread platform */
#include <rtthread.h>
@@ -130,7 +116,7 @@ struct fal_flash_dev
} ops;
/* write minimum granularity, unit: bit.
1(nor flash)/ 8(stm32f4)/ 32(stm32f1)/ 64(stm32l4)
1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32l4)
0 will not take effect. */
size_t write_gran;
};
+2 -16
View File
@@ -1,21 +1,7 @@
/*
* File : fal_cfg.h
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
+2 -16
View File
@@ -1,21 +1,7 @@
/*
* File : fal_flash_sfud_port.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
+2 -16
View File
@@ -1,21 +1,7 @@
/*
* File : fal.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
+4 -20
View File
@@ -1,21 +1,7 @@
/*
* File : fal_flash.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
@@ -42,7 +28,6 @@ static uint8_t init_ok = 0;
int fal_flash_init(void)
{
size_t i;
const struct fal_flash_dev *dev;
if (init_ok)
{
@@ -51,7 +36,6 @@ int fal_flash_init(void)
for (i = 0; i < device_table_len; i++)
{
dev = device_table[i];
assert(device_table[i]->ops.read);
assert(device_table[i]->ops.write);
assert(device_table[i]->ops.erase);
@@ -61,8 +45,8 @@ int fal_flash_init(void)
device_table[i]->ops.init();
}
log_d("Flash device | %*.*s | addr: 0x%08lx | len: 0x%08x | blk_size: 0x%08x |initialized finish.",
FAL_DEV_NAME_MAX, FAL_DEV_NAME_MAX, dev->name, dev->addr, dev->len,
dev->blk_size);
FAL_DEV_NAME_MAX, FAL_DEV_NAME_MAX, device_table[i]->name, device_table[i]->addr, device_table[i]->len,
device_table[i]->blk_size);
}
init_ok = 1;
+69 -37
View File
@@ -1,21 +1,7 @@
/*
* File : fal_partition.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
@@ -32,6 +18,11 @@
#define FAL_PART_MAGIC_WORD_L 0x3130L
#define FAL_PART_MAGIC_WROD 0x45503130
struct part_flash_info
{
const struct fal_flash_dev *flash_dev;
};
/**
* FAL partition table config has defined on 'fal_cfg.h'.
* When this option is disable, it will auto find the partition table on a specified location in flash partition.
@@ -58,6 +49,8 @@
//USED static const struct fal_partition partition_table_def[] SECTION("FalPartTable") = FAL_PART_TABLE;
static const struct fal_partition partition_table_def[] = FAL_PART_TABLE;
static const struct fal_partition *partition_table = NULL;
/* partition and flash object information cache table */
static struct part_flash_info part_flash_cache[sizeof(partition_table_def) / sizeof(partition_table_def[0])] = { 0 };
#else /* FAL_PART_HAS_TABLE_CFG */
@@ -71,6 +64,7 @@ static const struct fal_partition *partition_table = NULL;
#endif
static struct fal_partition *partition_table = NULL;
static struct part_flash_info *part_flash_cache = NULL;
#endif /* FAL_PART_HAS_TABLE_CFG */
static uint8_t init_ok = 0;
@@ -119,6 +113,48 @@ void fal_show_part_table(void)
log_i("=============================================================");
}
static int check_and_update_part_cache(const struct fal_partition *table, size_t len)
{
const struct fal_flash_dev *flash_dev = NULL;
size_t i;
#ifndef FAL_PART_HAS_TABLE_CFG
if (part_flash_cache)
{
FAL_FREE(part_flash_cache);
}
part_flash_cache = FAL_MALLOC(len * sizeof(struct part_flash_info));
if (part_flash_cache == NULL)
{
log_e("Initialize failed! No memory for partition table cache");
return -2;
}
#endif
for (i = 0; i < len; i++)
{
flash_dev = fal_flash_device_find(table[i].flash_name);
if (flash_dev == NULL)
{
log_d("Warning: Do NOT found the flash device(%s).", table[i].flash_name);
continue;
}
if (table[i].offset >= (long)flash_dev->len)
{
log_e("Initialize failed! Partition(%s) offset address(%ld) out of flash bound(<%d).",
table[i].name, table[i].offset, flash_dev->len);
partition_table_len = 0;
return -1;
}
part_flash_cache[i].flash_dev = flash_dev;
}
return 0;
}
/**
* Initialize all flash partition on FAL partition table
*
@@ -126,8 +162,6 @@ void fal_show_part_table(void)
*/
int fal_partition_init(void)
{
size_t i;
const struct fal_flash_dev *flash_dev = NULL;
if (init_ok)
{
@@ -144,6 +178,8 @@ int fal_partition_init(void)
uint8_t part_table_find_ok = 0;
uint32_t read_magic_word;
fal_partition_t new_part = NULL;
size_t i;
const struct fal_flash_dev *flash_dev = NULL;
flash_dev = fal_flash_device_find(FAL_PART_TABLE_FLASH_DEV_NAME);
if (flash_dev == NULL)
@@ -264,23 +300,9 @@ int fal_partition_init(void)
#endif /* FAL_PART_HAS_TABLE_CFG */
/* check the partition table device exists */
for (i = 0; i < partition_table_len; i++)
if (check_and_update_part_cache(partition_table, partition_table_len) != 0)
{
flash_dev = fal_flash_device_find(partition_table[i].flash_name);
if (flash_dev == NULL)
{
log_d("Warning: Do NOT found the flash device(%s).", partition_table[i].flash_name);
continue;
}
if (partition_table[i].offset >= (long)flash_dev->len)
{
log_e("Initialize failed! Partition(%s) offset address(%ld) out of flash bound(<%d).",
partition_table[i].name, partition_table[i].offset, flash_dev->len);
partition_table_len = 0;
goto _exit;
}
goto _exit;
}
init_ok = 1;
@@ -326,6 +348,14 @@ const struct fal_partition *fal_partition_find(const char *name)
return NULL;
}
static const struct fal_flash_dev *flash_device_find_by_part(const struct fal_partition *part)
{
assert(part >= partition_table);
assert(part <= &partition_table[partition_table_len - 1]);
return part_flash_cache[part - partition_table].flash_dev;
}
/**
* get the partition table
*
@@ -355,6 +385,8 @@ void fal_set_partition_table_temp(struct fal_partition *table, size_t len)
assert(init_ok);
assert(table);
check_and_update_part_cache(table, len);
partition_table_len = len;
partition_table = table;
}
@@ -384,7 +416,7 @@ int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t
return -1;
}
flash_dev = fal_flash_device_find(part->flash_name);
flash_dev = flash_device_find_by_part(part);
if (flash_dev == NULL)
{
log_e("Partition read error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
@@ -425,7 +457,7 @@ int fal_partition_write(const struct fal_partition *part, uint32_t addr, const u
return -1;
}
flash_dev = fal_flash_device_find(part->flash_name);
flash_dev = flash_device_find_by_part(part);
if (flash_dev == NULL)
{
log_e("Partition write error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
@@ -464,7 +496,7 @@ int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t
return -1;
}
flash_dev = fal_flash_device_find(part->flash_name);
flash_dev = flash_device_find_by_part(part);
if (flash_dev == NULL)
{
log_e("Partition erase error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
+29 -25
View File
@@ -1,21 +1,7 @@
/*
* File : fal_rtt.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
@@ -794,12 +780,14 @@ static void fal(uint8_t argc, char **argv) {
}
/* full chip benchmark test */
uint32_t start_time, time_cast;
size_t write_size = strtol(argv[2], NULL, 0), read_size = strtol(argv[2], NULL, 0), cur_read_size;
size_t write_size = strtol(argv[2], NULL, 0), read_size = strtol(argv[2], NULL, 0), cur_op_size;
uint8_t *write_data = (uint8_t *)rt_malloc(write_size), *read_data = (uint8_t *)rt_malloc(read_size);
if (write_data && read_data)
{
memset(write_data, 0x55, write_size);
for (i = 0; i < write_size; i ++) {
write_data[i] = i & 0xFF;
}
if (flash_dev)
{
size = flash_dev->len;
@@ -834,13 +822,21 @@ static void fal(uint8_t argc, char **argv) {
start_time = rt_tick_get();
for (i = 0; i < size; i += write_size)
{
if (i + write_size <= size)
{
cur_op_size = write_size;
}
else
{
cur_op_size = size - i;
}
if (flash_dev)
{
result = flash_dev->ops.write(i, write_data, write_size);
result = flash_dev->ops.write(i, write_data, cur_op_size);
}
else if (part_dev)
{
result = fal_partition_write(part_dev, i, write_data, write_size);
result = fal_partition_write(part_dev, i, write_data, cur_op_size);
}
if (result < 0)
{
@@ -864,22 +860,30 @@ static void fal(uint8_t argc, char **argv) {
{
if (i + read_size <= size)
{
cur_read_size = read_size;
cur_op_size = read_size;
}
else
{
cur_read_size = size - i;
cur_op_size = size - i;
}
if (flash_dev)
{
result = flash_dev->ops.read(i, read_data, cur_read_size);
result = flash_dev->ops.read(i, read_data, cur_op_size);
}
else if (part_dev)
{
result = fal_partition_read(part_dev, i, read_data, cur_read_size);
result = fal_partition_read(part_dev, i, read_data, cur_op_size);
}
/* data check */
if (memcmp(write_data, read_data, cur_read_size))
for (int index = 0; index < cur_op_size; index ++)
{
if (write_data[index] != read_data[index])
{
rt_kprintf("%d %d %02x %02x.\n", i, index, write_data[index], read_data[index]);
}
}
if (memcmp(write_data, read_data, cur_op_size))
{
result = -RT_ERROR;
rt_kprintf("Data check ERROR! Please check you flash by other command.\n");