【RTT-Studio】详细使用教程一:Flash读写

一、RTT 配置步骤

1、在RT_Thread Settings中打开FAL组件,如下:

在这里插入图片描述

2、定义struct fal_flash_dev类型的flash设备

  • struct fal_flash_dev的具体成员:flash设备名字、flash起始地址、flash大小、块大小(执行擦除时的最小颗粒)、操作函数(init、read、write、erase)、写操作最小颗粒度;
  • 找到STM32F407VET6扇区的大小,主存储器一共5个扇区,4个16K、1个64K、3个128K;

3、drv_flash_f4.c代码:

  • 第一部分:宏定义各扇区的起始地址
/* Base address of the Flash sectors Bank 1 */
#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9     ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10    ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11    ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */

/* Base address of the Flash sectors Bank 2 */
#define ADDR_FLASH_SECTOR_12     ((uint32_t)0x08100000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_13     ((uint32_t)0x08104000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_14     ((uint32_t)0x08108000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_15     ((uint32_t)0x0810C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_16     ((uint32_t)0x08110000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_17     ((uint32_t)0x08120000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_18     ((uint32_t)0x08140000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_19     ((uint32_t)0x08160000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_20     ((uint32_t)0x08180000) /* Base @ of Sector 8, 128 Kbytes  */
#define ADDR_FLASH_SECTOR_21     ((uint32_t)0x081A0000) /* Base @ of Sector 9, 128 Kbytes  */
#define ADDR_FLASH_SECTOR_22     ((uint32_t)0x081C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_23     ((uint32_t)0x081E0000) /* Base @ of Sector 11, 128 Kbytes */
  • 第二部分:读、写、擦除
// Read data from flash.
int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size);

// Write data to flash.
int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size);

// Erase data on flash.
int stm32_flash_erase(rt_uint32_t addr, size_t size);
  • 第三部分:修改drv_flash_f4.c的宏定义
//芯片型号:STM32407xE
//起始地址
#define STM32_FLASH_START_ADRESS_16K        ADDR_FLASH_SECTOR_0
#define STM32_FLASH_START_ADRESS_64K        ADDR_FLASH_SECTOR_4
#define STM32_FLASH_START_ADRESS_128K       ADDR_FLASH_SECTOR_5

//大小
#define FLASH_SIZE_GRANULARITY_16K          (4*16*1024)         // 4个16K
#define FLASH_SIZE_GRANULARITY_64K          (64*1024)           // 1个64K
#define FLASH_SIZE_GRANULARITY_128K         (3*128*1024)        // 3个128K

const struct fal_flash_dev stm32_onchip_flash_16k = { "onchip_flash_16k", STM32_FLASH_START_ADRESS_16K, FLASH_SIZE_GRANULARITY_16K, (16 * 1024), {NULL, fal_flash_read_16k, fal_flash_write_16k, fal_flash_erase_16k} };
const struct fal_flash_dev stm32_onchip_flash_64k = { "onchip_flash_64k", STM32_FLASH_START_ADRESS_64K, FLASH_SIZE_GRANULARITY_64K, (64 * 1024), {NULL, fal_flash_read_64k, fal_flash_write_64k, fal_flash_erase_64k} };
const struct fal_flash_dev stm32_onchip_flash_128k = { "onchip_flash_128k", STM32_FLASH_START_ADRESS_128K, FLASH_SIZE_GRANULARITY_128K, (128 * 1024), {NULL, fal_flash_read_128k, fal_flash_write_128k, fal_flash_erase_128k} };

4、fal_cfg.h文件编写

  • 在driver文件的include下添加fal_cfg,h文件:
    在这里插入图片描述

  • 可以添加多个块进行读写,多个块地址不能交叉,但注意擦除是以扇区进行擦除的。添加代码:

#ifndef APPLICATIONS_FAL_CFG_H_
#define APPLICATIONS_FAL_CFG_H_

#include <rtconfig.h>
#include <board.h>

