设置FLASH的读写保护及解除—零死角玩转STM32-F429系列

Jlink使用技巧之--芯片加密(FLASH读保护-F4系列) 1. 读保护函数及解除读保护函数。 阅读详情

第51章     设置FLASH的读写保护及解除

全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn

野火视频教程优酷观看网址:http://i.youku.com/firege

 

 

 

本章参考资料:《STM32F4xx 中文参考手册》、《STM32F4xx规格书》、库说明文档《stm32f4xx_dsp_stdperiph_lib_um.chm》以及《Proprietary code read-out protection on microcontrollers》。

51.1 选项字节与读写保护

在实际发布的产品中,在STM32芯片的内部FLASH存储了控制程序,如果不作任何保护措施的话,可以使用下载器直接把内部FLASH的内容读取回来,得到bin或hex文件格式的代码拷贝,别有用心的厂商即可利用该代码文件山寨产品。为此,STM32芯片提供了多种方式保护内部FLASH的程序不被非法读取,但在默认情况下该保护功能是不开启的,若要开启该功能,需要改写内部FLASH选项字节(Option Bytes)中的配置。

51.1.1 选项字节的内容

选项字节是一段特殊的FLASH空间,STM32芯片会根据它的内容进行读写保护、复位电压等配置,选项字节的构成见表 511。

表 511 选项字节的构成

地址
[63:16]
[15:0]
0x1FFF C000
保留
ROP 和用户选项字节 (RDP & USER)
0x1FFF C008
保留
扇区 0 到 11 的写保护 nWRP 位
0x1FFE C000
保留
保留
0x1FFE C008
保留
扇区 12 到 23 的写保护 nWRP 位
选项字节具体的数据位配置说明见表 512。

表 512 选项字节具体的数据位配置说明

选项字节(字,地址 0x1FFF C000)
RDP:读保护选项字节。
读保护用于保护 Flash 中存储的软件代码。
位 15:8
0xAA:级别 0,无保护
其它值:级别 1,存储器读保护(调试功能受限)
0xCC:级别 2,芯片保护(禁止调试和从 RAM 启动)
USER:用户选项字节
此字节用于配置以下功能:
选择看门狗事件:硬件或软件
进入停止模式时产生复位事件
进入待机模式时产生复位事件
位 7
nRST_STDBY
0:进入待机模式时产生复位
1:不产生复位
位 6
nRST_STOP
0:进入停止模式时产生复位
1:不产生复位
位 5
WDG_SW
0:硬件看门狗
1:软件看门狗
位 4
0x1:未使用
位 3:2
BOR_LEV: BOR 复位级别
这些位包含释放复位信号所需达到的供电电压阈值。
通过对这些位执行写操作,可将新的 BOR 级别值编程到 Flash。
00: BOR 级别 3 (VBOR3),复位阈值电压为 2.70 V 到 3.60 V
01: BOR 级别 2 (VBOR2),复位阈值电压为 2.40 V 到 2.70 V
10: BOR 级别 1 (VBOR1),复位阈值电压为 2.10 V 到 2.40 V
11: BOR 关闭 (VBOR0),复位阈值电压为 1.8 V 到 2.10 V
位 1:0
0x1:未使用
选项字节(字,地址 0x1FFF C008)
位15
SPMOD:选择nWPRi位的模式
0:nWPRi位用于写保护(默认)
1:nWPRi位用于代码读出保护(Proprietary code readout protection ,PCROP)
位14
DB1M:设置内部FLASH为1MB的产品的双Bank模式
0:单个Bank的模式
1:使用两个Bank的模式
位 13:12
0xF:未使用
nWRP: Flash 写保护选项字节。
扇区 0 到 11 可采用写保护。
位 11:0
nWRPi (i值为0-11,对应0-11扇区的保护设置):
0:开启所选扇区的写保护
1:关闭所选扇区的写保护
选项字节(字,地址 0x1FFE C000)
位 15:0
0xFF:未使用
选项字节(字,地址 0x1FFE C008)
位 15:12
0xF:未使用
nWRP: Flash 写保护选项字节。
扇区 12 到 23 可采用写保护。
位 11:0
nWRPi:
0:开启扇区 i 的写保护。
1:关闭扇区 i 的写保护。
我们主要讲解选项字节配置中的RDP位和PCROP位,它们分别用于配置读保护级别及代码读出保护。

51.1.2 RDP读保护级别

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

    0xAA:级别0,无保护

这是STM32的默认保护级别,它没有任何读保护,读取内部FLASH及"备份SRAM"的内容都没有任何限制。(注意这里说的"备份SRAM"是指STM32备份域的SRAM空间,不是指主SRAM,下同)

    其它值:级别1,使能读保护

把RDP配置成除0xAA或0xCC外的任意数值,都会使能级别1的读保护。在这种保护下,若使用调试功能(使用下载器、仿真器)或者从内部SRAM自举时都不能对内部FLASH及备份SRAM作任何访问(读写、擦除都被禁止);而如果STM32是从内部FLASH自举时,它允许对内部FLASH及备份SRAM的任意访问。

也就是说,在级别1模式下,任何尝试从外部访问内部FLASH内容的操作都被禁止,例如无法通过下载器读取它的内容,或编写一个从内部SRAM启动的程序,若该程序读取内部FLASH,会被禁止。而如果是芯片自己访问内部FLASH,是完全没有问题的,例如前面的"读写内部FLASH"实验中的代码自己擦写内部FLASH空间的内容,即使处于级别1的读保护,也能正常擦写。

