历史上的今天

今天是:2024年10月29日(星期二)

正在发生

2021年10月29日 | stm32专题二十九:Flash 读写保护

发布者:幸福的家园 来源: eefocus关键字:stm32  Flash  读写保护 手机看文章 扫描二维码
随时随地手机看文章

设置Flash的读写保护,其实就是操作内部Flash的选项字节。

选项字节在内部Flash的主存储页之后,由于是Flash,不能像内存RAM一样随意写入。由于Flash的写入特性,只能将 1 写成 0,而如果要确保写入数据的绝对正确,则需要先擦除再写入。如果直接对Flash写入,则只能确保写入 0 值是正确的。

选项字节,可以认为是掉电不会丢失的寄存器(Flash空间)。就是用Flash介质来存储配置,要修改选项字节,跟修改Flash一样。

RDP 读保护字节描述(可以通过j-link或st-link读Flash 加密等):

RDP配置方式:

2个数据字节 Data0 Data1

3 设置写保护

RDP 读保护


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

读保护的解除,必须要上电复位才可以。

WRP 写保护


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


1 设置写保护


       写保护的配置一般以 4K 字节为单位,除 WRP3 的最后一位比较特殊外,每个WRP 选项字节的一位用于控制 4K 字节的写访问权限, 把对应 WRP 的位置 0 即可把它匹配的空间加入写保护。被设置成写保护后,主 FLASH 中的内容使用任何方式都不能被擦除和写入,写保护不会影响读访问权限,读访问权限完全由前面介绍的读保护设置限制。


2 解除写保护


       解除写保护是逆过程,把对应 WRP 的位置 1 即可把它匹配的空间解除写保护。解除写保护后,主 FLASH 中的内容不会像解读保护那样丢失,它会被原样保留。

修改选项字节的过程

Flash_CR寄存器,操作选项字节的位描述:

操作选项字节的固件库函数:


结构体和宏定义:


/** 

  * @brief Option Bytes Registers

  */

  

typedef struct

{

  __IO uint16_t RDP;

  __IO uint16_t USER;

  __IO uint16_t Data0;

  __IO uint16_t Data1;

  __IO uint16_t WRP0;

  __IO uint16_t WRP1;

  __IO uint16_t WRP2;

  __IO uint16_t WRP3;

} OB_TypeDef;

 

#define OB                  ((OB_TypeDef *) OB_BASE) 

#define OB_BASE               ((uint32_t)0x1FFFF800)    /*!< Flash Option Bytes base address */

注意,这里的RDP定义成16位,但实际上的RDP只有8位。这里是把RDP和nRDP连续两个寄存器合起来。当向选项字节RDP写入时,stm32会把nRDP会自动取反并写入。

设置Flash写保护使能函数:


/* 宏定义,对应WRP寄存器的相应位 */

#define FLASH_WRProt_Pages0to1         ((uint32_t)0x00000001) 

#define FLASH_WRProt_Pages2to3         ((uint32_t)0x00000002) 

#define FLASH_WRProt_Pages4to5         ((uint32_t)0x00000004) 

#define FLASH_WRProt_Pages6to7         ((uint32_t)0x00000008) 

#define FLASH_WRProt_Pages8to9         ((uint32_t)0x00000010) 

 

/* FLASH Mask 掩码,用于取出页码的对应位 */

#define RDPRT_Mask               ((uint32_t)0x00000002)

#define WRP0_Mask                ((uint32_t)0x000000FF)

#define WRP1_Mask                ((uint32_t)0x0000FF00)

#define WRP2_Mask                ((uint32_t)0x00FF0000)

#define WRP3_Mask                ((uint32_t)0xFF000000)

 

/* 因为是 0 写保护,所以要对Flash页码来取反 */

FLASH_Pages = (uint32_t)(~FLASH_Pages);

 

/* 取出对应的WPR寄存器要写入的值,如果该页不写保护,则应该是0XFF */

WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_Mask);

WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_Mask) >> 8);

WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_Mask) >> 16);

WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_Mask) >> 24);

/* 没有先擦除选项字节,而是直接修改WRP寄存器的对应位,但是会存在一个问题,

   Flash只能把1改写成0,因此写保护是能生效的。但是,如果想要解除某页的写保护,

   无法使用这个函数,只能擦除选项字节 */

FLASH_EnableWriteProtection

