stm32 HAL库 Flash操作简介

目录

stm32的hal库确实提供有关flash的操作代码库,,但是我们在操作flash之前依旧需要对stm32的flash进行简单的介绍。
首先,stm32的flash读不限制次数,写大约100 0000次,也就是说一天对同一个地方写100次,你需要大约20年才能写坏,所以可以你可以放心大胆的写。
其次,对于flash的操作代码也储存在flash中,也就是说如果你的写块覆盖掉了你的原始代码,你的程序可能出现未知的错误。
最后,flash的读写操作在一定程度上的修正,可以有效的实现代码的边运行变更新,当然有人意识到这就是iap,但是我不这么认为,iap至少需要bootloaer启动不同的代码块,而采用这种操作可以在运行状态下修正部分常量。例如,如果你的某段控制代码或者运行代码的某些参数并非是最优的,需要在运行中调节,你就可以通过指定该常量的存储地址并且在之后的运行与自我修正中不停 的覆盖,就可以闪现代码的自我优化。
stm32HAL库提供的flash操作库

第一stm32,flash介绍

stm32的烧录后的程序起始地址是从 0x0800 0000开始的,但是起始地址是从0x0000 0000,根据芯片名字及明面规则计算可用flash的结束地址。
在这里插入图片描述
对照下图的内存映射表就可以看出内存的开始与结束位置
在这里插入图片描述

查看代码段,以判断代码长度

一个编译完成的程序在下方会提示你代码长度,其中

Code 表示代码占用的空间 
RO-data表示(Read Only) 只读常亮的大小,如const		  型、字符串常量;
RW-data表示(Read Wirte) 已初始化的读写数据,程序中定义并且初始化的全局变量和静态变量位于此处
ZI-data表示(Zero Initialize) 未初始化的读写数据,程序中定义了但没有初始化的全局变量和静态变量

烧写入Flash中所占用的空间为:Code + RO-data + RW-data
程序运行时,芯片所占用的RAM空间为:RW-data + ZI-data
在这里插入图片描述
然后通过实际可用地址开始位置为0x0800 0000+烧写入Flash中所占用的空间
当然这种方法还学要计算比较麻烦,还有一种更为简单的查找方式,打开工程所属的文件夹,在右上角搜索中找到 .map开头文件
在这里插入图片描述
找到内存映射,将这两个求和就行了。
在这里插入图片描述

flash的基本操作规则

flash的成型以块(block)和扇区(sector)存在

STM32的flash在写的时候不能读,读的时候不能写,也就是说stm32在操作flash的时候程序必然是中止的,所以既不能响应中断,也不能有运行程序

During a write operation to the Flash memory, any attempt to read the Flash memory willstall the bus. The read operation will proceed correctly once the write operation hascompleted. This means that code or data fetches cannot be made while a write/eraseoperation is ongoing.For write and erase operations on the Flash memory(write/erase), the internal RC oscillator (HSI) must be ON.
The Flash memory can be programmed and erased using in-circuit programming and in-application programming.
中文翻译第一段话:在Flash写入操作过程中,任何试图读取Flash的操作都会锁定住总线,在完成Flash写操作之后读取Flash操作会继续执行,这意味着写入Flash期间无法访问Flash中的代码和数据。

极端情况下,如果想写FLASH时响应中断,唯有cortex-m从RAM中取指令能行的通,即写FLASH前,将响应中断的代码从FLASH拷入RAM中运行并将中断向量表设置到RAM即可。
flash的读可以从读写可以从任何地方开始,但是一次必须以半字,字,或者双字的方式来,但是flash的写之前如果该扇区存在数据,必须擦除整个扇区,再重写。

对照下面的表格可以找出你所有的可操作的stm32的扇区,不是你的代码段,又恰好在可用的flash扇区。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

stm32 HAL库 Flash操作指南

stm32 有一个与flash相关的寄存器FLASH Option Control Registers该寄存器提供了flash的读写保护以及中断响应flag等标识。

stm32f1xx_hal_flash.c