当芯片处于级别1的时候,可以把选项字节的RDP位重新设置为0xAA,恢复级别0。在恢复到级别0前,芯片会自动擦除内部FLASH及备份SRAM的内容,即降级后原内部FLASH的代码会丢失。在级别1时使用SRAM自举的程序也可以访问选项字节进行修改,所以如果原内部FLASH的代码没有解除读保护的操作时,可以给它加载一个SRAM自举的程序进行保护降级,后面我们将会进行这样的实验。

    0xCC:级别2,禁止调试

把RDP配置成0xCC值时,会进入最高级别的读保护,且设置后无法再降级,它会永久禁止用于调试的JTAG接口(相当于熔断)。在该级别中,除了具有级别1的所有保护功能外,进一步禁止了从SRAM或系统存储器的自举(即平时使用的串口ISP下载功能也失效),JTAG调试相关的功能被禁止,选项字节也不能被修改。它仅支持从内部FLASH自举时对内部FLASH及SRAM的访问(读写、擦除)。

由于设置了级别2后无法降级,也无法通过JTAG、串口ISP等方式更新程序,所以使用这个级别的保护时一般会在程序中预留"后门"以更新应用程序,若程序中没有预留后门,芯片就无法再更新应用程序了。所谓的"后门"是一种IAP程序(In Application Program),它通过某个通讯接口获取将要更新的程序内容,然后利用内部FLASH擦写操作把这些内容烧录到自己的内部FLASH中,实现应用程序的更新。

不同级别下的访问限制见图 511。

图 511 不同级别下的访问限制

不同保护级别之间的状态转换见图 512。

图 512 不同级别间的状态转换

51.1.3 PCROP代码读出保护

在STM32F42xx及STM32F43xx系列的芯片中,除了可使用RDP对整片FLASH进行读保护外,还有一个专用的代码读出保护功能(Proprietary code readout protection,下面简称PCROP),它可以为内部FLASH的某几个指定扇区提供保护功能,所以它可以用于保护一些IP代码,方便提供给另一方进行二次开发,见图 513。

图 513 PCROP保护功能

当SPMOD位设置为0时(默认值),nWRPi位用于指定要进行写保护的扇区,这可以防止错误的指针操作导致FLASH 内容的改变,若扇区被写保护,通过调试器也无法擦除该扇区的内容;当SPMOD位设置为1时,nWRPi位用于指定要进行PCROP保护的扇区。其中PCROP功能可以防止指定扇区的FLASH内容被读出,而写保护仅可以防止误写操作,不能被防止读出。

当要关闭PCROP功能时,必须要使芯片从读保护级别1降为级别0,同时对SPMOD位置0,才能正常关闭;若芯片原来的读保护为级别0,且使能了PCROP保护,要关闭PCROP时也要先把读保护级别设置为级别1,再在降级的同时设置SPMOD为0。

51.2 修改选项字节的过程

修改选项字节的内容可修改各种配置,但是,当应用程序运行时,无法直接通过选项字节的地址改写它们的内容,例如,接使用指针操作地址0x1FFFC0000的修改是无效的。要改写其内容时必须设置寄存器FLASH_OPTCR及FLASH_OPTCR1中的对应数据位,寄存器的与选项字节对应位置见图 514及图 515,详细说明请查阅《STM32参考手册》。

图 514 FLASH_OPTCR寄存器说明(nWRP表示0-11扇区)

图 515 FLASH_OPTCR1寄存器说明(nWRP表示12-23扇区)

默认情况下,FLASH_OPTCR寄存器中的第0位OPTLOCK值为1,它表示选项字节被上锁,需要解锁后才能进行修改,当寄存器的值设置完成后,对FLASH_OPTCR寄存器中的第1位OPTSTRT值设置为1,硬件就会擦除选项字节扇区的内容,并把FLASH_OPTCR/1寄存器中包含的值写入到选项字节。

所以,修改选项字节的配置步骤如下:

(1)    解锁,在 Flash 选项密钥寄存器 (FLASH_OPTKEYR) 中写入 OPTKEY1 = 0x0819 2A3B;接着在 Flash 选项密钥寄存器 (FLASH_OPTKEYR) 中写入 OPTKEY2 = 0x4C5D 6E7F。

(2)    检查 FLASH_SR 寄存器中的 BSY 位,以确认当前未执行其它Flash 操作。

(3)    在 FLASH_OPTCR 和/或 FLASH_OPTCR1 寄存器中写入选项字节值。

(4)    将 FLASH_OPTCR 寄存器中的选项启动位 (OPTSTRT) 置 1。

(5)    等待 BSY 位清零,即写入完成。

51.3 操作选项字节的库函数

为简化编程,STM32标准库提供了一些库函数,它们封装了修改选项字节时操作寄存器的过程。

1.    选项字节解锁、上锁函数

对选项字节解锁、上锁的函数见代码清单 511。

代码清单 511选项字节解锁、上锁

1

2 #define FLASH_OPT_KEY1 ((uint32_t)0x08192A3B)

3 #define FLASH_OPT_KEY2 ((uint32_t)0x4C5D6E7F)

4

