开发环境:
一般情况下,我们在KEIL-MDK中开发时,调试下载程序默认是把程序下载进FLASH中运行的,CODE和RW-data的内容被写进FLASH存储,单片机掉电数据不会丢失。
但是在调试阶段存在大量的程序下载、程序调试,一方面下载进FLASH比较慢,尤其开发比较大的STM32程序时;另一方面对FLASH频繁擦写造成的磨损减少了其使用寿命。那么此时我们就可以将程序直接下载进内存(SRAM)中去运行调试,既下载的快又有效的保护了FLASH的寿命。
除去加快调试的目的,还有一个作用就是可以利用keil将代码下载进内存,从而实现解除写保护!
在项目完工交付阶段或者实现了量产,为了保护芯片内的程序不被别人非法拷贝,芯片一般会在出厂时开启读保护,要么在代码中加入,要么在烧录程序后人工通过软件开启该功能,比如STM32 ST-LINK Utility,当然,也可以使用该工具关闭读保护功能。
但这样会导致一个麻烦的问题:无法正常调试。
如果每次都使用STM32 ST-LINK Utility软件或者JFLASH软件去解锁FLASH,那就太麻烦了。下面就介绍一种使用KEIL-MDK来解除读保护的方法。
先说一下读保护的原理:
设置读保护功能是通过设置相应的Option Bytes来实现的,并且掉电不会消失。
而解除读保护是则是复位相应的Option Bytes来实现,掉电也不会消失。
但不同的是,解除读保护设置完之后,芯片自动会擦除整颗芯片,这样就不能通过解除读保护进而读取整颗芯片代码了,顾就实现了程序的非法读取保护。
此时,你会发现,虽然无法读取FLASH,但是却可以通过调试器连接上它,那么我们就可以通过配置keil的一些设置,将代码下载进RAM中运行,而下载进RAM的这段代码中就包含着解除读保护的程序!
具体操作步骤如下:
然后在设置一下链接地址,使代码下载进SRAM中:
接下来新建一个Debug_RAM.ini的配置文件:
该文件在目录E:\install\Keil_v5\Packs\Keil\STM32F1xx_DFP\2.3.0\Boards\Keil\MCBSTM32C\Blinky\
中存在,可以直接拷贝过来!
该文件内容如下:
/*----------------------------------------------------------------------------
* Name: Debug_RAM.ini
* Purpose: RAM Debug Initialization File
* Note(s):
*----------------------------------------------------------------------------
* This file is part of the uVision/ARM development tools.
* This software may only be used under the terms of a valid, current,
* end user licence from KEIL for a compatible version of KEIL software
* development tools. Nothing else gives you the right to use this software.
*
* This software is supplied "AS IS" without warranties of any kind.
*
* Copyright (c) 2008-2011 Keil - An ARM Company. All rights reserved.
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
Setup() configure PC & SP for RAM Debug
*----------------------------------------------------------------------------*/
FUNC void Setup (void) {
SP = _RDWORD(0x20000000); // Setup Stack Pointer
PC = _RDWORD(0x20000004); // Setup Program Counter
_WDWORD(0xE000ED08, 0x20000000); // Setup Vector Table Offset Register
}
FUNC void OnResetExec (void) { // executes upon software RESET
Setup(); // Setup for Running
}
load %L incremental
Setup(); // Setup for Running
g, main
新增这两个宏定义:VECT_TAB_SRAM
,USER_VECT_TAB_ADDRESS
编译,然后点击Debug即可。
此时,程序应该自动停止在断点处 __breakpoint(0),这说明解除代码已经顺利运行完成!
经过这样设置后,每次需要解除芯片读保护功能时,只要切换目标后即可成功解除(前提是已经编译过一次了),非常方便,省去了再去使用STM32 ST-LINK Utility软件的麻烦!
void FLASH_SetReadProtectionState(int state)
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct;
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
if(state)
{
if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL0)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL1;
HAL_FLASHEx_OBProgram(&OptionsBytesStruct);
}
}
else
{
if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL1)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL0;
HAL_FLASHEx_OBProgram(&OptionsBytesStruct);
}
}
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
}
ends…