当前位置: 首页 > news >正文

HAL库配置片内FLASH读写

一、FLASH简介

        不同型号的 STM32F40xx/41xx,其 FLASH 容量也有所不同,最小的只有 128K 字节,最大
的则达到了 1024K 字节。我们的探索者开发板选择的是 STM32F407ZGT6 的 FLASH 容量为
1024K 字节。

        主存储器,存放代码和数据常数(如 const 类型的数据)。分为 12 个扇区,前 4个扇区为 16KB 大小,扇区 4 为 64KB 大小,扇区 5~11 为 128KB 大小,不同容量的 STM32F4,拥有的扇区数不一样。B0、B1 都接 GND 的时候,就是从 0x08000000 开始运行代码。
        系统存储器,存放 STM32F4 的 bootloader 代码,此代码在出厂的时候就固化在STM32F4 里面了,专门用来给主存储器下载代码的。当 B0 接 V3.3,B1 接 GND 的时候,从该存储器启动(即进入串口下载模式)。
        OTP 区域,即一次性可编程区域,总共 528 字节大小,被分成两个部分,前面 512 字节(32
字节为 1 块,分成 16 块),可以用来存储一些用户数据(一次性的,写完一次,永远不可以擦
除!!),后面 16 字节,用于锁定对应块。
        选项字节,用于配置读保护、BOR 级别、软件/硬件看门狗以及器件处于待机或停止模式下
的复位。 

二、闪存的 编程和擦除

        执行任何 Flash 编程操作(擦除或编程)时,CPU 时钟频率(HCLK)不能低于 1 MHz。如果
在 Flash 操作期间发生器件复位,无法保证 Flash 中的内容。在对 STM32F4 的 Flash 执行写入或擦除操作期间,任何读取 Flash 的尝试都会导致总线阻塞。只有在完成编程操作后,才能正确处理读操作。这意味着,写/擦除操作进行期间不能从 Flash中执行代码或数据获取操作。

三、代码

stmflash.c