5 /**

6 * @brief Unlocks the FLASH Option Control Registers access.

7 * @param None

8 * @retval None

9 */

10 void FLASH_OB_Unlock(void)

11 {

12 if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET)

13 {

14 /* Authorizes the Option Byte register programming */

15 FLASH->OPTKEYR = FLASH_OPT_KEY1;

16 FLASH->OPTKEYR = FLASH_OPT_KEY2;

17 }

18 }

19

20 /**

21 * @brief Locks the FLASH Option Control Registers access.

22 * @param None

23 * @retval None

24 */

25 void FLASH_OB_Lock(void)

26 {

27 /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */

28 FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;

29 }

解锁的时候,它对FLASH_OPTCR寄存器写入两个解锁参数,上锁的时候,对FLASH_ OPTCR寄存器的FLASH_OPTCR_OPTLOCK位置1。

2.    设置读保护级别

解锁后设置选项字节寄存器的RDP位可调用FLASH_OB_RDPConfig完成,见代码清单 512。

代码清单 512 设置读保护级别

1 /**

2 * @brief Sets the read protection level.

3 * @param OB_RDP: specifies the read protection level.

4 * This parameter can be one of the following values:

5 * @arg OB_RDP_Level_0: No protection

6 * @arg OB_RDP_Level_1: Read protection of the memory

7 * @arg OB_RDP_Level_2: Full chip protection

8 *

9 * /!\ Warning /!\ When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0

10 *

11 * @retval None

12 */

13 void FLASH_OB_RDPConfig(uint8_t OB_RDP)

14 {

15 FLASH_Status status = FLASH_COMPLETE;

16

17 /* Check the parameters */

18 assert_param(IS_OB_RDP(OB_RDP));

19

20 status = FLASH_WaitForLastOperation();

21

22 if(status == FLASH_COMPLETE)

23 {

24 *(__IO uint8_t*)OPTCR_BYTE1_ADDRESS = OB_RDP;

25

26 }

27 }

该函数根据输入参数设置RDP寄存器位为相应的级别,其注释警告了若配置成OB_RDP_Level_2会无法恢复。类似地,配置其它选项时也有相应的库函数,如FLASH_OB_PCROP1Config、FLASH_OB_WRP1Config分别用于设置要进行PCROP保护或WRP保护(写保护)的扇区。

3.    写入选项字节

调用上一步骤中的函数配置寄存器后,还要调用代码清单 513中的FLASH_OB_Launch函数把寄存器的内容写入到选项字节中。

代码清单 513 写入选项字节

1 /**

2 * @brief Launch the option byte loading.

3 * @param None

4* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM,

5 * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE.

6 */

7 FLASH_Status FLASH_OB_Launch(void)

8 {

9 FLASH_Status status = FLASH_COMPLETE;

10

11 /* Set the OPTSTRT bit in OPTCR register */

12 *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= FLASH_OPTCR_OPTSTRT;

13

14 /* Wait for last operation to be completed */

15 status = FLASH_WaitForLastOperation();

16

17 return status;

18 }

该函数设置FLASH_OPTCR_OPTSTRT位后调用了FLASH_WaitForLastOperation函数等待写入完成,并返回写入状态,若操作正常,它会返回FLASH_COMPLETE。

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

在本实验中我们将以实例讲解如何修改选项字节的配置,更改读保护级别、设置PCROP或写保护,最后把选项字节恢复默认值。

本实验要进行的操作比较特殊,在开发和调试的过程中都是在SRAM上进行的(使用SRAM启动方式)。例如,直接使用FLASH版本的程序进行调试时,如果该程序在运行后对扇区进行了写保护而没有解除的操作或者该解除操作不正常,此时将无法再给芯片的内部FLASH下载新程序,最终还是要使用SRAM自举的方式进行解除操作。所以在本实验中为便于修改选项字节的参数,我们统一使用SRAM版本的程序进行开发和学习,当SRAM版本调试正常后再改为FLASH版本。

关于在SRAM中调试代码的相关配置,请参考前面的章节。

注意:

若您在学习的过程中想亲自修改代码进行测试,请注意备份原工程代码。当芯片的FLASH被保护导致无法下载程序到FLASH时,可以下载本工程到芯片,并使用SRAM启动运行,即可恢复芯片至默认配置。但如果修改了读保护为级别2,采用任何方法都无法恢复!(除了这个配置,其它选项都可以大胆地修改测试。)

51.4.1 硬件设计

本实验在SRAM中调试代码,因此把BOOT0和BOOT1引脚都使用跳线帽连接到3.3V,使芯片从SRAM中启动。

51.4.2 软件设计

本实验的工程名称为"设置读写保护与解除",学习时请打开该工程配合阅读,它是从"RAM调试—多彩流水灯"工程改写而来的。为了方便展示及移植,我们把操作内部FLASH相关的代码都编写到"internalFlash_reset.c"及"internalFlash_reset.h"文件中,这些文件是我们自己编写的,不属于标准库的内容,可根据您的喜好命名文件。

1.    主要实验

(1)    学习配置扇区写保护;

(2)    学习配置PCROP保护;

(3)    学习配置读保护级别;

(4)    学习如何恢复选项字节到默认配置;

2.    代码分析

配置扇区写保护

我们先以代码清单 514中的设置与解除写保护过程来学习如何配置选项字节。

