OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7090|回复: 6

stm32 选项字节的使用,u16宽度掉电存储用户数据

[复制链接]

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2018-6-13 22:16:27 | 显示全部楼层 |阅读模式
本帖最后由 275891381 于 2018-6-13 22:33 编辑

选项字节是详细参考  http://blog.sina.com.cn/s/blog_bf63e2650102vyi1.html

选项字节
     选项字节用于存储芯片使用者对芯片的配置信息。
目前,所有的STM32101xx、STM32102xx、STM32103xx、STM32105xx、STM32107xx产品,选项字节都是16字节。但是这16字节,每两个字节组成一个正反对,即,字节1是字节0的反码,字节3是字节2的反码,...,字节15是字节14的反码,所以,芯片使用者只要设置8个字节就行了,另外8个字节系统自动填充为反码。因此,有时候,也说STM32的选项字节是8个字节,但是占了16字节的空间。选项字节的8字节正码概述如下:


RDP   字节0。读保护字节,存储对主存储块的读保护设置。
USER  字节2。用户字节,配置看门狗、停机、待机。
Data0  字节4。数据字节0,由芯片使用者自由使用 0x1FFFF804
Data1  字节6。数据字节1,由芯片使用者自由使用 0x1FFFF806
WRP0  字节8。写保护字节0,存储对主存储块的写保护设置。
WRP1  字节10。写保护字节1,存储对主存储块的写保护设置。
WRP2  字节12。写保护字节2,存储对主存储块的写保护设置。
WRP3  字节14。写保护字节3,存储对主存储块的写保护设置。



用户可以使用的是 Data0 Data1 两个u8位置

这样可以用这u16(两个u8)保存自己掉电保存的紧急数据。自己可以合理分配u16的位,发挥使用效果最大化


//用户选项字节
u16  OptionByte;
u16 OptionByte_Read(void)      //两个8字节合成1个16字节使用
{
                u8 high=(*(vu16*)(0x1FFFF804))&0x00ff;//读0x1FFFF804
                u8 low =(*(vu16*)(0x1FFFF806))&0x00ff;//读0x1FFFF806
                return (   (high<<8)+low  );
}
void OptionByte_Write(u16 data)//两个8字节合成1个16字节使用
{
                FLASH_Unlock();//解锁
                FLASH_EraseOptionBytes();//flash为ff时候才能写入,所以先擦除,网上很多不成功就是没擦除
                FLASH_ProgramOptionByteData(0x1FFFF804,data>>8);    //写0x1FFFF804
                FLASH_ProgramOptionByteData(0x1FFFF806,data&0x00ff);//写0x1FFFF806
                FLASH_Lock();  //上锁
}

main 里面
{
                        //简单记录复位次数
                        OptionByte=OptionByte_Read();   
                        printf("OptionByte=0x%4x\r\n",OptionByte);
                        OptionByte_Write(OptionByte+1);

}

串口下载程序的时候可以设置初值
1.JPG




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

29

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
249
金钱
249
注册时间
2018-5-12
在线时间
56 小时
发表于 2018-6-14 08:18:09 | 显示全部楼层
楼主确认仅解锁FLASH就可以编程用户字节?
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2018-6-14 08:51:06 | 显示全部楼层
admvip 发表于 2018-6-14 08:18
楼主确认仅解锁FLASH就可以编程用户字节?

确认,别的操作,库函数里面都有了
回复 支持 反对

使用道具 举报

1

主题

29

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
249
金钱
249
注册时间
2018-5-12
在线时间
56 小时
发表于 2018-6-14 11:06:30 | 显示全部楼层
本帖最后由 admvip 于 2018-6-14 11:08 编辑
275891381 发表于 2018-6-14 08:51
确认,别的操作,库函数里面都有了

我没有试过标准库的OP字节读写操作,不过在HAL库,写入OP用户字节是需要两步解锁的,先解锁FLASH,然后解锁obFLASH。这样才可以编程OP里面的用户字节。
/*保存程序数据至Flash,实现掉电存储*/
        HAL_FLASH_Unlock();           //解锁flash
        HAL_FLASH_OB_Unlock();     //解锁flash ob
        FLASH_OBProgramInitTypeDef obData;        //定义flash ob编程结构体变量
        HAL_FLASHEx_OBGetConfig(&obData);              //读取原ob数据
        HAL_FLASHEx_OBErase();                                //ob数据擦除
        
        obData.DATAAddress = OB_DATA_ADDRESS_DATA0;        //设置用户字节0的flash地址
        obData.DATAData = ch;                                                  //修改用户字节0的内容,保存工作信道号至Flash保存
        obData.OptionType = OPTIONBYTE_DATA;                       //操作模式设定为用户字节操作
        while(HAL_FLASHEx_OBProgram(&obData) != HAL_OK);    //写入修改后的ob结构体数据
        HAL_FLASH_OB_Lock();        //锁定flash ob
        HAL_FLASH_Lock();                //锁定flash
回复 支持 反对

使用道具 举报

61

主题

160

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
270
金钱
270
注册时间
2012-1-12
在线时间
93 小时
发表于 2018-6-14 14:43:13 | 显示全部楼层
有个小小的疑问,当运行FLASH_EraseOptionBytes()这个函数之后,16字节的用户数据不是都擦除了吗?那这样的话芯片的配置信息不就没有了吗?
回复 支持 反对

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
 楼主| 发表于 2018-6-14 16:47:55 | 显示全部楼层
47933673 发表于 2018-6-14 14:43
有个小小的疑问,当运行FLASH_EraseOptionBytes()这个函数之后,16字节的用户数据不是都擦除了吗?那这样的 ...

没试,你可以试试,要是都擦出了,你可以向4楼那样,全部读出来改了再写进去
回复 支持 反对

使用道具 举报

4

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2016-1-25
在线时间
16 小时
发表于 2019-4-19 10:20:01 | 显示全部楼层
GD32版本:

[mw_shl_code=c,false]/* 写data区,addr_data0_or_data1=0或1
* 设置完毕后,重启才能获取。
* 成功返回0,否则返回-1
*/
int ob_datax_write(int addr_data0_or_data1,uint8_t data)
{
        uint8_t u8;
        uint16_t u16;
        int ret = -1;

        fmc_unlock();
        ob_unlock();

        /* 备份 */
        u8 = ob_user_get();
        u16 = ob_data_get();
        ob_erase();

        if(ob_data_program(0x1FFFF804,(addr_data0_or_data1 == 0)?data: (u16&0xFF)) != FMC_READY)
                goto fail;

        if(ob_data_program(0x1FFFF806,(addr_data0_or_data1 == 1)?data: ((u16>>8)&0xFF) ) != FMC_READY)
                goto fail;

        if(ob_user_write(u8&OB_FWDGT_SW,u8&OB_DEEPSLEEP_NRST,u8&OB_STDBY_NRST,u8&OB_BOOT_B0) != FMC_READY)
                goto fail;

        ret = 0;
fail:
        ob_lock();
        fmc_lock();
        return ret;
}[/mw_shl_code]
诚交各路大侠
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 06:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表