[STM32 - 野火] - - - 固件库学习笔记 - - - 十五.设置FLASH的读写保护及解除

一、选项字节与读写保护

在这里插入图片描述

1.1 为什么要设置读写保护

防止内部FLASH中的程序被非法读取

在实际发布的产品中,STM32芯片的内部FLASH存储了控制程序。然而,如果不对内部FLASH采取任何保护措施,用户可以使用下载器直接读取其内容,并将其导出为bin或hex文件格式的代码副本。这可能导致别有用心的厂商利用该方法复制产品。为了防止这种情况,STM32芯片提供了多种方式来保护内部FLASH中的程序,防止其被非法读取。但在默认情况下,这些保护功能是未开启的。若要启用这些保护功能,需要修改内部FLASH选项字节(Option Bytes)中的相关配置。

1.2 选项字节的内容

选项字节是一段特殊的 FLASH 空间, STM32 芯片会根据它的内容进行读写保护配置,选项字节的构成如下图:

在这里插入图片描述

STM32F103 系列芯片的选项字节有 8 个配置项,即上表中的 USER、 RDP、 DATA0/1 及 WRP0/1/2/3,而表中带 n 的同类项是该项的反码,即 nUSER 的值等于 (~USER)、 nRDP 的值等于 (~RDP), STM32利用反码来确保选项字节内容的正确性

选项字节的 8 个配置项具体的数据位配置说明如下:

在这里插入图片描述

当nRST_STDBY设置为0时:只要成功执行进入待机模式指令,器件就会复位,而非进入待机模式。

在这里插入图片描述

1.2.1 RDP

设置读保护:修改选项字节的 RDP 位的值可设置内部 FLASH 为以下保护级别:

  • 0xA5:无保护;

    这是 STM32 的默认保护级别。在STM32芯片的默认保护级别下,内部FLASH没有任何读保护措施,读取其内容没有任何限制。这意味着第三方可以使用调试器等工具轻松获取芯片FLASH中存储的程序,并将其以bin或hex格式下载到另一块STM32芯片中。结合PCB抄板技术,他们可以轻易地复制出相同的产品。

  • 其它值:使能读保护;

    将RDP(Read Protection Level,读保护级别)配置为除0xA5以外的任意数值,都会启用读保护功能。在这种情况下,如果通过调试功能(例如使用下载器或仿真器)或者从内部SRAM启动,将无法对内部FLASH进行任何访问(包括读取、写入和擦除操作)。然而,如果STM32是从内部FLASH启动的,它仍然允许对内部FLASH进行任意访问。
    换句话说,任何试图从外部访问内部FLASH内容的操作都会被禁止。例如,无法通过下载器读取其内容,也无法编写一个从内部SRAM启动的程序来读取内部FLASH,因为这种操作会被阻止。相反,如果芯片是从内部FLASH启动的程序本身访问内部FLASH(例如程序中包含对内部FLASH某个地址的读取操作),则可以正常进行,不会受到限制。

当STM32芯片被设置为读保护后,内部FLASH的前4KB空间会被强制加上写保护。这意味着,即使是从FLASH启动的程序,也无法对这4KB空间进行擦除或写入操作。然而,对于前4KB以外的FLASH空间,读保护不会限制对其的擦除或写入操作。利用这一特性,可以编写IAP(In-Application Programming,应用程序内编程)代码来更新FLASH中的程序。

IAP的工作原理是通过某种通信接口(如UART、I2C、SPI等)接收外部设备发送的程序更新数据,然后利用内部FLASH的擦写功能将这些数据烧录到FLASH的指定区域(通常是前4KB之外的区域),从而实现应用程序的更新。这种原理类似于串口ISP(In-System Programming,系统内编程)程序下载功能。不过,ISP的接收数据和更新代码由ST公司提供,并存放在系统的存储区域;而IAP代码由用户自行编写,存放在用户自定义的FLASH区域,并且通信方式可以根据用户需求定制,只要能够接收数据即可。


解除读保护:当需要解除芯片的读保护时,要把选项字节的 RDP 位重新设置为 0xA5。