代码清单 514 配置扇区写保护

1

2 #define FLASH_WRP_SECTORS (OB_WRP_Sector_0|OB_WRP_Sector_1)

3 __IO uint32_t SectorsWRPStatus = 0xFFF;

4

5 /**

6 * @brief WriteProtect_Test,普通的写保护配置

7 * @param 运行本函数后会给扇区FLASH_WRP_SECTORS进行写保护,再重复一次会进行解写保护

8 * @retval None

9 */

10 void WriteProtect_Test(void)

11 {

12 FLASH_Status status = FLASH_COMPLETE;

13 {

14 /* 获取扇区的写保护状态 */

15 SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;

16

17 if (SectorsWRPStatus == 0x00)

18 {

19 /* 扇区已被写保护,执行解保护过程*/

20

21 /* 使能访问OPTCR寄存器 */

22 FLASH_OB_Unlock();

23

24 /* 设置对应的nWRP位,解除写保护 */

25 FLASH_OB_WRPConfig(FLASH_WRP_SECTORS, DISABLE);

26 status=FLASH_OB_Launch();

27 /* 开始对选项字节进行编程 */

28 if (status != FLASH_COMPLETE)

29 {

30 FLASH_ERROR("对选项字节编程出错,解除写保护失败,status = %x",status);

31 /* User can add here some code to deal with this error */

32 while (1)

33 {

34 }

35 }

36 /* 禁止访问OPTCR寄存器 */

37 FLASH_OB_Lock();

38

39 /* 获取扇区的写保护状态 */

40 SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;

41

42 /* 检查是否配置成功 */

43 if (SectorsWRPStatus == FLASH_WRP_SECTORS)

44 {

45 FLASH_INFO("解除写保护成功!");

46 }

47 else

48 {

49 FLASH_ERROR("未解除写保护!");

50 }

51 }

52 else

53 { /* 若扇区未被写保护,开启写保护配置 */

54

55 /* 使能访问OPTCR寄存器 */

56 FLASH_OB_Unlock();

57

58 /*使能 FLASH_WRP_SECTORS 扇区写保护 */

59 FLASH_OB_WRPConfig(FLASH_WRP_SECTORS, ENABLE);

60

61 status=FLASH_OB_Launch();

62 /* 开始对选项字节进行编程 */

63 if (status != FLASH_COMPLETE)

64 {

65 FLASH_ERROR("对选项字节编程出错,设置写保护失败,status = %x",status);

66 while (1)

67 {

68 }

69 }

70 /* 禁止访问OPTCR寄存器 */

71 FLASH_OB_Lock();

72

73 /* 获取扇区的写保护状态 */

74 SectorsWRPStatus = FLASH_OB_GetWRP() & FLASH_WRP_SECTORS;

75

76 /* 检查是否配置成功 */

77 if (SectorsWRPStatus == 0x00)

78 {

79 FLASH_INFO("设置写保护成功!");

80 }

81 else

82 {

83 FLASH_ERROR("设置写保护失败!");

84 }

85 }

86 }

87 }

本函数分成了两个部分,它根据目标扇区的状态进行操作,若原来扇区为非保护状态时就进行写保护,若为保护状态就解除保护。其主要操作过程如下:

    调用FLASH_OB_GetWRP函数获取目标扇区的保护状态若扇区被写保护,则开始解除保护过程,否则开始设置写保护过程;

    调用FLASH_OB_Unlock解锁选项字节的编程;

    调用FLASH_OB_WRPConfig函数配置目标扇区关闭或打开写保护;

    调用FLASH_OB_Launch函数把寄存器的配置写入到选项字节;

    调用FLASH_OB_GetWRP函数检查是否配置成功;

    调用FLASH_OB_Lock禁止修改选项字节。

配置PCROP保护

配置PCROP保护的过程与配置写保护过程稍有区别,见代码清单 515。

代码清单 515 配置PCROP保护(internalFlash_reset.c文件)

1

2 /**

3 * @brief SetPCROP,设置PCROP位,用于测试解锁

4 * @note 使用有问题的串口ISP下载软件,可能会导致PCROP位置1,

5 导致无法给芯片下载程序到FLASH,本函数用于把PCROP位置1,

6 模拟出无法下载程序到FLASH的环境,以便用于解锁的程序调试。

7 若不了解PCROP位的作用,请不要执行此函数!!

8 * @param None

9 * @retval None

10 */

11 void SetPCROP(void)

12 {

13

14 FLASH_Status status = FLASH_COMPLETE;

15

17

18 FLASH_INFO();

19 FLASH_INFO("正在设置PCROP保护,请耐心等待...");

20 //选项字节解锁

21 FLASH_OB_Unlock();

22

23 //设置为PCROP模式

24 FLASH_OB_PCROPSelectionConfig(OB_PcROP_Enable);

25 //设置扇区0进行PCROP保护

26 FLASH_OB_PCROPConfig(OB_PCROP_Sector_10,ENABLE);

27 //把寄存器设置写入到选项字节

28 status =FLASH_OB_Launch();

29

30 if (status != FLASH_COMPLETE)

31 {

32 FLASH_INFO("设置PCROP失败!");

33 }

34 else

35 {

36 FLASH_INFO("设置PCROP成功!");

37

38 }

39 //选项字节上锁

40 FLASH_OB_Lock();

41 }