/* 写保护所有页,直接0XFFFF FFFF,则取反后所有的位全为0,那么所有的WRP寄存器全部写入0 */

/* 解除写保护所有页,要先全部擦除选项字节,再0X0000 0000,取反后全为FFFF FFFF,那么所有

   WPR寄存器全为1,都不设置写保护  */

注意,这里有对CR寄存器进行操作,因此要先对Flash进行解锁。


设置读保护FLASH_ReadOutProtection函数:

注意:在设置Flash读写保护时,一定要预留一个接口(串口 按键等都可以),来解除Flash的读写保护,不然很有可能导致芯片报废了。另外,由于Flash的特性,在操作Flash之前,最好先进行擦除操作,不然可能会设置出错。


示例:利用按键功能,来设置 / 解除 读写保护


写保护例程:


**

  * @brief  反转写保护的配置,用于演示

          若芯片处于写保护状态,则解除,

若不是写保护状态,则设置成写保护

  * @param  无

  * @retval 无

  */

void WriteProtect_Toggle(void)

{

/* 获取写保护寄存器的值进行判断,寄存器位为0表示有保护,为1表示无保护 */

/*  若不等于0xFFFFFFFF,则说明有部分页被写保护了 */

if(FLASH_GetWriteProtectionOptionByte() != 0xFFFFFFFF )

{

FLASH_DEBUG("芯片处于写保护状态,即将执行解保护过程...");

//解除对FLASH_CR寄存器的访问限制

FLASH_Unlock();

 

/* 擦除所有选项字节的内容,操作之前先进行擦除 */

FLASH_EraseOptionBytes();

 

/* 对所有页解除,这一句不加,应该也可以解锁写保护,因为选项字节被擦除至全为1 */

FLASH_EnableWriteProtection(0x00000000);

FLASH_DEBUG("配置完成,芯片将自动复位加载新配置,复位后芯片会解除写保护状态rn");

 

/* 复位芯片,以使选项字节生效 */

NVIC_SystemReset();

}

else //无写保护

{

FLASH_DEBUG("芯片处于无写保护状态,即将执行写保护过程...");

//解除对FLASH_CR寄存器的访问限制

FLASH_Unlock();

 

/* 先擦除所有选项字节的内容,防止因为原有的写保护导致无法写入新的保护配置 */

FLASH_EraseOptionBytes();

 

/* 对所有页进行写保护 */

FLASH_EnableWriteProtection(FLASH_WRProt_AllPages);

 

FLASH_DEBUG("配置完成,芯片将自动复位加载新配置,复位后芯片会处于写保护状态rn");

 

/* 复位芯片,以使选项字节生效 */

NVIC_SystemReset();

}

 

}

读保护例程:


/**

  * @brief  反转读保护的配置,用于演示

          若芯片处于读保护状态,则解除,

若不是读保护状态,则设置成读保护

  * @param  无

  * @retval 无

  */

void ReadProtect_Toggle(void)

{

if(FLASH_GetReadOutProtectionStatus () == SET )

{

FLASH_DEBUG("芯片处于读保护状态rn");

//解除对FLASH_CR寄存器的访问限制

FLASH_Unlock();

FLASH_DEBUG("即将解除读保护,解除读保护会把FLASH的所有内容清空");

FLASH_DEBUG("由于解除后程序被清空,所以后面不会有任何提示输出");

FLASH_DEBUG("等待20秒后即可给芯片下载新的程序...rn");

FLASH_ReadOutProtection (DISABLE);

 

//即使在此处加入printf串口调试也不会执行的,因为存储程序的整片FLASH都已被擦除。

FLASH_DEBUG("由于FLASH程序被清空,所以本代码不会被执行,串口不会有本语句输出(SRAM调试模式下例外)rn");

 

}

else

{

FLASH_DEBUG("芯片处于无读保护状态,即将执行读保护过程...rn");

//解除对FLASH_CR寄存器的访问限制

FLASH_Unlock();

 

FLASH_ReadOutProtection (ENABLE);

printf("芯片已被设置为读保护,上电复位后生效(必须重新给开发板上电,只按复位键无效)rn");

printf("处于保护状态下无法正常下载新程序,必须要先解除保护状态再下载rn");

 

}

}

这些函数,本质上都是操作寄存器。实施起来其实并不复杂,但是不敢轻易尝试(即使我确定解除程序正确),因为一旦失败,可能芯片就报废了,永远无法写入,很矛盾。所以,使用J-Flash或者ST-Link来设置保护比较稳妥。


