如何更改STM32F3上的读取保护?

如何更改STM32F3上的读取保护

 
  1. 介绍
STM32F3微控制器提供三级读出保护:0级(无保护)、1级(闪存、备份SRAM和备份寄存器受保护)和2级(与1级相同,但通过锁定选项字节提供永久保护)。需要注意的是,级别2只应用于最终产品,而不是在开发阶段。
在0级时,不启用读出保护,并且在所有引导配置中都可以对闪存和备份SRAM进行所有读写操作。微控制器上的选项字节也可以更改。
级别1设置闪存的读取保护。只有从用户闪存启动时才允许访问受保护的内存,否则会生成系统硬故障,阻止所有代码执行,直到下一次通电重置。选项字节在这个级别上仍然是可配置的,使得可以通过系统引导加载程序模式或常规SWD/JTAG接口将读出保护恢复到级别0。
级别2提供与级别1相同的保护,但通过锁定选项字节提供永久保护。一旦设置了2级保护,它就无法撤消,并且微控制器将保持永久保护,在这种模式下,系统引导加载程序也无法访问。
从1级保护倒退到0级保护会导致闪存和备份SRAM的大规模擦除,在此过程中只有选项字节不会被擦除。
在本文中,我们将使用固件对其进行修改来展示此功能。您也可以使用此方法配置任何其他选项字节,但重点将放在读取保护上。
  1. 微控制器配置
首先,让我们为STM32F3系列创建一个STM32CubeIDE项目,然后添加我们的逻辑。
打开软件后,单击文件->新建->STM32项目:

加载菜单后,搜索STM32F334R8,您可以使用相应的Nucleo板轻松定位它,然后按“下一步”。

为项目命名(避免使用特殊字符和空格),然后单击“使用默认设置完成”。

现在我们将设置必要的微控制器外围设备,包括SWD接口、USART和GPIO:
要设置微控制器的SWD,请转到系统核心>系统并启用调试串行线,我们可以使用默认值时基源系统定时器


接下来,我们将配置USART2,它在Nucleo板上连接到板上的ST-LINK。在ST Link的虚拟COM端口的帮助下,我们将使用此链接来中继消息。转到连接>USART2并将其设置为异步模式。配置选项卡下的默认基本参数应该有效,但可以根据您的偏好进行调整,只需记住,稍后配置终端时会使用此参数。

对于按钮引脚和LED,我们将使用NUCLEO板上可用的硬件:第13页连接到按钮,我们可以通过单击并选择“EXTI_13'。之后,为按钮设置一个用户标签,执行以下操作:系统核心>GPIO>PC13及以下用户标签类型'B1[蓝色按钮]'。

至于LED,我们将使用第5页,因为它连接到板载的绿色LED。在下拉菜单上,选择GPIO_输出,类似于按钮引脚,转到系统核心>GPIO>PA5及以下用户标签类型'LD2[绿色Led]’。

现在可以点击设备配置工具代码生成图标,或按Alt+K。这将生成一个基本项目,其中包含我们使用GUI选择的所有配置。
  1. 编码
基本代码准备好后,是时候开始添加应用程序代码了。首先在private includes部分包含stdio.h库,这样我们就可以轻松地打印到vcom终端。
#包括“stdio.h”
在私有函数原型中,我们将创建一个函数,允许我们简单地使用printf函数将其传输到USART。
int __io_putchar(int ch){HAL_UART_Transmit(&huart2,(uint8_t*)&ch,1100);返回ch;}