该代码在解锁选项字节后,调用FLASH_OB_PCROPSelectionConfig函数把SPMOD寄存器位配置为PCROP模式,接着调用FLASH_OB_PCROPConfig函数配置目标保护扇区。

恢复选项字节为默认值

当芯片被设置为读写保护或PCROP保护时,这时给芯片的内部FLASH下载程序时,可能会出现图 516和图 517的擦除FLASH失败的错误提示。

图 516 擦除失败提示

图 517 擦除进度条卡在开始状态

只要不是把读保护配置成了级别2保护,都可以使用SRAM启动运行代码清单 516中的函数恢复选项字节为默认状态,使得FLASH下载能正常进行。

代码清单 516 恢复选项字节为默认值

1 // @brief OPTCR register byte 0 (Bits[7:0]) base address

2 #define OPTCR_BYTE0_ADDRESS ((uint32_t)0x40023C14)

3 //@brief OPTCR register byte 1 (Bits[15:8]) base address

4 #define OPTCR_BYTE1_ADDRESS ((uint32_t)0x40023C15)

5 //@brief OPTCR register byte 2 (Bits[23:16]) base address

6 #define OPTCR_BYTE2_ADDRESS ((uint32_t)0x40023C16)

7 // @brief OPTCR register byte 3 (Bits[31:24]) base address

8 #define OPTCR_BYTE3_ADDRESS ((uint32_t)0x40023C17)

9 // @brief OPTCR1 register byte 0 (Bits[7:0]) base address

10 #define OPTCR1_BYTE2_ADDRESS ((uint32_t)0x40023C1A)

11

12 /**

13 * @brief InternalFlash_Reset,恢复内部FLASH的默认配置

14 * @param None

15 * @retval None

16 */

17 int InternalFlash_Reset(void)

18 {

19 FLASH_Status status = FLASH_COMPLETE;

20

21 /* 使能访问选项字节寄存器 */

22 FLASH_OB_Unlock();

23

24 /* 擦除用户区域 (用户区域指程序本身没有使用的空间,可以自定义)**/

25 /* 清除各种FLASH的标志位 */

26 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |

27 FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

28

29 FLASH_INFO("\r\n");

30 FLASH_INFO("正在准备恢复的条件,请耐心等待...");

31

32 //确保把读保护级别设置为LEVEL1,以便恢复PCROP寄存器位

33 //PCROP寄存器位从设置为0时,必须是读保护级别由LEVEL1转为LEVEL0时才有效,

34 //否则修改无效

35 FLASH_OB_RDPConfig(OB_RDP_Level_1);

36

37 status=FLASH_OB_Launch();

38

39 status = FLASH_WaitForLastOperation();

40

41 //设置为LEVEL0并恢复PCROP位

42

43 FLASH_INFO("\r\n");

44 FLASH_INFO("正在擦除内部FLASH的内容,请耐心等待...");

45

46 //关闭PCROP模式

47 FLASH_OB_PCROPSelectionConfig(OB_PcROP_Disable);

48 FLASH_OB_RDPConfig(OB_RDP_Level_0);

49

50 status =FLASH_OB_Launch();

51

52 //设置其它位为默认值

53 (*(__IO uint32_t *)(OPTCR_BYTE0_ADDRESS))=0x0FFFAAE9;

54 (*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS))=0x0FFF;

55 status =FLASH_OB_Launch();

56 if (status != FLASH_COMPLETE)

57 {

58 FLASH_ERROR("恢复选项字节默认值失败,错误代码:status=%X",status);

59 }

60 else

61 {

62 FLASH_INFO("恢复选项字节默认值成功!");

63 }

64 //禁止访问

65 FLASH_OB_Lock();

66

67 return status;

68 }

这个函数进行了如下操作:

    调用FLASH_OB_Unlock解锁选项字节的编程;

    调用FLASH_ClearFlag函数清除所有FLASH异常状态标志;

    调用FLASH_OB_RDPConfig函数设置为读保护级别1,以便后面能正常关闭PCROP模式;

    调用FLASH_OB_Launch写入选项字节并等待读保护级别设置完毕;

    调用FLASH_OB_PCROPSelectionConfig函数关闭PCROP模式;

    调用FLASH_OB_RDPConfig函数把读保护级别降为0;

    调用FLASH_OB_Launch定稿选项字节并等待降级完毕,由于这个过程需要擦除内部FLASH的内容,等待的时间会比较长;

    直接操作寄存器,使用"(*(__IO uint32_t *)(OPTCR_BYTE0_ADDRESS))=0x0FFFAAE9;"和"(*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS))=0x0FFF;"语句把OPTCR及OPTCR1寄存器与选项字节相关的位都恢复默认值;

    调用FLASH_OB_Launch函数等待上述配置被写入到选项字节;

    恢复选项字节为默认值操作完毕。

main函数

最后来看看本实验的main函数,见。代码清单 517。

代码清单 517 main函数

1 /**

2 * @brief 主函数

3 * @param 无

4 * @retval 无

5 */

6 int main(void)