附加:


读保护等级:


在使用 hal 库来设置FLASH读保护时,看到有一个读保护等级的配置如下:


typedef struct

{

  uint32_t OptionType;  /*!< OptionType: Option byte to be configured.

                             This parameter can be a value of @ref FLASHEx_OB_Type */

 

  uint32_t WRPState;    /*!< WRPState: Write protection activation or deactivation.

                             This parameter can be a value of @ref FLASHEx_OB_WRP_State */

 

  uint32_t WRPPage;     /*!< WRPPage: specifies the page(s) to be write protected

                             This parameter can be a value of @ref FLASHEx_OB_Write_Protection */

 

  uint8_t RDPLevel;     /*!< RDPLevel: Set the read protection level..

                             This parameter can be a value of @ref FLASHEx_OB_Read_Protection */

 

  uint8_t USERConfig;   /*!< USERConfig: Program the FLASH User Option Byte: 

                             IWDG / STOP / STDBY / BOOT1 / VDDA_ANALOG / SRAM_PARITY

                             This parameter can be a combination of @ref FLASHEx_OB_IWatchdog, @ref FLASHEx_OB_nRST_STOP,

                             @ref FLASHEx_OB_nRST_STDBY, @ref FLASHEx_OB_BOOT1, @ref FLASHEx_OB_VDDA_Analog_Monitoring and

                             @ref FLASHEx_OB_RAM_Parity_Check_Enable */

 

  uint32_t DATAAddress; /*!< DATAAddress: Address of the option byte DATA to be programmed

                             This parameter can be a value of @ref FLASHEx_OB_Data_Address */

  

  uint8_t DATAData;     /*!< DATAData: Data to be stored in the option byte DATA

                             This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF */  

} FLASH_OBProgramInitTypeDef;

可以看到,这里有一个RDPLevel的结构体成员,然后会调用下面这个函数来写入RDP寄存器:


/**

  * @brief  Set the read protection level.

  * @param  ReadProtectLevel specifies the read protection level.

  *         This parameter can be one of the following values:

  *            @arg @ref OB_RDP_LEVEL_0 No protection

  *            @arg @ref OB_RDP_LEVEL_1 Read protection of the memory

  *            @arg @ref OB_RDP_LEVEL_2 Full chip protection

  * @note   Warning: When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0

  * @retval HAL status

  */

static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel)