该文件用于基本的flash操作,提供了以下的方法对flash进行写操作与上锁解锁操作。

写操作

/** @addtogroup FLASH_Exported_Functions_Group1
  * @{
  */
/* IO operation functions *****************************************************/
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data); 
HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data);

/* FLASH IRQ handler function */
void       HAL_FLASH_IRQHandler(void);
/* Callbacks in non blocking modes */ 
void       HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue);
void       HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue);

上锁与解锁

/** @addtogroup FLASH_Exported_Functions_Group2
  * @{
  */
/* Peripheral Control functions ***********************************************/
HAL_StatusTypeDef HAL_FLASH_Unlock(void);
HAL_StatusTypeDef HAL_FLASH_Lock(void);
HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void);
HAL_StatusTypeDef HAL_FLASH_OB_Lock(void);
void HAL_FLASH_OB_Launch(void);
void FLASH_PageErase(uint32_t PageAddress); 

注意上面的最后一行代码,FLASH_PageErase该函数在擦除时没有检测并且置0忙标识位,使得该段flash一直状态忙,无法使用,所以在擦除页面时一定要使用下面文件中的HAL_FLASHEx_Erase函数

stm32f1xx_hal_flash_ex.c

flash擦除

/** @addtogroup FLASHEx_Exported_Functions_Group1
  * @{
  */
/* IO operation functions *****************************************************/
HAL_StatusTypeDef  HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError);
HAL_StatusTypeDef  HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit);

flash 寄存器操作

/** @addtogroup FLASHEx_Exported_Functions_Group2
  * @{
  */
/* Peripheral Control functions ***********************************************/
HAL_StatusTypeDef  HAL_FLASHEx_OBErase(void);
HAL_StatusTypeDef  HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit);
void               HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit);
uint32_t           HAL_FLASHEx_OBGetUserData(uint32_t DATAAdress);

代码实例

flash 读数据

uint16_t flash_read = *(__IO uint16_t*)( Flash_Add ); //读2字节
uint32_t flash_read = *(__IO uint32_t*)( Flash_Add );//读4字节

flash 擦除页

	uint32_t Flash_Add = 0x0800d000;
	FLASH_EraseInitTypeDef My_Flash;  //声明FLASH_EraseInitTypeDef 结构体为 My_Flash
	HAL_FLASH_Unlock();               //解锁Flash
            
   My_Flash.TypeErase = FLASH_TYPEERASE_PAGES;  //标明Flash执行页面只做擦除操作
   My_Flash.PageAddress = Flash_Add;  //声明要擦除的地址
   My_Flash.NbPages = 1;                        //说明要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最大页数-初始页的值)之间的值
            
   uint32_t PageError = 0;                    //设置PageError,如果出现错误这个变量会被设置为出错的FLASH地址
   HAL_FLASHEx_Erase(&My_Flash, &PageError);  //调用擦除函数擦除
   HAL_FLASH_Lock();

flash 写操作

	HAL_FLASH_Unlock();               //解锁Flash
   	uint16_t Write_Flash_Data = my_data;
   	HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Flash_Add, Write_Flash_Data); //对Flash进行烧写,FLASH_TYPEPROGRAM_HALFWORD 声明操作的Flash地址的16位的,此外还有32位跟64位的操作,自行翻查HAL库的定义即可
   	HAL_FLASH_Lock(); //锁住Flash