7 {

8 /* LED 端口初始化 */

9 LED_GPIO_Config();

10 Debug_USART_Config();

11 LED_BLUE;

12

13 FLASH_INFO("本程序将会被下载到STM32的内部SRAM运行。");

14 FLASH_INFO("下载程序前,请确认把实验板的BOOT0和BOOT1引脚都接到3.3V电源处!!");

15

16 FLASH_INFO("\r\n");

17 FLASH_INFO("----这是一个STM32芯片内部FLASH解锁程序----");

18 FLASH_INFO("程序会把芯片的内部FLASH选项字节恢复为默认值");

19

20

21 #if 0 //工程调试、演示时使用,正常解除时不需要运行此函数

22 SetPCROP(); //修改PCROP位,仿真芯片被锁无法下载程序到内部FLASH的环境

23 #endif

24

25 #if 0 //工程调试、演示时使用,正常解除时不需要运行此函数

26 WriteProtect_Test(); //修改写保护位,仿真芯片扇区被设置成写保护的的环境

27 #endif

28

30

31 /*恢复选项字节到默认值,解除保护*/

32 if(InternalFlash_Reset()==FLASH_COMPLETE)

33 {

34 FLASH_INFO("选项字节恢复成功,请把BOOT0和BOOT1引脚都连接到GND,");

35 FLASH_INFO("然后随便找一个普通的程序,下载程序到芯片的内部FLASH进行测试");

36 LED_GREEN;

37 }

38 else

39 {

40 FLASH_INFO("选项字节恢复成功失败,请复位重试");

41 LED_RED;

42 }

43

45

46 while (1);

47 }

在main函数中,主要是调用了InternalFlash_Reset函数把选项字节恢复成默认值,程序默认时没有调用SetPCROP和WriteProtect_Test函数设置写保护,若您想观察实验现象,可修改条件编译的宏,使它加入到编译中。

3.    下载测试

把开发板的BOOT0和BOOT1引脚都使用跳线帽连接到3.3V电源处,使它以SRAM方式启动,然后用USB线连接开发板"USB TO UART"接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板并复位运行,在串口调试助手可看到调试信息。程序运行后,请耐心等待至开发板亮绿灯或串口调试信息提示恢复完毕再给开发板断电,否则由于恢复过程被中断,芯片内部FLASH会处于保护状态。

芯片内部FLASH处于保护状态时,可重新下载本程序到开发板以SRAM运行恢复默认配置。
--------------------- 
作者:0木木0 
来源:优快云 
原文:https://blog.youkuaiyun.com/flyleaf91/article/details/52325561 
版权声明:本文为博主原创文章,转载请附上博文链接!

STM32 Flash读保护设置和解除方法,保护代码不被读出。 本文记录 关于 STM32 的 Flash 读保护的设置和解除方法,可以简单的保护 Flash 中的代码不被读出,这个方法能防止通过调试工具读出MCU内部程序,但不清楚专业搞破解的是否有手段读出设置了读保护的程序,为了代码更安全还是建议根据 MCU ID 增加软件加密,或者使用其他加密方式。测试环境是 STM32G474 , 其他 STM32 系列的类似,可以 CV 过去试试。 阅读详情

相关推荐

揭秘STM32内部FLASH的读写保护及解除方法

在STM32微控制器开发中,保护内部FLASH的数据安全至关重要。设置FLASH的读写保护可以有效防止未经授权的访问和修改,而解除保护则为开发者提供了灵活性和便利性。本文将深入探讨STM32内部FLASH的读写保护及解除方法,通过生动的描述和实例代码,帮助读者更好地理解和应用。

2301_78660211的博客 3140

STM32芯片写保护/解除写保护的方法

一. 写保护 1. 目的   将Flash设置为写保护的目的,是为了防止其他人通过J-Link,ULINK2等仿真器,将Flash中的程序读取出来(设想一下,你辛辛苦苦研发的产品,别人通过仿真器将程序读取出来,再copy一下产品的硬件,就可以生产)。   可以通过将Flash设置为读保护来保护自己的程序。 2. 开发环境 适用于STM32F1和F4系列(其他系列没有用过); F1系列的库:STM32F10x_StdPeriph_Lib_V3.5.0 F4系列的库:STM32F4xx_DSP_StdP

自由的天空 1万+

第51章 设置FLASH的读写保护及解除—零死角玩转STM32-F429系列

第51章     设置FLASH的读写保护及解除 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege       本章参考资料:《STM32F4xx 中文参考手册》、《STM32F4xx规格书》、库说明文档《stm32f4xx_dsp_stdperiph_lib_um

flyleaf91的专栏 3万+

【免费下载】 STM32芯片Flash被锁解决方案:高效解锁,轻松编程

STM32芯片Flash被锁解决方案:高效解锁,轻松编程 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在STM32微控制器的开发过程中,开发者有时会遇到一个棘手的问题:Flash被锁导致无法下载程序。这一问题通常表现为“Error: Flash Download failed - 'Cortex-M4'”错误提示。为了帮助开发者快速解决这一问题,我们详细介绍了四种有...

gitblog_06570的博客 2248

Android Audio - 支持多应用同时录音_Android8.1修改方法

支持多应用同时录音_Android8.1修改方法 源码路径: sdk\frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp 需要修改两个位置: audio_io_handle_t AudioPolicyManager::getInputForDevice() 在mpClientInterface-&gt...

iFinelio Tower 的博客 5758

高德地图JSAPI中旋转Marker点标签图片时候,且不旋转lable内容方法。