{

  HAL_StatusTypeDef status = HAL_OK;

  

  /* Check the parameters */

  assert_param(IS_OB_RDP_LEVEL(ReadProtectLevel));

  

  /* Wait for last operation to be completed */

  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

  

  if(status == HAL_OK)

  { 

    /* Clean the error context */

    pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;

    

    /* If the previous operation is completed, proceed to erase the option bytes */

    SET_BIT(FLASH->CR, FLASH_CR_OPTER);

    SET_BIT(FLASH->CR, FLASH_CR_STRT);

 

    /* Wait for last operation to be completed */

    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

 

    /* If the erase operation is completed, disable the OPTER Bit */

    CLEAR_BIT(FLASH->CR, FLASH_CR_OPTER);

 

    if(status == HAL_OK)

    {

      /* Enable the Option Bytes Programming operation */

      SET_BIT(FLASH->CR, FLASH_CR_OPTPG);

      

      WRITE_REG(OB->RDP, ReadProtectLevel);

      

[1] [2]
关键字:stm32  Flash  读写保护 引用地址:stm32专题二十九:Flash 读写保护

上一篇:stm32专题二十八:读写内部Flash
下一篇:stm32专题三十:12864 IIC驱动

推荐阅读

 IPC CFX Demo Line(IPC全球互联工厂数据交换标准示范生产线)在LEAP Expo旗下的慕尼黑华南电子生产设展上向观众成功展示工业4.0生产线,这是IPC CFX Demo首次亮相中国。        此次IPC CFX Demo Line共有包括印刷、贴片、在线检测、回流焊、点胶、涂覆、焊接、清洗等设备在内的17家企业组成的完整电子组装生产线,基于IPC-CFX-2591标...
今天学了一下msp430 ad转换,编程ad单通道单次转换。首先顺一下思路:adc12 :单通道单次转换流程,开了adc12on 后,shs (选择输入信号源)= 0,ENC上跳,adc12sc 上跳, 开始采样,经过采样保持时间,转换成功,值放在adc12MEMx中。发生中断,adcifg置位,读取后adc12mem 后,自动复位。相关寄存器:ADC12CTL0 : SHT0_2 + ADC12ON设置采样保...
颇负盛名的英国房车锦标赛 (BTCC) 是一项始于 1958 年的悠久赛事。30 多辆精心设计的赛车为获胜竞相角逐,令赛事精彩壮观。2022年,英国房车锦标赛将会增加一个新的维度,并将成为业界首个采用轻度混合动力汽车的大型房车锦标赛。 BTCC 规定,驾驶员可以战术性地使用电动机提升车辆性能,并提高车辆加速能力。此合同已授予 Cosworth Electronics,该公司...
据外媒报道,威世集团(Vishay Intertechnology)宣布推出全新符合AEC-Q100标准的环境光传感器VEML6031X00,专为需要极高灵敏度以穿过深色覆盖材料感测光线的汽车和消费类应用打造。该威世半导体VEML6031X00搭载高度敏感的光电二极管、低噪声放大器、16位ADC和红外(IR)通道,并采用微型、不透明的2.67mm x 2.45mm表面贴装封装中,外廓低至0.6mm。(图...

史海拾趣

问答坊 | AI 解惑

windows ce5.0与MBCS之间的问题

在编译windows ce5.0的程序时,字符集采用的是MBCS,但是在编译的时候出现了一个错误: 1>D:\\Program Files\\Microsoft Visual Studio 8\\VC\\ce\\atlmfc\\include\\afxv_w32.h(227) : fatal error C1083: Cannot open include file: \'mbctype ...…

查看全部问答∨

定时器捕获与匹配冲突

我用CORTEX-M3内核,用TIM1做捕获中断,TIM3做匹配更新中断,但是发现TIM1的捕获必须在TIM3匹配中断禁止后才有用,有没有人了解的…

查看全部问答∨

wince上, 存储内存 <--> 程序内存 如何理解?

wince上, 控制面板->系统->内存(系统属性) wince上, 存储内存 <--> 程序内存 如何理解? 我的程序运行某个功能时,存储内存越来越少,是什么原因? …

查看全部问答∨

延时电路问题

我很菜,现在要用到一个延时5S到30S可调的电路,用这个电路(附件),R1,R2用的是可调的电位器。可是只有积分的作用没有起到延时的作用,望大家多多指点。 谢谢!…

查看全部问答∨

紧急求助:正在找工作,两家公司,一家做手机开发,一家电视开发哪个工作更有前途?

目前正在找工作。 两家公司,一家做手机开发。一家做电视开发。都给我了面试笔试通过的通知。两家的实力相当。 因为我以前做得软件很杂,所以对嵌入式行业不了解。 希望大家帮我分析下, 手机开发和电视开发哪个行业更有前途? …

查看全部问答∨

CF卡启动问题

请问各位大虾: 这两天在PC机上做CF卡启动,按照网上查的资料修改了相关文件后生成了bootrom和vxworks文件,启动行设置为 ata=0,0(0,0)target:/ata0/vxWorks h=10.21.110.16 e=10.21.110.30 u=TargetUser pw=vxworks 然后在DOS下vxsys C:(C为 ...…

查看全部问答∨

探讨下关于不等电位的MOS管驱动

如图,请大家一起他们探讨下关于这种不等电位的MOS管驱动有哪些办法,不用专门芯片,谢谢 …

查看全部问答∨

恳请武林高手出山指点一二

各位大虾:            小弟最近在学习uc/os ii 在arm7 ADuC7026上的移植,想第一步实现操作系统下的简单控制,单任务,比方说LED闪烁控制,希望各位大牛门能帮忙指点一二,帮忙详细讲解一下整 ...…

查看全部问答∨

今天真是悲惨的一天啊

今天真是悲惨的一天啊 最近想A8开发板都想疯了 公司没法上网,请朋友帮忙抢购 结果呢,没抢到,她不会操作..... 啊啊啊!我的A8啊 管理员啊,管理员…

查看全部问答∨

基于RL78/G14的双轮自平衡小车

本设计采用RL78/G14评估版作为主控芯片,使用大容量12v锂电池供电,以lm2596s作为电压转化芯片,把12v转化为5v给单片机供电,lm2596s最大电流可达2a非常适合本设计,用l298作为电机驱动芯片,l298最大电流大,在高速pwm波下不易失真,该系统传感器 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved