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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662711.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在ESP32上使用MicroPython

ESP32是一款非常好用的物联网芯片&#xff0c;MicroPython可以充分利用ESP32的各种资源,本文会对MicroPython在ESP32上的应用进行说明&#xff0c;包括初始使用、提示信息、使用 WebREPL、连接网络与互联网通信、使用硬件外设以及控制外部组件等等。 准备开发板 在进行下面的…

PHP的线程安全与非线程安全模式选哪个

曾经初学PHP的时候也很困惑对线程安全与非线程安全模式这块环境的选择&#xff0c;也未能理解其中意。近来无意中看到一个教程对线程安全&#xff08;饿汉式&#xff09;&#xff0c;非线程安全&#xff08;懒汉式&#xff09;的描述&#xff0c;虽然觉得现在已经能够很明了透彻…

openlayers地图自定义图标打点(二)

1.效果 2.代码 结构,地图初始化同上篇 <template><div class"container">//地图结构<div id"map"></div></div> </template><script> //引入依赖项 import { Map, View } from ol import TileLayer from ol/l…

模板讲解之进阶

在之前的C入门的博客中我们就学习到了模板初阶&#xff0c;今天我们来学习模板的进阶&#xff0c;以便于更好地将模板运用到代码中 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的…

2024美赛C题思路/代码:网球中的动量

美赛直播b站&#xff0c;提前关注&#xff1a;川川菜鸟 美赛辅导预定&#xff1a;美赛服务 去年美赛C题&#xff1a;2023美赛C题 题目翻译 背景 在2023年温布尔登男子单打决赛中&#xff0c;20岁的西班牙新星阿尔卡拉兹击败了36岁的诺瓦克德约科维奇。这是德约科维奇自201…

关于v8垃圾回收机制联想到的知识点

对于值类型b来说&#xff0c;就直接释放了其占用的内存&#xff0c;对于引用类型obj来说&#xff0c;销毁的只是变量obj对堆内存地址 1001 的引用&#xff0c;obj的值 { c: 3 } 依然存在于堆内存中。那么堆内存中的变量如何进行回收呢&#xff1f; V8的垃圾回收策略主要是基于…

怎么录制屏幕视频?让你的视频脱颖而出

随着科技的飞速发展&#xff0c;录制屏幕视频已经成为人们日常学习和工作中不可或缺的技能。无论是制作教程、分享游戏高光时刻&#xff0c;还是保存线上会议的内容&#xff0c;屏幕录制都可以帮助我们更好地传达信息。可是怎么录制屏幕视频呢&#xff1f;本文将介绍两种录制屏…

手把手教你如何将项目发布到Maven中央仓库(附步骤及常见问题解决方法)

手把手教你如何将项目发布到Maven中央仓库(附步骤及常见问题解决方法) 业余时间写了个轻量级的权限控制框架 light-security &#xff0c;并发布到了 Maven 中央仓库。发布时的操作步骤还挺多&#xff0c;我这个记性是记不住的&#xff0c;所以记录一下&#xff0c;便于以后查…

【C++】 C++入门— 基于范围的 for 循环

C 基于范围的for循环1 使用样例2 使用条件3 完善措施 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 基于范围的for循环 1 使用样例 使用for循环遍历数组&#xff0c;我们通常这么写&#xff1a; …

3D打印、自动升降超静电机驱动方案TMC2209

TMC2209步进电机驱动芯片介绍 TMC2209是一款用于两相步进电机的超静音电机驱动IC。Trinamic的精密StealthChop波器确保了无噪音运行、最大效率和最佳电机转矩。它的快速电流调节和与SpreadCycle的可选组合允许高度动态运动&#xff0c;同时为无传感器归位添加了StallGuard4。集…

python中的可变与不可变、深拷贝和浅拷贝