高德地图JSAPI中旋转Marker点标签图片时候,且不旋转lable内容方法

weixin_42960380的博客 2500

第51章 设置FLASH的读写保护及解除—零死角玩转STM32-F429系列

原文地址::https://www.cnblogs.com/firege/p/5806164.html 相关文章 1、用J-Flash去掉STM32写保护----http://download.youkuaiyun.com/download/liuhuan307056001/9643702 第51章     设置FLASH的读写保护及解除 全套200集视频教程和1000页P

xqhrs232的专栏 2716

无人机蜂群作战设计技术详解

构建防御网络,拦截敌方无人机或导弹;无人机蜂群作战设计技术是一种创新的军事应用概念,它基于生物仿生学原理,通过先进的通信技术、自主导航与决策算法,将大量小型、低成本、功能各异的无人机组织成一个高度协同的群体,以执行复杂多样的军事任务。无人机蜂群作战的概念源于自然界中蜜蜂、蚂蚁等生物群体的行为模式,这些生物群体通过简单的个体间的信息交互和分工协作,能够完成远远超出单一个体能力的复杂任务。其中,无人机群体是执行任务的主体,指挥控制系统负责任务分配和决策,通信数据链则保障无人机群体与指挥控制系统之间的信息交换。

专注多旋翼、复合翼无人机技术研究,从事低空经济行业。 2216

STM32F103RC 一上电重复重启

现象:烧了有看门狗的程序,就正常;反之,一直在重启。 原因:之前用STM32 ST-LINK Utility 烧写程序时,Options Bytes设置错误。正确的是默认选上WDG_SW、nRST_STOP、nRST_STDBY。不勾选WDG_SW,代表选择硬件看门狗,因程序中没有喂狗,故一直重启。   参考: 记录STM32的一次不明原因的复位 https://blog.csdn.ne...

RosyCloudsLee的博客 3117

Halcon实战:5种边缘检测算子对比(Sobel、Roberts、Prewitt、Kirsch、Canny)

本文深入对比了Halcon中Sobel、Roberts、Prewitt、Kirsch和Canny五大边缘检测算子的实战表现与核心差异。通过工业图像实例与代码解析,提供了基于噪声水平、边缘连续性及实时性要求的场景化选型指南,帮助工程师精准选择最适合的算子以优化视觉检测流程。

weixin_29266007的博客 392

【即插即用模块】卷积篇 | TCSVT 2025 | MFACB:多尺度膨胀融合,快速扩大感受野,多尺度特征精准捕捉!

本文提出了一种新型多尺度融合膨胀卷积模块MFACB,用于增强语义分割任务中的特征表达能力。该模块通过三分支串联膨胀卷积结构快速扩大感受野,采用双路径融合机制(基础信息路径+多尺度信息路径)实现高效上下文聚合。相比传统卷积块,MFACB在保持轻量化的同时显著提升了多尺度特征捕捉能力,实验表明其性能优于基础残差块。该模块支持自定义膨胀率和步长调整,可灵活嵌入不同网络阶段,适用于需要特征增强的视觉任务。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 311

嵌入式※~STM32芯片写保护/解除写保护的方法

这个写到程序当中并执行过后,使用j-link就不能‘读出’程序了,就是‘读保护’了!将Flash设置为写保护的目的,是为了防止其他人通过J-Link,ULINK2等仿真器,将Flash中的程序读取出来(设想一下,你辛辛苦苦研发的产品,别人通过仿真器将程序读取出来,再copy一下产品的硬件,就可以生产)。STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。

whaosoft~aiotの开发板商城 5501

微信支付接口「系统繁忙 SYSTEM_ERROR」/「文件不存在」报错分析与解决方案 接口开发实现SDK

微信支付的“平台证书模式”只有5年的有效期,过期后微信支付将不再签发新的平台证书,转而要求开发者使用“微信支付公钥”来处理敏感信息加密及回调签名验证。然而,由于以下几点原因,许多开发者在调用 获取平台证书。尽管微信支付在技术迭代上有其必要性,但报错设计过于不友好。诸如“系统繁忙”这样的提示很难直接关联到平台证书失效或公钥切换问题。这样的信息表达,开发者不仅看不懂,还需要花费大量时间分析排查,非常影响效率。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 780

stm32f4 RAM中运行程序 读保护设置

主要是为了在RAM中运行程序来解除读保护的。没想到ST-Link Utility 就直接可以。 ST-Link Utility:target-->options bytes-->就可以看到读保护。 解除读保护,选择 Level 0. 其他都不变(WDG_SW,nRST_STDBY,nRST_STOP都按照默认的勾上) 然后点击Apply即可。 读保护: ...

weixin_30483697的博客 649

OpenClaw 超级 AI 实战专栏【实战案例】(五)邮件收发 + 日历日程 + 文件管理一站式搞定

OpenClaw 实现办公自动化核心是模块解耦:邮件收发、文件管理、日历日程各自封装,便于维护和扩展;开发中需重点解决编码兼容、权限配置、时间格式、重复处理四大类坑点,核心思路是 “提前校验 + 异常兜底 + 统一格式”;敏感信息(邮箱密码、API Token)务必通过.env管理,避免硬编码泄露。

qq_36130719的博客 742

STM32入门教程:无人机控制

