以STM32F103为例。
参见stm32f10x.h头文件中的定义:
#define OB_BASE ((uint32_t)0x1FFFF800) /*!< Flash Option Bytes base address */
共有16个字节,定义如下:
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;
每一个都是16位的(2个字节),但是,每一个元素的2个字节中,高字节和低字节是互补关系。相当于只有一个字节是有效内容。实际上,操作的是偶地址的字节,奇地址的字节是其补码。
通过STM32 ST-LINK Utility读取的值为:
通过仿真器查看到的也一样:
地址:0x1FFF F800
规则如下:
即:只有当RDP字节和nRDP字节互为补码时,取消读保护。默认情况下刚好是0xA5和0x5A。
将选项字节区擦除后,RDP为0xFFFF,也是读保护状态。读保护时,连JTAG和SWD都不能使用。
地址:0x1FFF F802
低3位有效:
Bit0: 0=软件控制使能片内看门狗IWDG;1=硬件使能片内看门狗。此时,一上电看门狗就生效了,并且不能取消,必须及时喂狗。
Bit1: 进入STOP模式时是否产生复位。0=复位,1=不复位。默认为1,不复位。
BIT2:进入STANDBY模式时是否产生复位。0=复位,1=不复位。默认为1,不复位。
地址:0x1FFF F804 和 0x1FFF F806
供用户使用。
地址:0x1FFF F808 / 0x1FFF F80A / 0x1FFF F80C / 0x1FFF F80E,共4个字节。
这4个字节,共32个位,其中,bit0~bit30这31个位,每个位控制2个FLASH页(扇区)的写保护;Bit31控制其他页(第62~511页)的写保护。也就是说,前面的62个页可以单独配置(以2页为单位),后面的只能统一配置。
0=保护;1=不保护。默认为全1,全都不保护。
每次系统复位后,选择字节装载器读出信息块的数据并保存在寄存器中;每个选择位都在信息
块中有它的反码位,在装载选择位时反码位用于验证选择位是正确的,如果有任何的差别,将
产生一个选择字节错误标志(OPTERR)。当发生选择字节错误时,对应的选择字节被强置为
0xFF。当选择字节和它的反码均为0xFF时(擦除后的状态),上述验证功能被关闭。
如果试图在一个受保护的页面进行编程或擦除操作,在闪存状态寄存器(FLASH_SR)中会返回一
个保护错误标志( WRPRTERR)。
上述的8个有效字节,会被映射到FLASH控制寄存器FLASH_OBR和FLASH_WRPR。
On every system reset, the option byte loader (OBL) reads the information block and stores
the data into the Option byte register (FLASH_OBR) and the Write protection register
(FLASH_WRPR). Each option byte also has its complement in the information block. During
option loading, by verifying the option bit and its complement, it is possible to check that the
loading has correctly taken place. If this is not the case, an option byte error (OPTERR) is
generated. When a comparison error occurs the corresponding option byte is forced to
0xFF. The comparator is disabled when the option byte and its complement are both equal
to 0xFF (Electrical Erase state).
每次系统复位时,选项字节加载器(OBL)都会读取信息块,并将数据存储到选项字节寄存器(FLASH_OBR)和写保护寄存器(FLASH_WRPR)中。 每个选项字节在信息块中也都有其补码。 在选项加载期间,通过验证选项位及其补码,可以检查加载是否正确进行。 如果不是这种情况,则会生成选项字节错误(OPTERR)。 当发生比较错误时,相应的选项字节被强制为0xFF。 当选项字节及其补码都等于0xFF(电擦除状态)时,比较器被禁用。
地址:0x4002 201C
复位值:0x03FF FFFC(这是出厂值,实际复位值取决于上一次编程后的结果。最低2位取决于当前状态。)
地址:0x4002 2020
直接映射选项字节中的WRP0~WRP3.
可以从FLASH上读,也可以从映射寄存器中读。
选项字节擦除
建议使用如下步骤对选项字节进行擦除:
1.检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作。
2.解锁FLASH_CR寄存器的OPTWRE位。即,打开写使能。
3.设置FLASH_CR寄存器的OPTER位为1。选择选项字节擦除操作。
4.设置FLASH_CR寄存器的STRT位为1。
5.等待FLASH_SR寄存器的BSY位变为0,表示操作完成。
6.查询FLASH_SR寄存器的EOP位,EOP为1时,表示操作成功。
7.读出选项字节并验证数据。
由于选项字节只有16字节,因此,擦除时是整个选项字节都被擦除了。
参考库函数:
FLASH_Status FLASH_EraseOptionBytes(void)
选项字节编程
建议使用如下步骤对选项字节进行编程:
1.检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的编程操作。
2.解锁FLASH_CR寄存器的OPTWRE位。即,打开写使能。
3.设置FLASH_CR寄存器的OPTPG位为1。选择编程操作。
4.写入要编程的半字到指定的地址。启动编程操作。
5.等待FLASH_SR寄存器的BSY位变为0,表示操作完成。
6.查询FLASH_SR寄存器的EOP位,EOP为1时,表示操作成功。
7.读出写入的选项字节并验证数据。 对选项字节编程时,FPEC使用半字中的低字节并自动地计算出高字节(高字节为低字节的反码),并开始编程操作,这将保证选项字节和它的反码始终是正确的。
参考库函数:
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY);
在编辑扇区写保护时,对于前面62个扇区,每次勾选时自动选择一对扇区,如:
对于Page62以及后面的扇区,选择其中的一个,则会自动全部选择:
编辑用户数据字节,
然后,点击“Apply”,工具会先擦除再写入。写入后:
参考资料:
PM0068 Programming manual STM32F10xxx XL-density Flash programming.pdf
闪存编程手册