当解除读保护时,芯片会自动触发擦除主FLASH存储器的全部内容。这意味着解除保护后,原内部FLASH中的代码会丢失,从而防止降级后原内容被读取。
这种机制是为了确保在解除保护后,原有的程序代码不会被非法读取或复制。

如果设置了读保护后在代码中没有解除读保护,可以通过把(解除读保护的)代码写入到RAM中,在RAM中运行代码,进而解除读保护。


芯片被配置成读保护后根据不同的使用情况,访问权限如下图:

在这里插入图片描述

RAM自举:程序存储在STM32的内部SRAM中,并从SRAM中启动执行;
ROM自举:程序存储在STM32的系统存储器(System Memory)中,并从该区域启动。

1.2.2 Datax

Data字段是供用户自定义使用的存储区域,主要用于存储一些需要在掉电后仍能保留的配置信息或状态标志。

作用:

  • 1、存储存储用户自定义数据:

    • Data字段通常包含两个字节(Data0和Data1),位于选项字节的特定地址(例如0x1FFF F804和0x1FFF F806)。这些字节可以存储用户定义的任意数据。

    • 例如,可以用于存储固件版本号、设备配置参数或标志位,这些数据在设备掉电后仍能保留。

  • 2、用于固件升级:

    • 在固件升级过程中,Data字段可以用来存储升级标志位或状态信息,帮助设备在重启后判断是否需要继续执行升级操作。
  • 3、灵活的配置用途:

    • 由于Data字段的内容由用户定义,因此可以根据具体应用场景灵活使用。例如,可以用于存储设备的唯一标识符、校准参数或其他重要信息。

1.2.3 WRP

在这里插入图片描述

使用选项字节的 WRP0/1/2/3 可以设置主 FLASH 的写保护,防止它存储的程序内容被修改。

设置写保护

写保护的配置通常以4KB为单位进行设置。除了WRP3的最后一位较为特殊外,每个WRP选项字节的每一位都对应一个4KB的FLASH区域,用于控制该区域的写访问权限。

将对应的WRP位设置为0,即可对该4KB区域启用写保护。启用写保护后,被保护的主FLASH区域中的内容将无法通过任何方式被擦除或写入。

例如WRP0设置为11111110,那么页0、页1就不能写;为11111101,那么页2、页3就不能写。

需要注意的是,写保护仅限制写操作,不影响读操作的权限,读操作的权限则由前面介绍的读保护设置决定。

设置写保护

解除写保护的过程是写保护设置的逆操作。将对应的WRP位设置为1,即可解除对应4KB区域的写保护。

解除写保护后,主FLASH中的内容不会像解除读保护那样丢失,而是会保持原样,不会发生任何改变。

二、修改选项字节的过程

根据前面的说明,修改选项字节的内容可以修改读写保护的配置。然而,选项字节复位后的默认状态是==可读但被写保护==的。这与FLASH_CR寄存器的访问限制类似。

因此,要修改选项字节,需要先对FLASH_OPTKEYR寄存器写入解锁编码。由于修改选项字节时也需要访问FLASH_CR寄存器,因此还需要对FLASH_KEYR寄存器写入解锁编码。

修改选项字节的整个过程总结如下

  • 1、解除 FLASH_CR 寄存器的访问限制。

    • 先往 FPEC 键寄存器(FLASH_KEYR) 中写入 KEY1 = 0x45670123。

    • 再往 FPEC 键寄存器(FLASH_KEYR) 中写入 KEY2 = 0xCDEF89AB。

  • 2、解除对选项字节的访问限制。

    • 先往 闪存 OPTKEY 寄存器(FLASH_OPTKEYR) 中写入 KEY1 = 0x45670123。

    • 再往 闪存 OPTKEY 寄存器(FLASH_OPTKEYR) 中写入 KEY2 = 0xCDEF89AB。

  • 3、配置 FLASH_CR 的 OPTPG 位,准备修改选项字节。

  • 4、直接使用指针操作修改选项字节的内容,根据需要修改 RDP、 WRP 等内容。

  • 5、对于读保护的解除,由于它会擦除 FLASH 的内容,所以需要检测状态寄存器标志位以确认FLASH 擦除操作完成。

  • 6、若是设置读保护及其解除,需要给芯片重新上电复位,以使新配置的选项字节生效;对于设置写保护及其解除,需要给芯片进行系统复位,以使新配置的选项字节生效。

    • 解除读保护后需要给系统上电复位,如果是使用系统复位(NVIC_SystemReset)会出现不可预知的情况。