我们将会一步一步引导您完成无人机的控制代码,包括无人机的姿态控制、飞行控制和通信控制等。第三步:配置无人机姿态控制 无人机的姿态控制是指控制无人机在空中的倾斜和转向。为了实现姿态控制,我们需要使用加速度计和陀螺仪传感器来获取无人机的姿态信息,并使用PID控制算法来控制无人机的姿态。在这一步骤中,您需要根据您使用的具体传感器和控制算法的要求进行更详细的配置和编码。在通信控制中,您需要考虑到通信的稳定性和可靠性。第五步:通信控制 无人机的通信控制是指与地面站或其他设备进行通信,传输飞行数据和接收飞行指令。

m0_75244442的博客 747

STM32 F4系列设置Flash读保护

适用芯片:STM32F4全部芯片。

dxaws123456的博客 1017

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

STM32芯片flash被锁导致Error Flash Download failed Cortex-M4,解决办法(全)亲测有效

原本这几天一切顺利,结果昨天遇到了问题,前几天有组员捣蛋用杜邦线母头接3.3V,公头直接触碰led电阻(手动点灯显摆),今天开始做项目才发现LED灯坏了,亮不了了(好在今天实话实说,实训老师宽宏大量,没有计较,后续吹掉换个新的灯珠或者LED电阻应该能修好),这里也提醒大家没事千万别拿杜邦线接电源乱搞。接着来到今天上午,老师给了我一个JTAG转接头,跟我说只能死马当活马医了,我又重新用J-FLASH软件试了一下,这次终于可以erase chip了,但是虽然没有直接报错,当是好像没啥效果。

qq_25218501的博客 3万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

使用STM32 ST-LINK Utility 烧录程序,ST LINK烧录程序,解锁FLASH

关键词:ST LINK烧录程序,STLINK烧录程序,ST-LINK烧录程序,STLINK烧录程序,ST LINK解锁Flash。

yutian0606的博客 3万+

stm32对flash的读写保护与解除

一、STM32对内部Flash的保护措施 所有STM32的芯片都提供对Flash的保护,防止对Flash的非法访问 - 写保护和读保护。 1、读保护即大家通常说的“加密”,是作用于整个Flash存储区域。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:A、 通过调试器(JTAG或SWD); B...

qlexcel的专栏 3万+

STM32入门教程(FLASH闪存篇)

本文摘要: 基于江协科技STM32视频教程,详细介绍了STM32F1系列Flash存储器的结构与操作。主要内容包括:1)Flash存储器的三个组成部分(程序存储器、系统存储器和选项字节)及其功能;2)Flash编程操作流程(解锁、擦除、编程、加锁);3)用户选择字节的配置方法;4)通过指针访问存储器的技术;5)器件电子签名的读取方法。文章提供了完整的示例代码,演示了如何读写内部Flash和读取芯片ID信息,并建议配合STM32ST-LINKUtility工具进行调试。适合具备数字电路基础和单片机基础的开发者

Zevalin的博客 5205

学习STM32的防护措施

总结: 本文介绍了学习STM32的防护措施的内容,并提供了相关的代码案例。这些防护措施可以有效地保护STM32的安全性和可靠性,确保嵌入式系统的正常运行。通过合理设置代码保护、电压和功耗保护、外设保护以及通信安全等防护措施,可以大大提高STM32的安全性和可靠性。希望本文对学习STM32的防护措施有所帮助。STM32是一款广泛应用于嵌入式系统开发的微控制器。为了保护STM32的安全性和可靠性,需要采取一系列的防护措施。本文将详细介绍学习STM32的防护措施的内容,并提供相关的代码案例。

xiaoalla的博客 1805

STM32烧熔丝

欢迎使用Markdown编辑器写博客最近一直在研究STM32加密的问题,偶然发现STM32具有类似烧死熔丝的操作,简要说明如下:下面是stm32f4xx参考手册中文版上的内容。(RM0090) 从以上可以看出,当向RDP寄存器写入0xcc时,将是永久性的不能用外部工具对其读写操作,但是用IAP升级的方式却可以来更新里面的APP。 利用库函数操作实际只需要3句话,F

Jack Yi的博客 3753

STM32 Flash

STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行闪存存储器,可以在通用地址空间直接寻址,即可读写FLASH的用途:(1)利用程序存储器的剩余空间来(2)通过在程序中编程(IAP),闪存存储器可以用ICP或IAP方式编程:ICP方式用于更新闪存存储器的全部内容,它通过JTAG、 SWD协议或系统加载程序(Bootloader)下载用户应用程序到微控制器中。IAP。

qq_68719489的博客 2382

ssd内部是多个flash一起操作_STM32学习笔记—片内FLASH读写失败问题分析

FLASH,指Flash Memory,是一种非易失性存储器(闪存),掉电能正常保存数据。今天是第5篇分享,《STM32学习笔记》之片内FLASH读写失败问题分析。往期分享:AI电堂:STM32学习笔记— 电源管理及低功耗设计要点​zhuanlan.zhihu.comAI电堂:STM32学习笔记— SPI通信异常分析​zhuanlan.zhihu.comAI电堂:STM32学习笔记—引起电源和系统...

weixin_39648297的博客 853
上一篇: STM32F4(Flash读保护)
下一篇: 使用STM32 ST-LINK Utility 设置读保护后不能运行
oshan2012
博客等级 码龄15年 300粉丝 91原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值