笔者已经在前面的篇章中带领大家阅读了ST官方的Flash读写例程,本篇我们就将这个例程进行移植。
一、概述
- 本文的硬件实现平台:幻尔科技开源舵机控制器(STM32核心板)
- 本文的软件实现平台:Keil MDK v5.41(IDE)+ 基础开发课程\01 点亮LED灯例程工程源码
二、操作步骤
2.1 源码移植
2.1.1 main.h
-
在原例程中,将MCU的Flash从0x08000000开始的地址,按页为单位,进行对应宏的声明,并将这些自定义宏放于
main.h,方便用户快速访问各页的起始地址。 -
我们将
main.h中这部分的宏直接移植到正在开发的工程的main.h文件中专门用户存放用户自定义宏的区域,如下图。 -
原例程与正在开发的工程均采用STM32F103RB系列,因此Flash大小一致,可以直接无缝移植使用,若用户使用的其他型号的MCU,Flash容量可能更大或更小,需要用户根据情况删减或者增加这一部分的宏。
2.1.2 main.c
-
在原例程中,区域①中宏定义了用户自定义读写区的起始与结束地址、自定义写入内容,可以直接移植到开发工程
main.h的用户自定义宏的区域。 -
在原例程中,区域②中宏定义了Flash擦除操作结构体对象(HAL库官方结构体)、用于读写过程中的若干变量,也可以直接移植到开发工程
main.h的用户自定义变量的区域。
-
进入
main函数,原例程的HAL_Init与SystemClock_Config在开发工程中也有,这些是cubemx自动生成的,在这里无需移植。 -
在区域③,原例程调用的是专用于配套开发板的LED初始化函数,没有移植意义,在这里我们保留开发工程原有封装的专用于幻尔科技开源舵机控制器的LED初始化函数
led_init即可。 -
在区域④,配置擦除操作结构体对象,并调用HAL库官方的Flash解锁函数
HAL_FLASH_Unlock、擦除Flash函数HAL_FLASHEx_Erase,实现解锁并擦除Flash的效果,可以直接移植。 -
在区域⑤,原例程调用的是专用于配套开发板的LED控制函数,实现点亮100ms熄灭200ms的效果,没有移植意义,在这里我们保留开发工程原有封装的专用于幻尔科技开源舵机控制器的LED闪烁函数
led_flash即可(默认使用1号ID的LED),该函数的定义如下(见led_porting.h),将参数2点亮时长修改为100,参数3熄灭时长修改为2000,参数4循环次数修改为1;再在后面调用HAL_Delay函数等长延时2100ms,即可等效实现。
void led_flash(uint8_t id, uint32_t ticks_on, uint32_t ticks_off, uint16_t times)
-
在区域⑥与⑧,调用HAL库官方的Flash锁定函数
HAL_FLASH_Unlock、Flash写入函数HAL_FLASH_Program,实现写入Flash并重新上锁保护的效果,可以直接移植。 -
在区域⑦,原例程调用的是专用于配套开发板的LED控制函数,实现点亮100ms熄灭200ms的效果,没有移植意义,我们已经在第6点讲解了处理方法,这里不在赘述。
-
后续的程序用于将Flash地址强制转换为指针并访问对应地址的数据,校验写入情况,这一部分是纯C语言语法,可以直接移植并覆盖开发工程中红框所示的原程序逻辑。
-
内部区域⑨与⑩为原例程调用的是专用于配套开发板的LED控制函数,分别LED常亮、实现点亮100ms熄灭200ms的效果,没有移植意义,后者我们已经在第6点讲解了处理方法。前者控制LED常亮的功能,我们可以在开发工程的文件
led_porting.h中找到对应效果函数,该函数定义如下,将参数1LED灯ID设置为1,即可等效实现。
void led_on(uint8_t id)
- 至此,代码移植工作就告一段落了~
2.2 工程配置
- 打开“Options for Target…”。
- 在Target标签页,将工程on-chip IROM1(片上ROM区)的起始地址为0x8000000,大小为0xC000(0x800C000开始为用户读写区)。
- 编译工程,可以看到输出如下,Flash中程序与只读数据大小=17234+338=17525=0x4475,没有侵入用户自定义读写区,我们在第2点中的设置是合理可行的。
三、程序验证
3.1 实物验证
- 将程序下载烧录至安装在幻尔科技开源舵机控制器的STM32核心板,可以观察到,LED1(对应id为1的LED灯)上电后一段时间后开始常亮,表示Flash擦除、写入、读取验证一切正常。
3.2 软件验证(可选)
- 将J-LINK调试器接入STM32核心板的调试口(对应关系如下表),并接入电脑。
| 调试器接口 | STM32核心板接口 |
|---|---|
| SWCLK | DCLK |
| SWDIO | DIO |
| GND | GND |
| 3V3 | 3V3 |
- 打开JFlash软件。
需要提前下载SEGGER的JLink软件,JFlash为JLink内含软件之一,此处相关下载安装不做展开,可自行检索教程
- 在界面中选择“Create new project(新建工程)”,再点击“Start J-Flash”开始配置。
- 点击"…"选择芯片型号。
- 在Device栏输入关键词“STM32F103RB”,双击对应弹出项即可选择。
- 点击“ok”,即可完成配置。
- 在Target选项卡中,点击“Connect”,连接接入电脑的调试器。
- 连接成功后,在Target选项卡中,点击“Manual Programming(手动编程)”,点击“Read back(Flash回读)”,三个选项理论上都可以选择,我们在这里选择“Range…(范围读取)”。
- 将读取范围设定为用户自定义读写区起始地址。
#define FLASH_USER_START_ADDR ADDR_FLASH_PAGE_48 /* Start @ of user Flash area ((uint32_t)0x0800C000) */
#define FLASH_USER_END_ADDR ADDR_FLASH_PAGE_127 + FLASH_PAGE_SIZE /* End @ of user Flash area ((uint32_t)0x08020000) */
- 软件开始读取Flash数据并显示到界面,我们点击“4”图标,将读取数据按4字节(word,一个字)为单位显示方便观察,最终界面如下,可以看到显示数据与我们写入的数据完全一致,打完收工~
#define DATA_32 ((uint32_t)0x12345678)
参考致谢:
纸上得来终觉浅,绝知此事要躬行~
下一期我们学习Flash的写保护开启与关闭操作,感谢你看到这里~
本期文档配套例程:
Demo_FLASH_EraseProgram.zip (31.1 MB)
