#include "stmflash.h"
uint32_t stmflash_read_word(uint32_t faddr)
{return *(volatile uint32_t *)faddr;
}uint8_t  stmflash_get_flash_sector(uint32_t addr)
{if (addr < ADDR_FLASH_SECTOR_1) return FLASH_SECTOR_0;else if (addr < ADDR_FLASH_SECTOR_2) return FLASH_SECTOR_1;else if (addr < ADDR_FLASH_SECTOR_3) return FLASH_SECTOR_2;else if (addr < ADDR_FLASH_SECTOR_4) return FLASH_SECTOR_3;else if (addr < ADDR_FLASH_SECTOR_5) return FLASH_SECTOR_4;else if (addr < ADDR_FLASH_SECTOR_6) return FLASH_SECTOR_5;else if (addr < ADDR_FLASH_SECTOR_7) return FLASH_SECTOR_6;else if (addr < ADDR_FLASH_SECTOR_8) return FLASH_SECTOR_7;else if (addr < ADDR_FLASH_SECTOR_9) return FLASH_SECTOR_8;else if (addr < ADDR_FLASH_SECTOR_10) return FLASH_SECTOR_9;else if (addr < ADDR_FLASH_SECTOR_11) return FLASH_SECTOR_10;return FLASH_SECTOR_11;
}void stmflash_write(uint32_t waddr, uint32_t *pbuf, uint32_t length)
{FLASH_EraseInitTypeDef flasheraseinit;HAL_StatusTypeDef FlashStatus=HAL_OK;uint32_t addrx = 0;uint32_t endaddr = 0;uint32_t sectorerror=0;if (waddr < STM32_FLASH_BASE || waddr % 4 ||        /* 写入地址小于 STM32_FLASH_BASE, 或不是4的整数倍, 非法. */waddr > (STM32_FLASH_BASE + STM32_FLASH_SIZE))  /* 写入地址大于 STM32_FLASH_BASE + STM32_FLASH_SIZE, 非法. */{return;}HAL_FLASH_Unlock();             /* 解锁 */FLASH->ACR &= ~(1 << 10);       /* FLASH擦除期间,必须禁止数据缓存!!! */addrx = waddr;                  /* 写入的起始地址 */endaddr = waddr + length * 4;   /* 写入的结束地址 */if (addrx < 0X1FFF0000)         /* 只有主存储区,才需要执行擦除操作!! */{while (addrx < endaddr)     /* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */{if (stmflash_read_word(addrx) != 0XFFFFFFFF)    /* 有非0XFFFFFFFF的地方,要擦除这个扇区 */{flasheraseinit.TypeErase=FLASH_TYPEERASE_SECTORS;       /* 擦除类型,扇区擦除 */flasheraseinit.Sector=stmflash_get_flash_sector(addrx); /* 要擦除的扇区 */flasheraseinit.NbSectors=1;                             /* 一次只擦除一个扇区 */flasheraseinit.VoltageRange=FLASH_VOLTAGE_RANGE_3;      /* 电压范围,VCC=2.7~3.6V之间!! */if(HAL_FLASHEx_Erase(&flasheraseinit, &sectorerror) != HAL_OK) {break;/* 发生错误了 */}}else{addrx += 4;}FLASH_WaitForLastOperation(FLASH_WAITETIME);                 /* 等待上次操作完成 */}}FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME);             /* 等待上次操作完成 */if (FlashStatus==HAL_OK){while (waddr < endaddr)     /* 写数据 */{if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, waddr, *pbuf) != HAL_OK)  /* 写入数据 */{break;              /* 写入异常 */}waddr += 4;pbuf++;}}FLASH->ACR |= 1 << 10;          /* FLASH擦除结束,开启数据fetch */HAL_FLASH_Lock();               /* 上锁 */
}void stmflash_read(uint32_t raddr, uint32_t *pbuf, uint32_t length)
{uint32_t i;for (i = 0; i < length; i++){pbuf[i] = stmflash_read_word(raddr);    /* 读取4个字节. */raddr += 4; /* 偏移4个字节. */}
}
#ifndef __STMFLASH_H
#define __STMFLASH_H#include "main.h"/* FLASH起始地址 */
#define STM32_FLASH_SIZE        0x100000        /* STM32 FLASH 总大小 */
#define STM32_FLASH_BASE        0x08000000      /* STM32 FLASH 起始地址 */
#define FLASH_WAITETIME         50000           /* FLASH等待超时时间 *//* FLASH 扇区的起始地址 */
#define ADDR_FLASH_SECTOR_0     ((uint32_t )0x08000000)     /* 扇区0起始地址, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1     ((uint32_t )0x08004000)     /* 扇区1起始地址, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2     ((uint32_t )0x08008000)     /* 扇区2起始地址, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3     ((uint32_t )0x0800C000)     /* 扇区3起始地址, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4     ((uint32_t )0x08010000)     /* 扇区4起始地址, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5     ((uint32_t )0x08020000)     /* 扇区5起始地址, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6     ((uint32_t )0x08040000)     /* 扇区6起始地址, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7     ((uint32_t )0x08060000)     /* 扇区7起始地址, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8     ((uint32_t )0x08080000)     /* 扇区8起始地址, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9     ((uint32_t )0x080A0000)     /* 扇区9起始地址, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10    ((uint32_t )0x080C0000)     /* 扇区10起始地址,128 Kbytes */
#define ADDR_FLASH_SECTOR_11    ((uint32_t )0x080E0000)     /* 扇区11起始地址,128 Kbytes */uint32_t stmflash_read_word(uint32_t faddr);                             /* 读出字 */
void stmflash_write(uint32_t waddr, uint32_t *pbuf, uint32_t length);    /* 从指定地址开始写入指定长度的数据 */
void stmflash_read(uint32_t raddr, uint32_t *pbuf, uint32_t length);     /* 从指定地址开始读出指定长度的数据 */#endif

 四、测试代码