个人猜想&#xff08;很遗憾失败了&#xff09; 在硬盘或者系统中存在一个字符集 如果存在硬盘中&#xff0c;那么硬盘出厂的时候他的字符集所占用的空间就已经确定了。 如果存在于系统的话&#xff0c;硬盘应该在出厂的时候为系统设置一个存储系统字符集的地方。在安装系统…

L1-019 谁先倒分数 15

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为&#xff1a;每人口中喊出一个数字&#xff0c;同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和&#xff0c;谁就输了&#xff0c;输家罚一杯酒。两人同赢或两人同输则继续下一轮&…

2024/2/4周报

文章目录 摘要Abstract文献阅读题目引言创新点方法利用长短期记忆网络学习时空演化特征构建用于气象辅助信息编码的堆叠自编码器使用多任务学习发现全市通用模式 模型实验数据集评估准则实验结果 深度学习Self-attentionself-Attention由来self-attention原理self attention代码…

【ArcGIS微课1000例】0100:ArcGIS for CAD软件下载与安装(附安装包)

ArcGIS for CAD软件下载与安装(附安装包)。 文章目录 一、ArcGIS for CAD概述1. ArcGIS for CAD介绍2. 主要功能二、ArcGIS for CAD下载三、ArcGIS for CAD安装1. 安装CAD2. 安装ArcGIS for CAD3. 配置一、ArcGIS for CAD概述 1. ArcGIS for CAD介绍 ArcGIS for CAD是Esri提…

《拳皇97》中的人物性格——陈可汗

在热血沸腾、高手如云的《拳皇97》世界里,有一位壮硕威猛却自带喜感的角色引人注目,他就是我们的重量级选手——陈可汗。这位来自中国的摔跤手以其独特的性格特质和生动活泼的表现方式,在激烈的格斗赛场上描绘出了一幅既令人捧腹又充满力量的画面。 陈可汗甫一登场,那魁梧的…

Acwing---2816. 判断子序列

判断子序列 1.题目2.基本思想3.代码实现 1.题目 给定一个长度为 n n n 的整数序列 a 1 , a 2 , … , a n a1,a2,…,an a1,a2,…,an 以及一个长度为 m m m 的整数序列 b 1 , b 2 , … , b m b1,b2,…,bm b1,b2,…,bm。 请你判断 a a a序列是否为 b b b序列的子序列。 子…

解锁影视制作新境界:DaVinci Resolve Studio 18引领行业变革

随着科技的不断发展&#xff0c;影视制作行业也在日新月异地变革。在这一进程中&#xff0c;DaVinci Resolve Studio 18以其卓越的性能和无限的创新力&#xff0c;成为了行业的领跑者。 DaVinci Resolve Studio 18是一款集剪辑、调色、音频处理和特效合成于一身的专业级影视制…

CICD注册和使用gitlab-runner常见问题

1、现象 fatal: unable to access https://github.com/homebrew/brew/: 2、解决 git config --global --unset http.proxy git config --global --unset https.proxy 查看gitlab-runner是否成功&#xff1a; userusers-MacBook-Pro ~ % gitlab-runner -h 查看gitlab-run…

openssl3.2 - 帮助文档的整理

文章目录 openssl3.2 - 帮助文档的整理概述笔记整理后, 非空的文件夹如下整理后, 留下的有点用的文件列表如下备注END openssl3.2 - 帮助文档的整理 概述 openssl3.2源码工程编译安装完, 对于库的使用者, 有用的文档, 远不止安装的那些html. 用everything查找, 配合手工删除,…

使用python-pandas对比两个结构相同的文件差异,并输出差集文件的方法

最近在处理数据相关需求&#xff0c;遇到一个问题&#xff1a;两个文件&#xff0c;fileA.csv和fileB.csv&#xff0c;结构相同&#xff0c;fileA包含fileB的内容&#xff0c;但是需要得到二者的差集&#xff0c;输出新的文件fileC。 经过查询资料&#xff0c;发现pandas可以很…