RTT笔记-fal

2020-10-08  本文已影响0人  lissettecarlr

该笔记类别主要是在自己学习时做的一些记录,方便自己很久不用忘掉时进行快速回忆

1 使用

1.1 导入文件

文件名 位置
fal.c ./src/
fal_flash.c ./src/
fal_partition.c ./src/
fal_rtt.c ./src/
fal_flash_stm32l1_port.c(移植文件) ./samples/porting

然后导入头文件地址

目录
./samples/porting
./inc

1.2 添加宏定义

在rtconfig.h文件中添加宏定义

// fal
#define PKG_USING_FAL
#define FAL_PART_HAS_TABLE_CFG

1.3建立分区表

根据在移植文件中定义的存储空间名字来分区,例如在fal_flash_stm32l1_port.c中定义了

const struct fal_flash_dev stm32l_eeprom = { "stm32l_eeprom", 0, 2*1024, 2048, {NULL, read, write, erase} };

则在fla_cfg.h中可用如下划分区域

#define FAL_PART_TABLE                                                          \
{                                                                               \
     {FAL_PART_MAGIC_WROD, "eeprom",    "stm32l_eeprom", 0, 1024+512, 0},        \
       {FAL_PART_MAGIC_WROD, "eeprom2",    "stm32l_eeprom", 1024+512,512 , 0},      \
}

注意的是头文件中必须使用宏(FAL_PART_HAS_TABLE_CFG),才会使用这里定义的分区方式

1.3 例程

#include "fal.h"
fal_init();
fal_show_part_table();

输出结果:


image.png
const struct fal_partition * bli = fal_partition_find("eeprom2") ;
if (bli ==RT_NULL)
{
    rt_kprintf("flash not find\n");
}
 static uint8_t reg[3] ={0,0,0};
static uint8_t data[3] ={1,2,3};
fal_partition_read(bli,0,reg,3);
rt_kprintf("##%d %d %d",reg[0],reg[1],reg[2]); 
rt_thread_mdelay(1000);
fal_partition_erase(bli,0,3);
fal_partition_write(bli,0,data,3);
fal_partition_read(bli,0,reg,3);
rt_kprintf("##%d %d %d",reg[0],reg[1],reg[2]); 

先读取3个寄存器,然后写入新数据1,2,3,再次读取显示出来。串口打印结果在第一次读取时输出为零,在擦除写入后读取出来便是数据1,2,3. 复位模块后第一次读取出的数据也为1,2,3. 表示掉电保存成功了。

2 通用API

2.1查找 Flash 设备

失败返回NULL

const struct fal_flash_dev *fal_flash_device_find(const char *name)

2.2 查找 Flash 分区

const struct fal_partition *fal_partition_find(const char *name)

2.3 获取分区表

led:分区表长度

const struct fal_partition *fal_get_partition_table(size_t *len)

2.4 临时设置分区表

FAL 初始化时会自动装载默认分区表。使用该设置将临时修改分区表,重启后会 丢失 该设置

void fal_set_partition_table_temp(struct fal_partition *table, size_t len)

2.5 从分区读取数据

返回实际读取大小

int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size)

2.6 往分区写入数据

int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size)

2.7 擦除分区数据

int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size)

2.8 擦除整个分区数据

int fal_partition_erase_all(const struct fal_partition *part)

2.9 打印分区表

void fal_show_part_table(void)

2.10 根据分区名称,创建对应的块设备

该函数可以根据指定的分区名称,创建对应的块设备,以便于在指定的分区上挂载文件系统

struct rt_device *fal_blk_device_create(const char *parition_name)
参数 描述
parition_name 分区名称
return 创建成功,则返回对应的块设备,失败返回空

2.11 根据分区名称,创建对应的 MTD Nor Flash 设备

该函数可以根据指定的分区名称,创建对应的 MTD Nor Flash 设备,以便于在指定的分区上挂载文件系统

struct rt_device *fal_mtd_nor_device_create(const char *parition_name)
参数 描述
parition_name 分区名称
return 创建成功,则返回对应的 MTD Nor Flash 设备,失败返回空

2.12 根据分区名称,创建对应的字符设备

该函数可以根据指定的分区名称,创建对应的字符设备,以便于通过 deivice 接口或 devfs 接口操作分区,开启了 POSIX 后,还可以通过 oepn/read/write 函数操作分区

struct rt_device *fal_char_device_create(const char *parition_name)
参数 描述
parition_name 分区名称
return 创建成功,则返回对应的块设备,失败返回空

3 MSH命令

命令 说明
fal 显示fal的相关命令
fal probe 显示并用于指定分区
fal read addr size 例如 fal read 0 64
fal write addr data1 ... dataN 例如fal write 8 1 2 3 4 5
fal erase addr size 例如 fal erase 0 4096
fal bench <blk_size> 例如 fal bench 4096 yes

4 移植

使用一节中提到的samples\porting目下便是移植需要修改的文件,例如源码只提供了fal_flash_sfud_port.c和fal_flash_stm32f2_port.c两个文件,我想在芯片stm32L151上使用它的eeprom,则自己新建立一个文件,实现初始化、读、写、擦即可,最后在同目录下的fal_cfg.h中进行分区,就想下面这样

#define FAL_PART_TABLE                                                          \
{                                                                               \
     {FAL_PART_MAGIC_WROD, "eeprom",    "stm32l_eeprom", 0, 1024+512, 0},        \
     {FAL_PART_MAGIC_WROD, "eeprom2",    "stm32l_eeprom", 1024+512,512 , 0},      \
}

fal_flash_stm32l1_port.c

#include <fal.h>
#include "rtthread.h"

#define EEPROM_BASE_ADDR    0x08080000 

static int read(long offset, uint8_t *buf, size_t size)
{
    uint8_t *wAddr;
      size_t i;
    wAddr=(uint8_t *)(EEPROM_BASE_ADDR+offset);  
       
      for (i = 0; i < size; i++, wAddr++, buf++)
      {
           *buf = *(uint8_t *) wAddr;
        }
            
//    while(size--){  
//        *buf++=*wAddr++;  
//    }   
    return size;
}


static int write(long offset, const uint8_t *buf, size_t size)
{
       size_t i;
       uint32_t read_data;
       uint32_t addr = EEPROM_BASE_ADDR + offset;
       HAL_FLASHEx_DATAEEPROM_Unlock();

       for (i = 0; i < size; i++, buf++, addr++)
       {
          // HAL_FLASHEx_DATAEEPROM_Erase(FLASH_TYPEERASEDATA_BYTE,addr);
           HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_FASTBYTE , addr, *buf);
           read_data = *(uint8_t *) addr;
          /* check data */
          if (read_data != *buf)
          {
            return -1;
          }
       }        
       HAL_FLASHEx_DATAEEPROM_Lock();   
       return size; 
}

static int erase(long offset, size_t size)
{
    size_t i;
    uint32_t addr = EEPROM_BASE_ADDR + offset;
    HAL_FLASHEx_DATAEEPROM_Unlock();
    for(i=0;i<size;i++ , addr++)
    {
       HAL_FLASHEx_DATAEEPROM_Erase(FLASH_TYPEERASEDATA_BYTE,addr);
    }
    HAL_FLASHEx_DATAEEPROM_Lock();  

    return size;
}
const struct fal_flash_dev stm32l_eeprom = { "stm32l_eeprom", 0, 2*1024, 2048, {NULL, read, write, erase} };

同理无论任何存储,只需要实现对于接口后,上层使用便没有任何区别

5 参考

https://github.com/RT-Thread-packages/fal

上一篇 下一篇

猜你喜欢

热点阅读