STM32标准库内部Flash读写
STM32标准库FLASH读写
1. STM32内部FLASH介绍
STM32系列一般集成有内部flash,这部分内存可以直接通过指针的形式进行读取。但是由于内部flash一般存储为重要数据或程序运行数据,在进行写入或擦除时需要使用库函数的解锁和上锁函数进行读写。在STM32中,内部flash大致可以分为下图的几部分:

图1.1.STM32内部flash示意图
1.1. 主存储器
这部分为正常存储区,负责存储片上程序,若片上存储区充足,则可将某些需要掉电保存的数据存储至空闲区段。
判断片上程序截止位置可以通过查看项目的map文件来查看,具体方法为
双击keil左侧的项目文件夹打开项目map文件:

图1.2.map文件寻找
在map文件中找到Memory Map of the image这个表:

图1.3.内存加载表
在这个表的最后一行找到这么一段:

图1.4.内存占用位置
其中的load base的值就是片上程序的截止位置,从这里到片上flash的寻址结束都是可以用作数据存储的空闲空间。
1.2. 系统存储区
这部分为固定数据,不可修改擦除。所存储数据为芯片厂家出厂时保存的数据,用于ISP烧录功能等,相当于linux系统中的MMU,进行内存寻址等功能。
1.2. 选项字节
该区域用于配置片上flash的读写保护、待机/停机复位、软件硬件看门狗等功能,可以通过修改FLASH的的选项控制寄存器修改。
2. FLASH存储常见问题
在常见的FLASH芯片以及芯片片上FLASH中通常会仅允许FLASH页擦除,word写入或halfword写入。
页,是FLASH芯片中存储数据的最小单位。在某些芯片的资料中,也可能扇区是最小单位,
扇区与页的大小要根据芯片厂家资料的具体划分来看。FLASH的擦除操作最小单位只能是页,而写入单位为word或halfword,读取方式为以指针形式读取。这就出现了第一个矛盾:擦除量远大于写入量,而且由于FLASH是分页存储,若每次写入都擦除的话会导致上次的写入丢失。因此我的建议是给页或程序需要保存的数据建立一个页缓冲区,每次写入前先将数据写入缓冲区,然后一次性将缓冲区内的数据写入FLASH。可以减少数据丢失的问题。
FLASH是分页存储的,这就引发了第二个矛盾,若有一个数据横跨两个页面怎么读取写入,FLASH官方禁止跨页读写,且数据严格要求对齐。即在32位计算机中,若最小写入单位为word,写入的地址就只能为4的倍数,若最小写入单位为halfword,写入的地址就只能为2的倍数。不符合倍数要求的数据无法进行正常写入
3. 具体函数编写思路
野火的代码洋洋洒洒一大篇,但是我感觉不适合初学者,所以我对其进行了简化。
首先需要进行头文件引入与预编译变量定义:
#include "stm32f10x_flash.h"
#include "math.h"
#define FLASH_PAGE_SIZE ((uint16_t)0x800)//2048
#define WRITER_START_ADDR ((uint32_t)0x08008000)
#define WRITER_END_ADDR ((uint32_t)0x0800c000)
其中FLASH_PAGE_SIZE为片上flash每一页的大小,我所使用的芯片为STM32F103VET6,属于大容量,每一页的大小为2048字节。这个变量在正常读写时不使用,但是大批量擦除内存时可以使用这个变量编写函数。
引用math.h是为了使用floor函数,用于向下取整。
3.1. 写入函数
void flash_write_word(uint32_t data,uint32_t addr)//data变量为32个二进制变量的数据,addr为地址偏移量,我认为在程序编写时对偏移量修改,好过记一大串的地址。
{
uint32_t addr_true = addr + WRITER_START_ADDR;//addr_true为起始地址+地址偏移量,为数据在flash的实际地址。
uint32_t erase_page = floorf((addr + WRITER_START_ADDR) / FLASH_PAGE_SIZE);//这里是为了得到要擦除的第几页,floorf函数用于向下取整。
FLASH_Unlock();//解锁flash。
FLASH_ErasePage(WRITER_START_ADDR+(erase_page*FLASH_PAGE_SIZE));//擦除实际地址所在页面的flash。
FLASH_ProgramWord(addr_true,data);//向实际地址写入数据,在实际应用中还会遇到halfword写入的情况,在这里不进行讨论。
FLASH_Lock();//锁定flash。
}
3.2. 读取函数
uint32_t flash_read_word(uint32_t addr)//addr为地址偏移量,返回的值为读取到的数据。
{
uint32_t addr_true = addr + WRITER_START_ADDR;//addr_true为起始地址+地址偏移量,为数据在flash的实际地址。
return (*(__IO uint32_t*)addr_true);//将addr_true变量指针化,得到flahs地址存储的数据。
}
(__IO uint32_t)addr_true 是C或C++代码中的一个类型转换和解引用操作。我们可以将其分解为几个部分来理解其含义:
__IO:这是一个宏定义,通常在嵌入式编程中使用,特别是在与硬件寄存器交互时。__IO通常表示“输入/输出”,意味着该变量或地址可以读写。在某些嵌入式系统中,为了优化性能,开发者可能会区分“只读”和“可读/写”的内存区域,并使用宏来标记它们。
uint32_t:这是一个无符号32位整数类型,定义在stdint.h或cstdint头文件中。它确保变量或指针指向的内存区域被解释为32位无符号整数。
(uint32_t)addr_true:这是一个类型转换(或称为类型转换)。它将addr_true(可能是一个void类型的指针或其他类型的指针)转换为指向uint32_t类型的指针。
:这是一个解引用操作。当应用于指针时,它会获取该指针指向的值。
因此,(__IO uint32_t*)addr_true 的整体意思是:首先,将addr_true转换为一个指向uint32_t类型的指针(并确保该内存区域是可读/写的),然后获取该指针指向的32位无符号整数值。
这种操作在嵌入式编程中非常常见,特别是当需要直接访问或修改硬件寄存器的值时。
STM32标准库内部Flash读写的更多相关文章
- STM32 对内部FLASH读写接口函数(转)
源:STM32 对内部FLASH读写接口函数 因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序. ...
- 单片机stm32零基础入门之--初识STM32 标准库
CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...
- STM32 标准库
CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...
- STM32标准库GPIO操作
STM32标准库GPIO操作 STM32任何外围设备的使用都分为两部分:初始化和使用.体现在代码上就是:(1)有一个初始化函数(2)main函数中的使用 1.初始化GPIO 初始化GPIO函数代码: ...
- 初识STM32标准库
1.CMSIS 标准及库层次关系 CMSIS 标准中最主要的为 CMSIS 核心层,它包括了: STM32标准库可以从官网获得: 在使用库开发时,我们需要把 libraries 目录下的库函数文件添加 ...
- STM32 对内部FLASH读写接口函数
因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序. 原理:先要把整页FLASH的内容搬到RAM中 ...
- STM32 标准库V3.5启动文件startup_stm32f10xxx.s分析
layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 前言 分析startu ...
- STM32 HAL库 UART 串口读写功能笔记
https://www.cnblogs.com/Mysterious/p/4804188.html STM32L0 HAL库 UART 串口读写功能 串口发送功能: uint8_t TxData[10 ...
- [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写
一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...
- STM32 标准库3.5修改默认外部8M晶振为16M晶振
ST官方标准库V3.5默认的外部晶振频率为8M,实际使用中外部晶振需要修改为16M: 经过实验,修改有效,具体的patch如下: 修改 HSE_VALUE 值 diff --git "a/L ...
随机推荐
- echarts使用transform缩放后导致图标模糊
echarts使用transform缩放后导致图标模糊 --的解决办法 当使用了transform: scale(x,y)缩放后致使echarts图表模糊.怎么解决这个问题呢? 第一种解决办法:将ca ...
- 【分享笔记】druid存储系统-思维导图
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu 公众号:一本正经的瞎扯 源于:<Druid实时大数据分析原理与实践>这本书的阅读笔记 ...
- mac接入两根网线
mac机接了USB扩展槽之后,扩展槽可以接入一根网线,机器自带一个网线口,这样就可以同时接入两根网线,为什么要这样做? 因为我所在的公司是分内外网的,研发的机器是内网环境,而打包机有时候需要联网,那么 ...
- TienChin 渠道管理-字典原理分析
在上一节当中,我们使用到了字典来进行翻译我们的渠道类型等等字段,那么这一节我们就来分析一下字典的原理. 从代码方面先开始分析,我们先来看一下字典的定义,我们是在如下图当中编写了我们的渠道类型,使用,p ...
- 【Java并发入门】01 并发编程Bug的源头
一.根本原因 「CPU.内存.磁盘之间的速度差异」 为了能同时执行多个任务,CPU 发展出时间片轮转.多核等 CPU 要从内存中读数据太慢了,所以给自己设置了缓存 CPU 读磁盘更慢了,所以可以让该线 ...
- 【若归】 【LGR-142-Div.4】洛谷入门赛 #13赛后反思
比赛链接:[LGR-142-Div.4]洛谷入门赛 #13 rk288,比前几次差(可能是因为rated?) A 十年OI一场空,不开long long见祖宗 #include<bits/std ...
- 解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考
壹 ❀ 引 在本周迭代bug修复工作中,遇到了两个比较头疼的bug(同一个客户所提),bug问题描述也很奇怪,客户表示产品的富文本编辑器里的代码块功能,在纯文本语言模式下贴特定代码进去有的看不见,有的 ...
- NC19995 [HAOI2015]树上操作
题目链接 题目 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- Linux中echo的作用
Linux echo命令 echo命令是一个内置在Bash中的shell,通常用于shell脚本中以显示消息或输出其他命令的结果. echo命令的语法如下: 1 echo [-neE] [ARGUME ...
- 【OpenGL ES】渲染管线
1 前言 渲染管线是指图形渲染流程,涉及到的概念非常多,主要包含图元.片段.光栅化.空间.变换.裁剪.着色器.片段测试.混合等.渲染管线主体流程如下: 为方便读者理解渲染管线,本文将先介绍顶点 ...