rt-thread V4.1.0 开启stm32f4开启片上flash
正点原子探索者F4使用片上Flash完整指南(RT-Thread Studio v2.2.8 + RT-Thread v4.1.0)
以下是在正点原子探索者F4开发板上使用片上Flash的详细步骤:
准备工作
-
硬件配置:
- 正点原子探索者F4开发板(主控STM32F407ZGT6)
- USB数据线连接PC和开发板
- 跳线帽设置:BOOT0置低电平(启动方式为Flash)
-
软件环境:
- RT-Thread Studio v2.2.8
- RT-Thread v4.1.0 BSP包(STM32F407-Explorer)
完整配置步骤
步骤1:创建项目
- 打开RT-Thread Studio
- 文件 → 新建 → RT-Thread项目
- 选择:
- 项目类型:基于开发板
- 开发板:搜索"Explorer-F4" → STM32F407-Explorer
- 工具链:ARM GCC
- RT-Thread版本:v4.1.0
- 点击完成创建项目
步骤2:启用片上Flash驱动
-
在项目资源管理器中打开"RT-Thread Settings"
-
左侧导航:Hardware → On-chip Peripheral
-
启用:
- [*] Enable On-Chip FLASH (BSP_USING_ON_CHIP_FLASH)
-
保存配置(Ctrl+S)
步骤3:配置FAL组件
- 在board目录下创建
fal_cfg.h文件:
fal_cfg.h 下配置flash分区表
/* board/fal_cfg.h */
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include <rtconfig.h>
#include <board.h>
/* ============== 片上Flash设备配置 =============== */
extern const struct fal_flash_dev stm32_onchip_flash;
//flash设备表
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32_onchip_flash, \
}
/* ============== 分区表配置 =============== */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "boot", "onchip_flash", 0, 128*1024, 0}, \
{FAL_PART_MAGIC_WORD, "app", "onchip_flash", 128*1024, 512*1024, 0}, \
}
#endif /* _FAL_CFG_H_ */
步骤4:修改片上Flash驱动
在board/ports目录下创建fal_flash_stm32f4_port.c:
#include <rtthread.h>
#include <rtdevice.h>
#include <fal.h>
/* STM32F407ZGT6 Flash布局 */
#define STM32_FLASH_START_ADDR 0x08000000
#define STM32_FLASH_SIZE (1024*1024)
/* 扇区地址 */
#define ADDR_FLASH_SECTOR_0 0x08000000U /* 16 KB */
#define ADDR_FLASH_SECTOR_1 0x08004000U /* 16 KB */
#define ADDR_FLASH_SECTOR_2 0x08008000U /* 16 KB */
#define ADDR_FLASH_SECTOR_3 0x0800C000U /* 16 KB */
#define ADDR_FLASH_SECTOR_4 0x08010000U /* 64 KB */
#define ADDR_FLASH_SECTOR_5 0x08020000U /* 128 KB */
#define ADDR_FLASH_SECTOR_6 0x08040000U /* 128 KB */
#define ADDR_FLASH_SECTOR_7 0x08060000U /* 128 KB */
#define ADDR_FLASH_SECTOR_8 0x08080000U /* 128 KB */
#define ADDR_FLASH_SECTOR_9 0x080A0000U /* 128 KB */
#define ADDR_FLASH_SECTOR_10 0x080C0000U /* 128 KB */
#define ADDR_FLASH_SECTOR_11 0x080E0000U /* 128 KB */
/* 扇区映射函数 */
static uint32_t get_sector(uint32_t address)
{
if ((address >= ADDR_FLASH_SECTOR_0) && (address < ADDR_FLASH_SECTOR_1))
return FLASH_SECTOR_0;
else if ((address >= ADDR_FLASH_SECTOR_1) && (address < ADDR_FLASH_SECTOR_2))
return FLASH_SECTOR_1;
else if ((address >= ADDR_FLASH_SECTOR_2) && (address < ADDR_FLASH_SECTOR_3))
return FLASH_SECTOR_2;
else if ((address >= ADDR_FLASH_SECTOR_3) && (address < ADDR_FLASH_SECTOR_4))
return FLASH_SECTOR_3;
else if ((address >= ADDR_FLASH_SECTOR_4) && (address < ADDR_FLASH_SECTOR_5))
return FLASH_SECTOR_4;
else if ((address >= ADDR_FLASH_SECTOR_5) && (address < ADDR_FLASH_SECTOR_6))
return FLASH_SECTOR_5;
else if ((address >= ADDR_FLASH_SECTOR_6) && (address < ADDR_FLASH_SECTOR_7))
return FLASH_SECTOR_6;
else if ((address >= ADDR_FLASH_SECTOR_7) && (address < ADDR_FLASH_SECTOR_8))
return FLASH_SECTOR_7;
else if ((address >= ADDR_FLASH_SECTOR_8) && (address < ADDR_FLASH_SECTOR_9))
return FLASH_SECTOR_8;
else if ((address >= ADDR_FLASH_SECTOR_9) && (address < ADDR_FLASH_SECTOR_10))
return FLASH_SECTOR_9;
else if ((address >= ADDR_FLASH_SECTOR_10) && (address < ADDR_FLASH_SECTOR_11))
return FLASH_SECTOR_10;
else /* >= 0x080C0000 */
return FLASH_SECTOR_11;
}
/* 初始化函数 */
static int init(void)
{
return 0;
}
/* 读函数 */
static int read(long offset, uint8_t *buf, size_t size)
{
uint32_t addr = stm32_onchip_flash.addr + offset;
memcpy(buf, (const void*)addr, size);
return size;
}
/* 写函数 */
static int write(long offset, const uint8_t *buf, size_t size)
{
uint32_t addr = stm32_onchip_flash.addr + offset;
HAL_StatusTypeDef status;
if (HAL_FLASH_Unlock() != HAL_OK)
return -1;
for (size_t i = 0; i < size; i++)
{
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
addr + i,
buf[i]);
if (status != HAL_OK)
{
HAL_FLASH_Lock();
return -1;
}
}
if (HAL_FLASH_Lock() != HAL_OK)
return -1;
return size;
}
/* 擦除函数 */
static int erase(long offset, size_t size)
{
HAL_StatusTypeDef status;
size_t erased_size = 0;
uint32_t addr = stm32_onchip_flash.addr + offset;
if (HAL_FLASH_Unlock() != HAL_OK)
return -1;
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
while (erased_size < size)
{
uint32_t sector = get_sector(addr + erased_size);
FLASH_EraseInitTypeDef erase_init = {
.TypeErase = FLASH_TYPEERASE_SECTORS,
.Sector = sector,
.NbSectors = 1,
.VoltageRange = FLASH_VOLTAGE_RANGE_3
};
uint32_t sector_error;
status = HAL_FLASHEx_Erase(&erase_init, §or_error);
if (status != HAL_OK)
{
HAL_FLASH_Lock();
return -1;
}
erased_size += (sector < 4) ? 16 * 1024 :
(sector == 4) ? 64 * 1024 : 128 * 1024;
}
if (HAL_FLASH_Lock() != HAL_OK)
return -1;
return size;
}
/* Flash设备定义 */
const struct fal_flash_dev stm32_onchip_flash =
{
.name = "onchip_flash",
.addr = STM32_FLASH_START_ADDR,
.len = STM32_FLASH_SIZE,
.blk_size = 16 * 1024, // 使用最小擦除块(16KB)
.ops = {init, read, write, erase},
.write_gran = 1 // 1字节写入粒度
};
步骤5:修改SConscript文件
确保在board/SConscript中添加驱动文件:
# 添加以下内容
if GetDepend(['BSP_USING_ON_CHIP_FLASH']):
src += Glob('ports/fal_flash_stm32f4_port.c')
# 或者
# src += ['ports/fal_flash_stm32f4_port.c']
步骤6:初始化FAL
在application目录下的main.c中添加:
#include <fal.h>
#include <rtthread.h>
int main(void)
{
/* 初始化FAL */
fal_init();
/* 打印分区表 */
const struct fal_partition *part;
part = fal_partition_find("param");
if (part != RT_NULL)
{
rt_kprintf("Found param partition! Size: %d\n", part->len);
}
return RT_EOK;
}
步骤7:配置时钟
确保系统时钟配置正确(180MHz),在board/CubeMX_Config/Src/main.c中:
// 确保Flash等待状态设置为5(180MHz时需要)
__HAL_RCC_FLASH_CLK_ENABLE();
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_5); // 关键设置!
编译与测试
步骤8:编译与烧录
- 在RT-Thread Studio中:
- 项目 → 构建项目(Ctrl+B)
- 项目 → 烧录项目(Ctrl+D)
步骤9:测试Flash功能
- 打开串口终端(波特率115200)
- 在msh中输入以下命令测试:
# 查看FAL信息
msh >fal
FAL (Flash Abstract Layer) - flash partition info:
Partition | Flash device | Offset | Size
boot | onchip_flash | 0x00000000 | 131072
app | onchip_flash | 0x00020000 | 524288
# 擦除测试
msh >fal erase param 0 4096
Erase [param] from 0x00000000, size 4096: OK.
# 写入测试
msh >fal write param 0 "RT-Thread Flash Test!"
Write [param] from 0x00000000, size 21: OK.
# 读取验证
msh >fal read param 0 21
Read: 52 54 2D 54 68 72 65 61 64 20 46 6C 61 73 68 20 54 65 73 74 21
String: RT-Thread Flash Test!
常见问题解决
-
擦除/写入失败:
- 确认
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_5) - 检查Flash解锁顺序
- 验证地址范围在有效分区内
- 确认
-
分区未被识别:
- 检查
fal_cfg.h中的设备名称和分区名称匹配 - 确认
.blk_size设置正确(必须是最小擦除块大小)
- 检查
-
编译错误:
// 在stm32f4xx_hal_conf.h中启用Flash模块 #define HAL_FLASH_MODULE_ENABLED -
性能优化:
// 使用字/双字编程提高写入速度 HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, (uint32_t)data); -
低功耗优化:
// 操作完成后降低等待状态 __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_2); // 在降频后设置
通过以上步骤,您可以在正点原子探索者F4开发板上成功使用片上Flash进行数据存储、固件升级等操作。
总结:
1.使用fal(Flash抽象管理层) 来统一接口管理 Flash 设备,提供分区划分能力。其可以将多种flash,诸如片上flash和spi Flash等进行抽象为Init()/read()/write()/erase()等接口,并提供了类似诸如C/D/E/F等分区划分能力,以便在嵌入式系统中,将Flash划分为不同功能的分区,如bootload,app,log等分区。
2.对于分区表配置信息,需要在fal_cfg.h文件中,进行定义。
3.当使用片上Flash时,需要根据不同MCU的片上Flash大小和分布信息对Flash进行配置,还有需要开发者实现片上Flash的Init()/read()/write()/erase()等接口的底层驱动实现。如fal_flash_stm32f4_port.c
4、如使用spi Flash时,可以使用sfud驱动来控制SPI Flash,然后,将分区表配置信息在fal_cfg,h中进行配置。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)