三、实验:设置读写保护及解除

// flash_rdprotect.c文件
#include "flash_rdprotect.h"

void Write_Protect(void)
{
	FLASH_Unlock();
	
	FLASH_EraseOptionBytes();	// 写之前要先擦除
	
	FLASH_EnableWriteProtection(FLASH_WRProt_AllPages);
	
	NVIC_SystemReset();			// 产生系统复位
}

void Write_Protect_Disable(void)
{
	FLASH_Unlock();
	
	FLASH_EraseOptionBytes();
	
	FLASH_EnableWriteProtection(0x00000000);
	
	NVIC_SystemReset();			// 产生系统复位
}

void Read_Protect(void)
{
	FLASH_Unlock();
	
	FLASH_EraseOptionBytes();
	
	FLASH_ReadOutProtection(ENABLE);
}

void Read_Protect_Disable(void)
{
	FLASH_Unlock();
	
	FLASH_EraseOptionBytes();
	
	FLASH_ReadOutProtection(DISABLE);
}
  • 为什么设置写保护写的值是0xffffffff、解除写保护写的值是0x00000000:

    FLASH_EnableWriteProtection函数中会对传进来的参数进行取反,将WRPx中的位设置为1则是不实施写保护。
    在这里插入图片描述

// flash_rdprotect.h文件
#ifndef __FLASH_RDPROTECT_H
#define __FLASH_RDPROTECT_H

#include "stm32f10x.h"

#define WRITE_PROTECT

void Write_Protect(void);
void Write_Protect_Disable(void);
void Read_Protect(void);
void Read_Protect_Disable(void);
	
#endif /* __FLASH_RDPROTECT_H */								
// main.c文件
#include "stm32f10x.h"
#include "bsp_key.h"
#include "usart.h"
#include "flash_rdprotect.h"

int main(void)
{
	KEY1_GPIO_Config();
	KEY2_GPIO_Config();
	
	USART_Config();
	
	#ifdef WRITE_PROTECT
	printf("写保护状态:0x%08x \r\n", FLASH_GetWriteProtectionOptionByte());
	#else
	printf("写保护状态:0x%x \r\n", FLASH_GetReadOutProtectionStatus());
	#endif
	
	
	while(1)
	{
		if(KEY_Scan(KEY1_PROT, KEY1_Pin) == KEY_ON)
		{
			#ifdef WRITE_PROTECT
			printf("即将实施写保护 \r\n");
			
			Write_Protect();
			#else
			printf("即将实施读保护 \r\n");
			
			Read_Protect();
			#endif
		}
		
		if(KEY_Scan(KEY2_PROT, KEY2_Pin) == KEY_ON)
		{
			#ifdef WRITE_PROTECT
			printf("即将解除写保护 \r\n");
			
			Write_Protect_Disable();
			#else
			printf("即将解除读保护 \r\n");
			
			Read_Protect_Disable();
			#endif
		}
	}
	
}
  • FLASH_EraseOptionBytes()函数会将16个字节都擦除。如果想只擦除某一个字节:将WRP全部清除掉再重新配置。

  • FLASH_GetWriteProtectionOptionByte() 函数的返回值类型为 uint64_t,表示的是 WRP0~3 的值。当未设置写保护时,返回值为 0xFFFFFFFF;而当所有区域均设置为写保护时,返回值为 0x00000000。

四、将代码修改为RAM自举

  • 1、添加“Project Targets”;
    在这里插入图片描述

  • 2、在C/C++中添加宏VECT_TAB_SRAM;
    在这里插入图片描述