<think>好的,用户遇到了Keil编译STM32 HAL时出现的CreateProcess failed错误,需要帮助解决。首先,我需要回忆之前处理类似问题的经验,并参考提供的引用内容。根据引用[1]和[2],错误通常出现在调用外部工具如fromelf.exe或ArmCC时,路径或权限问题可能导致进程创建失败。 第一步,检查路径是否正确。用户提到的路径'E:\Keil 5\ARM\ARMCLANG\Bin\ArmCC'可能存在空格,比如“Keil 5”中的空格。Windows有时处理带空格的路径会有问题,需要用引号包裹路径。需要建议用户检查编译设置中的路径是否被正确引用。 第二步,权限问题。Keil可能需要管理员权限才能执行这些命令,尤其是当安装目录在Program Files下时。建议用户以管理员身份运行Keil,或者调整安装目录的权限。 第三步,检查工具链安装是否完整。可能ARMCLANG没有正确安装,或者某些组件缺失。重新安装或修复Keil的ARM编译器工具链可能会有帮助。 第四步,确认项目配置中的用户命令是否正确。比如在After Build步骤中的命令,是否正确调用了ArmCC,参数是否有误。需要用户检查Options for Target中的设置,特别是用户自定义命令的语法和路径。 第五步,防病毒软件或防火墙可能阻止了Keil创建进程。临时禁用这些软件,再尝试编译,看是否解决问题。 另外,可能需要检查环境变量是否设置正确,或者系统是否为64位而工具链是32位的情况,不过这种情况相对较少。还可以建议用户查看编译日志,确认具体的错误信息,是否有其他线索。 总结下来,可能的解决方案包括:路径处理、权限调整、工具链修复、命令检查以及安全软件设置。需要逐步排除这些可能性,用户可能需要逐一尝试这些步骤。</think>### Keil编译STM32 HAL出现CreateProcess failed错误的解决方案 #### 1. 检查路径格式与空格问题 - **问题描述**:当路径中包含空格(如`E:\Keil 5`)时,Windows可能无法正确解析命令行参数,导致外部工具调用失败。 - **解决方法**: 1. 在Keil的**Options for Target** → **User**选项卡中,检查**After Build**或**Before Build**的自定义命令。 2. **用英文引号包裹含空格的路径**,例如将`E:\Keil 5\ARM\ARMCLANG\Bin\ArmCC`改为`"E:\Keil 5\ARM\ARMCLANG\Bin\ArmCC"`[^1][^2]。 3. 示例修改: ``` fromelf.exe --bin -o ..\out\app.bin .\Objects\Project.axf → "C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe" --bin -o ..\out\app.bin .\Objects\Project.axf ``` #### 2. 验证工具链安装完整性 - **问题描述**:ARMCLANG或ARMCC组件未正确安装,导致系统找不到可执行文件。 - **解决方法**: 1. 打开Keil的**Pack Installer**,检查ARM Compiler是否已安装。 2. 若缺失,重新安装Keil的ARM工具链(通过安装包修复或更新)。 #### 3. 以管理员权限运行Keil - **问题描述**:若Keil安装目录(如`Program Files`)受系统权限保护,普通用户可能无法调用外部进程。 - **解决方法**: 1. 右键Keil图标,选择**以管理员身份运行**。 2. 如果问题解决,可永久设置Keil的兼容性属性为管理员模式。 #### 4. 检查防病毒软件拦截 - **问题描述**:部分安全软件可能误判Keil的编译工具为可疑程序。 - **解决方法**: 1. 临时关闭防病毒软件(如360、Windows Defender)。 2. 将Keil安装目录(如`E:\Keil 5`)加入白名单。 #### 5. 核对项目配置中的用户命令 - **问题描述**:用户自定义命令的语法错误(如参数顺序、文件路径错误)会导致进程创建失败。 - **解决方法**: 1. 进入**Options for Target** → **User**,检查以下内容: - 命令中的`.axf`文件路径是否与项目输出路径一致。 - 是否遗漏了必要的命令行参数(如`--bin`)。 2. 参考Keil官方文档验证命令格式[^1]。 #### 6. 修复环境变量 - **问题描述**:系统环境变量未包含ARM工具链路径,导致命令无法识别。 - **解决方法**: 1. 将ARMCLANG的路径(如`E:\Keil 5\ARM\ARMCLANG\Bin`)添加到系统环境变量`PATH`中。 2. 重启Keil并重新编译。 --- ### 示例修正后的用户命令 ```plaintext Before Build: "E:\Keil 5\ARM\ARMCLANG\Bin\ArmCC" --c99 -c ... After Build: "E:\Keil 5\ARM\ARMCC\Bin\fromelf.exe" --bin -o ..\out\app.bin .\Objects\Project.axf ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值