用户代码以0开头在第节中,我们将创建回归函数,使其从微控制器的RAM而不是Flash运行
void __attribute__((__section__(“.RamFunc”))RDP_Progression(void){FLASH_OBProgramInitTypeDef选项字节构造;__disable_irq();//禁用中断打印(“大批量擦除开始\r\n”);HAL_FLASH_Unlock();//Unlock闪存HAL_FLASH-OB_Unlock();//解锁选项字节OptionsBytesStruct.OptionType=OPTIONBYTE_RDP//配置RDP选项ByteConstruct.RDPLevel=OB_RDP_LEVEL_0;HAL_FLASHEx_OB程序(&OptionsByteConstruct);HAL_FLASH_OB_Launch();}

仍然在同一评论部分下,添加一个简单的功能,以给定的时间间隔闪烁板载LED。
void ToggleLED(uint16_t n)//用于切换板载LED的功能{if(HAL_GPIO_ReadPin(LD2_GPIO_Port,LD2_Pin)){printf(“\033[5];32mLED\033[0m\r\n”);HAL_GPIO_2 WritePin(LDA2_GPIO_Port,LD2_Pin,GPIO_Pin_RESET}

接下来,在主函数内部和用户代码开始1标签我们将定义一个结构来编辑选项字节。
FLASH_OBProgramInitTypeDef选项字节结构//定义一个结构来存储闪存的Options Bytes配置
下一个代码部分应该放在用户代码开始3完3。在RDP级别检查之后,发生小决策分支,如果它处于级别1,则代码将以500ms的速率闪烁led,直到按下按钮。按下按钮后,它将通过解锁闪存和Option字节来启动回归过程,并最终调用之前添加并从RAM内存执行的RDP_regression函数。重要的是要记住,在RDP回归时,会执行完全批量擦除。
 
printf(“\033[0m”);HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);//获取闪存的当前Options Bytes配置//如果(OptionsBytestruct.RDPLevel==OB_RDP_level_1{ToggleLED(500);}printf(“等待BT1释放\r\n”);//循环直到释放按钮BT1,同时(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)!=GPIO_PIN_SET){;}printf(“RDP回归LV0初始化\r\n”);//调用RDP_Progression()函数RDP_Progress();}

然后,代码每2秒执行一次检查,以决定微控制器的RDP级别何时应设置为1。当它等待按下和释放按钮时,代码会以2s的速率闪烁led。释放该按钮时,RDP级别设置为1。
//如果RDP被设置为0,等待按下按钮将其设置为1级printf(“\033[96mPress BT1 to change Option Bytes\033[0m\r\n”);如果(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)!=GPIO_Pin_set _FLASH_OB_解锁()!=HAL_OK){printf(“等待OB解锁\r\n”);}选项字节指令。选项类型=OPTIONBYTE_RDP//配置RDP选项ByteConstruct.RDPLevel=OB_RDP_LEVEL_1;而(HAL_FLASHEx_OBProgram(&OptionsBytestruct)!=HAL_OK){printf(“正在等待OB程序\r\n”);}print f(“RDP现在将设置为级别1\r\n”);printf(“OBLaunch\r\n”);HAL_FLASH_OB_Launch();}else{切换LED(2000);}/*用户代码结束3*/
 
  1. 测试
要测试此代码,我们必须遵循特定的流程。首先,您应该使用创建的代码对NUCLEO板进行编程。构建完成后,单击STM32CubeIDE上的绿色按钮,突出显示如下:

之后,必须断开NUCLEO板与USB计算机的连接,并从ST链路上拆下CN2跳线,如图所示:

现在,板必须插回电源,这将接通板的电源并重新启动程序执行。
注意:移除ST链路跳线的原因是为了防止ST链路的调试连接(在板上电时自动发生)干扰RDP进入/退出。
为了确认这一点,您可以打开一个终端,例如tera term,并将其配置为与我们之前设置的USART2配置相匹配,只需回忆一下,它是:115200/8/N/1。终端应显示以下内容:

现在,按住蓝色按钮,直到出现以下信息:

释放蓝色按钮将RDP级别更改为1。MCU将重置自身,并以更快的LED闪烁率显示新的RDP级别消息。

再次按下并释放蓝色按钮可将RDP级别恢复为0,从而导致MCU的大规模擦除。

在这一点上,闪存被自动大批量擦除。
警告:这可能需要长达10秒的时间,如果在闪存被完全擦除之前重置微控制器,则RDP字节将保持锁定在级别1,并且您的程序将被删除,因此在闪存被大规模擦除时保持静止非常重要。
要确认RDP回归,请重新安装CN2跳线,断开USB电缆并重新连接微控制器,使其通电,然后使用STM32CubeProg(GUI或CLI)读取内存。这里演示了如何使用CLI读取选项字节。
打开windows命令提示符,键入以下命令,如图所示
cd C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgramer\bin程序文件
STM32_Programer_CLI.exe-c端口=swd-ob显示


如果RDP回归有效,您将看到如下消息:

通过使用命令“STM32_Programer_cli.exe-c port=swd mode=HOTPLUG-r32 0x08000000 1000”,您可以看到闪存的内容,正如我们所预期的,这些内容都是FFFF FFFF:

为了查看正在进行的RDP保护,您可以重新执行步骤(使用CubeIDE重新编程代码,卸下CN2跳线,关闭电源,按下按钮设置RDP级别1),并在CN2跳线设置为级别1后安装它。现在,您可以重新发出选项字节命令“STM32_Programer_CLI.exe-c port=swd-ob disp”以查看RDP状态。请注意,这将触发读出保护,执行此命令后,您的微控制器将完全停止,只有在电源循环后才能恢复。

为了进一步探索,您可以尝试使用命令“STM32_Programer_cli.exe-c port=swd mode=HOTPLUG-r32 0x08000000 1000”再次检查Flash内容,但这一次您将收到一条错误消息,因为微控制器已保护Flash内容,并且微控制器将再次停止,直到重新通电。

注意:您可以按照相同的过程将RDP设置为级别2,但请记住,此操作是不可逆的,只能在最终生产时执行。如果您需要在RDP级别2之后更新固件,您应该首先实现自己的引导加载程序(请参阅IAP引导加载程序示例https://www.st.com/content/ccc/resource/technical/document/application_note/27/38/37/58/c2/8c/40/07/...因为RDP级别2将禁用内置的系统引导加载程序。
  1. 结论

在本文中,您学习了如何为STM32F3系列配置选项字节,更具体地说是读取保护功能,允许您的应用程序激活FLASH保护,甚至在必要时恢复到无保护状态。