此宏在SystemInit函数中。

注意,两个宏之间用","分开。

  • 3、打开.sct文件;
    在这里插入图片描述

  • 4、(根据实际需要)调整ROM空间大小;

在这里插入图片描述

修改前的空间大小。

在这里插入图片描述

修改后的空间大小。

  • 5、下载器配置;

在这里插入图片描述

在这里插入图片描述

  • 6、添加ini文件;

在这里插入图片描述

  • 七、将Project Targets更改为新建的Targets。
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法与数据结构】字典树(Trie)详解

目录 一,字典树的定义 二,字典树的代码实现 完整代码详细注释: 测试用例测试结果: 三,处理其他字符 四,内存优化与扩展 1. 内存优化 2. 扩展功能 五,扩展功能支持通配符匹配 六&…

MySQL 之存储引擎(MySQL Storage Engine)

MySQL 之存储引擎 常见存储引擎及其特点 ‌InnoDB‌: ‌特点‌:支持事务处理、行级锁定、外键约束,使用聚簇索引,适合高并发读写和事务处理的场景‌。‌适用场景‌:需要高可靠性、高并发读写和事务处理的场景‌。 ‌M…

CXL ALMP(ARB/MUX Link Management Packet)理解

前言: ALMP(ARB/MUX Link Management Packet) 是CXL协议中由ARB/MUX层生成和处理的专用管理报文,用于协调链路电源状态切换(如L0s/L1)和虚拟链路状态机(vLSM)同步。以下是其核心特性…

002 SpringCloudAlibaba整合 - Feign远程调用、Loadbalancer负载均衡

前文地址: 001 SpringCloudAlibaba整合 - Nacos注册配置中心、Sentinel流控、Zipkin链路追踪、Admin监控 文章目录 8.Feign远程调用、loadbalancer负载均衡整合1.OpenFeign整合1.引入依赖2.启动类添加EnableFeignClients注解3.yml配置4.日志配置5.远程调用测试6.服务…

计算机网络(3)TCP格式/连接

1、TCP三大特点:面向连接、可靠、基于字节流 2、如何唯一确定一个TCP连接?TCP四元组:源地址、源端口、目的地址、目的端口 源地址和目标地址的字段(32 位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机源端口和目标端口…

vscode远程报错:Remote host key has changed,...

重装了Ubuntu系统之后,由20.04改为22.04,再用vscode远程,就出现了以上报错。 亲测有效的办法 gedit ~/.ssh/known_hosts 打开这个配置文件 删掉与之匹配的那一行,不知道删哪一行的话,就打开第一行这个 /.ssh/confi…

无符号整数和带符号整数的相互转换

无符号字符数x转换为带符号字符数时,当时,转换后仍然为x;当时,转换后变为。 带符号字符数y转换为无符号字符数时,当时,转换后变为;当时,转换后仍然为y。 无符号整数和带符号整数的…

浏览器报错:无法访问此网站 无法找到xxx.xxx.net的DNS地址。正在诊断该问题。尝试运行Windows网络诊断。DNS_PROBE_STARTED

🤟致敬读者 🟩感谢阅读🟦希望我的文章能帮到您🟪如有兴趣可点关注了解更多内容 📘博主信息 点击标题👆有惊喜 📃文章前言 🔷文章均为学习和工作中整理的笔记,分享记录…

2025-02-18 学习记录--C/C++-PTA 7-25 念数字

一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ /*** 输入一个整数&#xff0c;输出每个数字对应的拼音。当整数为负数时&#xff0c;先输出fu字。*/#include <stdio.h>// 输出 正数 中 各位数 对应的 拼音 void getLetter(int num) {// 10个数字&#x…

VirtualBox 中使用 桥接网卡 并设置 MAC 地址

在 VirtualBox 中使用 桥接网卡 并设置 MAC 地址&#xff0c;可以按照以下步骤操作&#xff1a; 步骤 1&#xff1a;设置桥接网卡 打开 VirtualBox&#xff0c;选择你的虚拟机&#xff0c;点击 “设置” (Settings)。进入 “网络” (Network) 选项卡。在 “适配器 1” (Adapt…

Fiddler笔记

文章目录 一、与F12对比二、核心作用三、原理四、配置1.Rules:2.配置证书抓取https包3.设置过滤器4、抓取App包 五、模拟弱网测试六、调试1.线上调试2.断点调试 七、理论1.四要素2.如何定位前后端bug 注 一、与F12对比 相同点&#xff1a; 都可以对http和https请求进行抓包分析…

【数据结构初阶第十节】队列(详解+附源码)

好久不见。。。别不开心了&#xff0c;听听喜欢的歌吧 必须有为成功付出代价的决心&#xff0c;然后想办法付出这个代价。云边有个稻草人-CSDN博客 目录 一、概念和结构 二、队列的实现 Queue.h Queue.c test.c Relaxing Time&#xff01; ————————————《有没…

idea无法联网,离线安装插件

插件地址&#xff1a;https://plugins.jetbrains.com/ JetBrains Marketplace 如果无法进入&#xff0c;可以试试 配置hosts 3.163.125.103 plugins.jetbrains.com ip 变了&#xff0c;可以查询个最新的&#xff1a; https://tool.chinaz.com/speedtest/plugins.jetbrai…

二十多年前的苹果电源Power Mac G4 Mdd 电源接口

在1999年&#xff0c;苹果推出了最初的Power Mac G4电脑。第一代Power Mac G4有与G3系列相似的外壳和两种主板设置&#xff0c;分别使用PCI和AGP显示总线。第二代电脑被昵称为快银或水银机&#xff0c;来自2001年的它们有更高速的PowerPC 7450系列芯片&#xff0c;增强了L2缓存…

qt:按钮的常见操作(简单方向键项目)

1.圆形按钮 首先&#xff0c;设置圆形按钮&#xff0c;首先要将setGeometry(x位置&#xff0c;y位置&#xff0c;长&#xff0c;宽)中的长和宽设置为相等&#xff0c;再使用一下模板 q2->setStyleSheet("QPushButton {"" background-color: black;"…

SAP-ABAP:外部断点设置详解

在 SAP 中打外部断点&#xff08;External Breakpoint&#xff09;是调试 ABAP 程序的一种常用方法&#xff0c;尤其是在调试标准程序、增强或用户出口时。外部断点允许开发人员在特定用户或特定会话中触发断点&#xff0c;而不会影响其他用户。以下是使用外部断点时需要注意的…

springboot399-中文社区交流平台(源码+数据库+纯前后端分离+部署讲解等)

&#x1f495;&#x1f495;作者&#xff1a; 爱笑学姐 &#x1f495;&#x1f495;个人简介&#xff1a;十年Java&#xff0c;Python美女程序员一枚&#xff0c;精通计算机专业前后端各类框架。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xf…

(9/100)每日小游戏平台系列

项目地址位于&#xff1a;小游戏导航 新增一个跳跃小方块&#xff01; 游戏简介 跳跃小方块&#xff08;Jumping Square&#xff09;是一款轻松有趣的休闲小游戏&#xff0c;考验玩家的反应速度和操作技巧。玩家需要控制一个蓝色小方块&#xff0c;通过点击屏幕或按下空格键进…

React实现自动滚动表格

在 React 中实现一个自动滚动的表格&#xff0c;可以通过 CSS 动画和 JavaScript 定时器来实现。以下是一个完整的示例代码&#xff0c;包含示例数据和自动滚动功能。 实现思路&#xff1a; ** 自动滚动&#xff1a;** 使用 setInterval 实现表格的自动滚动。 手动滚动&…

数字滤波器的设计实现及应用(论文+仿真)

3.1系统总体设计 对于本次毕业设计的课题基于DSP的IIR数字滤波器来说&#xff0c;在此选用了TI公司的DSP芯片TMS320F5402芯片来作为数字滤波器的主控制器&#xff0c;另外再采用高速AD模拟到数字转换芯片来进行输入信号的采样&#xff0c;以此将采集到的信号输出给主控制器进行…