#define FLASH_SAVE_ADDR 0x08010000 /* 设置FLASH 保存地址(必须为4的整数倍,且其值要大于本代码所占用FLASH的大小 + 0X08000000) */const uint8_t g_text_buf[] = {"STM32 FLASH TEST"};
uint8_t datatemp[SIZE];stmflash_write(FLASH_SAVE_ADDR, (uint32_t *)g_text_buf, SIZE);
stmflash_read(FLASH_SAVE_ADDR, (uint32_t *)datatemp, SIZE);while(1)
{printf("%s\r\n",datatemp);HAL_Delay(1000);
}

相关文章:

HAL库配置片内FLASH读写

一、FLASH简介 不同型号的 STM32F40xx/41xx&#xff0c;其 FLASH 容量也有所不同&#xff0c;最小的只有 128K 字节&#xff0c;最大 的则达到了 1024K 字节。我们的探索者开发板选择的是 STM32F407ZGT6 的 FLASH 容量为 1024K 字节。 主存储器&#xff0c;存放代码和数据常数&…...

日志记录——单片机可执行文件合并

一&#xff1a;需求场景 现在有一片单片机&#xff0c;执行程序包括自定义boot和应用程序app, 在将打包好的固件给到生产是有以下问题&#xff0c;由于要通过jlink烧录boot&#xff0c;然后上电启动boot&#xff0c;通过boot烧录初始化程序&#xff0c;过程过于复杂&#xff0…...

2024数模美赛C题F题完整代码结果展示

C&#xff1a;Momentum in Tennis 实在精力有限&#xff0c;完整讲解可以移步去看我的讲解视频啦&#xff1a; 美赛C题每一问代码结果讲解及进度说明 F&#xff1a;Reducing lllegal Wildlife Trade 实在精力有限&#xff0c;完整讲解可以移步去看我的讲解视频啦&#xff1a; ​…...

H5调用安卓原生相机API案例

1、在activity_main.xml文件里添加webview标签 <WebViewandroid:id="@+id/webview"android:layout_width="match_parent"android:layout_height="match_parent"> </WebView> 2、AndroidManifest.xml(权限和活动声明) 开启访问…...

Java面试——计网篇

一、基础篇 1、 TCP/IP 网络模型 对于同一台设备上的进程间通信&#xff0c;有很多种方式&#xff0c;比如有管道、消息队列、共享内存、信号等方式&#xff0c;而对于不同设备上的进程间通信&#xff0c;就需要网络通信&#xff0c;而设备是多样性的&#xff0c;所以要兼容多…...

函数式接口当参数使用

如果函数式接口作为一个方法的参数&#xff0c;就以为着要方法调用方自己实现业务逻辑&#xff0c;常见的使用场景是一个业务整体逻辑是不相上下的&#xff0c;但是在某一个步骤有不同的逻辑&#xff0c;例如数据处理有不同的策略&#xff0c;如果有大量的if-els&#xff0c;或…...

全面详解Maven的配置文件settings.xml

全面详解Maven的配置文件settings.xml setting文件位置maven多仓库查找依赖的顺序大致如下&#xff1a;基本配置选项localRepository(本地仓库设置)mirrors(镜像设置)servers(服务器)Profiles(配置文件)Active Profiles(激活配置文件Profiles的Profile) Maven是一个用于构建和管…...

【Spring连载】使用Spring Data访问Redis(十四)----Redis Repositories

【Spring连载】使用Spring Data访问Redis&#xff08;十四&#xff09;----Redis Repositories 一、Core concepts二、Defining Repository Interfaces三、Creating Repository Instances四、Usage五、Object Mapping Fundamentals六、对象到Hash映射Object-to-Hash Mapping七、…...

小鹏汽车穿越“生死线”

文&#xff5c;刘俊宏编&#xff5c;王一粟 “颠覆与涅槃&#xff0c;颠覆自我与重新涅槃&#xff0c;让企业在变革中更完美的蜕变。” 2024新年伊始&#xff0c;小鹏汽车董事长兼CEO何小鹏对2023年的蜕变显然非常刻骨铭心。无论是在汽车新势力&#xff0c;还是放眼整个中国汽…...

AIPC专题:深耕笔电背光模组领域,AIPC与车载显示拉动公司成长

今天分享的是AIPC系列深度研究报告&#xff1a;《AIPC专题&#xff1a;深耕笔电背光模组领域&#xff0c;AIPC与车载显示拉动公司成长》。 &#xff08;报告出品方&#xff1a;东兴证券&#xff09; 报告共计&#xff1a;19页 公司深耕笔电背光模组&#xff0c;主要下游客户为…...

架构(十一)从0到1实现动态定时任务

一、引言 作者的平台项目最近需要实现一个功能&#xff0c;用户可选择这个任务什么时候执行&#xff0c;执行频率是什么&#xff1f; 这其实就是一个定时任务&#xff0c;只不过需要动态的&#xff0c;让用户自由选择。 二、原生实现 要实现这样的功能&#xff0c;可以直接依赖…...

Mybatis 批量插入数据 SQL

温故而知新&#xff0c;这里记录一下 案例1 批量插入时&#xff0c;xxxMapper.java 中方法的参数都必须是 List &#xff0c;泛型可以是 bean &#xff0c;也可以是 Map 。配合使用 mybatis 的 foreach 即可。示例如下&#xff1a; public Integer batchInsertDemo(List<D…...

【学员分享-考试心得】国产数据库潜力无限,云贝教育OBCP认证培训帮您解难题

近年来&#xff0c;随着国产化转型的推进&#xff0c;国外数据库的岗位需求逐渐减少&#xff0c;让许多IT从业者倍感压力。在这种情况下&#xff0c;了解国产数据库成为了求职市场上的竞争力。云贝老师们将聚焦于OceanBase、PostgreSQL、TDSQL等IT培训&#xff0c;探讨其对国产…...

【Mysql】事务的隔离级别与 MVCC

事务隔离级别 我们知道 MySQL 是一个 C/S 架构的服务&#xff0c;对于同一个服务器来说&#xff0c;可以有多个客户端与之连接&#xff0c;每个客户端与服务器连接上之后&#xff0c;就是一个会话&#xff08; Session &#xff09;。每个客户端都可以在自己的会话中向服务器发…...

MongoDB从入门到实战之MongoDB快速入门

前言 上一章节主要概述了MongoDB的优劣势、应用场景和发展史。这一章节将快速的概述一下MongoDB的基本概念&#xff0c;带领大家快速入门MongoDB这个文档型的NoSQL数据库。 MongoDB从入门到实战的相关教程 MongoDB从入门到实战之MongoDB简介&#x1f449; MongoDB从入门到实战…...

Linux服务详解

如有错误或有补充&#xff0c;以及任何改进的意见&#xff0c;请在评论区留下您的高见&#xff0c;同时文中给出大部分命令的示例&#xff0c;即是您暂时无法在Linux中查看&#xff0c;您也可以知道各种操作的功能以及输出 如果觉得本文写的不错&#xff0c;不妨点个赞&#x…...

闲聊电脑(4)硬盘分区

夜深人静&#xff0c;万籁俱寂&#xff0c;老郭趴在电脑桌上打盹&#xff0c;桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭&#xff1a;冰箱大哥&#xff0c;上次你说的那个“分区”和“格式化”是什么意思&#xff1f; 冰箱&#xff1a;分区么&#xff0c;就是分…...

光耦合器的结构与原理解析

光耦合器是一种重要的电光转换器件&#xff0c;广泛应用于电子设备、通信系统以及工业控制等领域。本文将深入分析光耦合器的结构与原理&#xff0c;旨在为读者提供清晰而全面的了解。 光耦合器作为一种关键的电子元件&#xff0c;扮演着信号隔离和传输的重要角色。它的设计结构…...

代码随想录day17--二叉树的应用5

LeetCode654.最大二叉树 题目描述&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后…...

跟着cherno手搓游戏引擎【19】抽象纹理

引入&#xff1a; 导入stb_image: GitHub - nothings/stb: stb single-file public domain libraries for C/C 下载复制stb_image.h的内容&#xff08;8000多行&#xff09;&#xff0c;然后粘到如图位置 stb_image.cpp: #include"ytpch.h" #define STB_IMAGE_IM…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...