/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash_16k;
extern const struct fal_flash_dev stm32_onchip_flash_64k;
extern const struct fal_flash_dev stm32_onchip_flash_128k;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                 \
{                                           \
    &stm32_onchip_flash_16k,                \
    &stm32_onchip_flash_64k,                \
    &stm32_onchip_flash_128k,               \
}

/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG

/* partition table */
#define FAL_PART_TABLE                                                                      \
{                                                                                           \
    {FAL_PART_MAGIC_WORD,"part1","onchip_flash_16k",    0            ,   4*16*1024  , 0},   \
    {FAL_PART_MAGIC_WORD,"part2","onchip_flash_64k",    0            ,   1*64*1024  , 0},   \
    {FAL_PART_MAGIC_WORD,"part3","onchip_flash_128k",   0            ,   2*128*1024 , 0},   \
    {FAL_PART_MAGIC_WORD,"part4","onchip_flash_128k",   2*128*1024   ,   1*128*1024 , 0},   \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* APPLICATIONS_FAL_CFG_H_ */

二、Flash读写验证

  1. flash.c文件
#include "flash.h"
#include "power.h"
#include "adc.h"

/*======================================================###### 宏定义 ######==================================================*/
const data_info_t Flash_Data_Deal[] =
{
    {"temp",        2, &g_power.temp},
};

// 定义一个GPIO引脚初始化列表计数值
const rt_uint32_t Flash_Data_CNT = ARRAY_CNT(Flash_Data_Deal);
/*=====================================================#######  END  #######=================================================*/

/*======================================================### 静态函数调用 ###==================================================*/
/**
 * @brief 读取数据处理
 */
static void Read_Data_Deal(void)
{
    for (int i = 0; i < Flash_Data_CNT; ++i)
    {
        *Flash_Data_Deal[i].variable =  (g_flash.buff[Flash_Data_Deal[i].index * 2] << 8) +
                                        (g_flash.buff[Flash_Data_Deal[i].index * 2 + 1]);
    }
}

/**
 * @brief 更新数据处理
 */
static void Update_Data_Deal(void)
{
    for (int i = 0; i < Flash_Data_CNT; ++i)
    {
        g_flash.buff[Flash_Data_Deal[i].index * 2] = (*Flash_Data_Deal[i].variable) >> 8;
        g_flash.buff[Flash_Data_Deal[i].index * 2 + 1] = (*Flash_Data_Deal[i].variable);
    }
}

/**
 * @brief flash读取数据
 */
static void Flash_Read_Data(void)
{
    // 查找flash分区
    g_flash.config_info = fal_partition_find(FLASH_DEVICE_BLK);

    // 读取数据
    fal_partition_read(g_flash.config_info, 0, g_flash.buff, FLASH_DATA_BUFFER_SIZE);
}

/*=====================================================#######  END  #######=================================================*/

/*======================================================##### 外部调用 #####==================================================*/
/**
 * @brief 读取flash偏移地址
 */
int Flash_Read_Offset_Addr(void)
{
    uint8_t buff[ONE_DATA_NUM] = {0};

    // 查找flash分区
    g_flash.config_info = fal_partition_find(FLASH_DEVICE_BLK);

    for (int i = 0; i < FIND_ADDR_COUNT; ++i)
    {
        // 读取偏移地址
        fal_partition_read(g_flash.config_info, i * ONE_DATA_NUM, buff, ONE_DATA_NUM);

        // 数据验证
        if (buff[0] == buff[1] && buff[0] == 0xFF)
        {
            return i * ONE_DATA_NUM;
        }
    }

    // 擦除分区
    fal_partition_erase(g_flash.config_info, 0, FLASH_PARTITION_SIZE);

    return 0;
}

/**
 * @brief 根据地址写入指定长度的数据
 * @param data: 写入的错误信息
 */
void Flash_Write_Data_Addr(uint16_t data, uint32_t time)
{
    uint8_t buff[ONE_DATA_NUM] = {0};
    int addr = Flash_Read_Offset_Addr();

    buff[0] = time >> 16;
    buff[1] = time >> 8;
    buff[2] = time;
    buff[3] = data >> 8;
    buff[4] = data;

    // 写入数据
    fal_partition_write(g_flash.config_info, addr, buff, ONE_DATA_NUM);
}

/**
 * @brief flash读取数据并处理
 */
void Flash_Read_Data_Deal(void)
{
    // 读数据
    Flash_Read_Data();

    // 数据处理
    Read_Data_Deal();
}

/**
 * @brief flash写数据
 */
void Flash_Write_Data(void)
{
    // 读取数据
    Flash_Read_Data();

    // 更新数据
    Update_Data_Deal();

    // 擦除分区
    fal_partition_erase(g_flash.config_info, 0, FLASH_PARTITION_SIZE);

    // 写入数据
    fal_partition_write(g_flash.config_info, 0, g_flash.buff, FLASH_DATA_BUFFER_SIZE);
}

/**
 * @brief flash读写测试
 */
void Flash_Read_Write_Test(void)
{
    fal_init();

    // 读数据
    Flash_Read_Data();
    LOG_E("read config data...\n");
    for (int i = 0; i < 6; ++i)
    {
        printf("%2x ", g_flash.buff[i]);
    }
    printf("\n");

    // 数据处理
    Read_Data_Deal();
    LOG_E("read data deal...\n");
//    printf("%d %d %d\n", g_power.output_vol, g_power.output_curr, g_power.temp);

    g_power.output_vol = 165;
    g_power.output_curr = 65231;
    g_power.temp = 479;

    // 写数据
    Flash_Write_Data();
    LOG_E("write data end...\n");
    for (int i = 0; i < 6; ++i)
    {
        printf("%2x ", g_flash.buff[i]);
    }
    printf("\n");

    LOG_E("write data deal...\n");
//    printf("%d %d %d\n", g_power.output_vol, g_power.output_curr, g_power.temp);
}
/*=====================================================#######  END  #######=================================================*/
  1. flash.h文件
#ifndef APPLICATIONS_INC_FLASH_H_
#define APPLICATIONS_INC_FLASH_H_

#include <rtthread.h>
#include <drv_common.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <fal.h>
#include "sys_string.h"

/**=====================================================###### 宏定义 ######==================================================*/
#define FLASH_DEVICE_BLK              "part4"           // flash存储分区4
#define FLASH_DEVICE_BLK5             "part5"           // flash存储分区5

#define FLASH_DATA_BUFFER_SIZE        50                // 数据缓冲区大小,一个数据使用两位,50则是存储25个数据
#define ONE_DATA_NUM                  5                 // 一组数据的个数
#define FIND_ADDR_COUNT               26214             // 寻址次数
#define FLASH_PARTITION_SIZE          (128 * 1024)      // flash分区大小
/**====================================================#######  END  #######=================================================*/

/**=====================================================### 全局变量定义 ####=================================================*/
// 数据处理结构体
typedef struct
{
    const char *name;                           // 变量名字
    uint16_t   index;                           // 序号
    uint16_t   *variable;                       // 变量

} data_info_t;

// flash结构体
typedef struct
{
    const struct fal_partition *config_info;    // flash结构体
    uint8_t buff[FLASH_DATA_BUFFER_SIZE];       // 接收数据缓冲区

    uint8_t save_flag;                          // 存储标志

} flash_info_t;

flash_info_t g_flash;
/**====================================================#######  END  #######=================================================*/

/**==================================================##### 函数及变量声明 #####===============================================*/
extern int Flash_Read_Offset_Addr(void);                            // 读取flash偏移地址
extern void Flash_Write_Data_Addr(uint16_t data, uint32_t time);    // 根据地址写入指定长度的数据

extern void Flash_Read_Data_Deal(void);                 // flash读取数据并处理
extern void Flash_Write_Data(void);                     // flash写数据
extern void Flash_Read_Write_Test(void);                // flash读写测试
/**====================================================#######  END  #######=================================================*/

#endif /* APPLICATIONS_INC_FLASH_H_ */

三、数据验证

  1. 设备开机初始化

  2. 通过串口助手发送读写指令进行数据的读写
    在这里插入图片描述
    在这里插入图片描述

四、参考链接

======》官方FAL组件库学习
======》FAL组件库参考博客

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值