STM32 之七 备份域(备份寄存器、备份SRAM)详解及数据丢失问题处理
某些STM32芯片提供了备份SRAM,例如STM32F系列芯片有4K的备份SRAM。然而在使用过程中发现备份区域数据丢失!下面从STM32系列芯片提供的整个备份域来看看啥情况。
电池备份域
首先,这部分在参考手册的电源(PWR)章节有详细的介绍。器件的工作电压 (VDD) 要求介于 1.8 V 到 3.6 V 之间。嵌入式线性调压器用于提供内部 1.2 V数字电源。当主电源 VDD 断电时,可通过 VBAT 电压为实时时钟 (RTC)
、RTC备份寄存器
和 备份 SRAM(BKP SRAM)
供电。具体如下图:
手册中有许多对于使用芯片时对于电源部分设计的要求,例如引脚的使用、电流的要求等等,具体见手册!
备份域访问
复位后,备份域(RTC 寄存器、RTC 备份寄存器和备份 SRAM)将受到保护,以防止意外的写访问。要使能对备份域的访问,请按以下步骤进行操作:
访问 RTC 和 RTC 备份寄存器
- 将 RCC_APB1ENR 寄存器中的 PWREN 位置 1,使能电源接口时钟(分别参见手册第 6.3.15 节和第 6.3.16 节了解 STM32F405xx/07xx 和 STM32F415xx/17xx 和 STM32F42xxx 和 STM32F43xxx)
- 将用于 STM32F405xx/07xx 和 STM32F415xx/17xx 的 PWR 电源控制寄存器 (PWR_CR)和 用于STM32F42xxx 和 STM32F43xxx 的 PWR 电源控制寄存器 (PWR_CR) 中的 DBP 位置 1,使能对备份域的访问
- 选择 RTC 时钟源:参见手册第 6.2.8 节:RTC/AWU 时钟
- 通过对 RCC 备份域控制寄存器 (RCC_BDCR) 中的 RTCEN [15] 位进行编程,使能 RTC 时钟
访问备份 SRAM
- 将 RCC_APB1ENR 寄存器中的 PWREN 位置 1,使能电源接口时钟(分别参见手册第 6.3.15 节和第 6.3.16 节了解 STM32F405xx/07xx 和 STM32F415xx/17xx 和 STM32F42xxx 和 STM32F43xxx)。
- 将用于 STM32F405xx/07xx 和 STM32F415xx/17xx 的 PWR 电源控制寄存器 (PWR_CR) 和用于STM32F42xxx 和 STM32F43xxx 的 PWR 电源控制寄存器 (PWR_CR) 中的 DBP 位置 1,使能对备份域的访问。
- 通过将 RCC AHB1 外设时钟使能寄存器 (RCC_AHB1ENR) 中的 BKPSRAMEN 位置 1,使能备份 SRAM 时钟。
想要访问备份域还是非常简单的,下面以访问备份SRAM为例,从代码角度说明一下(具体见注释即可):
/*** @brief (使用标准外设库)备份SRAM初始化* @param[in] void* @retval NULL*/
static void vBkpSramInit(void)
{/* 电源接口时钟使能 (Power interface clock enable) */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);/* DBP 位置 1,使能对备份域的访问 */PWR_BackupAccessCmd(ENABLE);/* 通过将 RCC AHB1 外设时钟使能寄存器 (RCC_AHB1ENR) 中的 BKPSRAMEN 位置 1, 使能备份 SRAM 时钟 */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);/* 应用程序必须等待备份调压器就绪标志 (BRR) 置 1,指示在待机模式和 VBAT 模式下会保持写入 RAM 中的数据。 */while(PWR_GetFlagStatus(PWR_FLAG_BRR) != SET);
}/** (使用HAL库)备份SRAM初始化* * @param[in] NULL* @retval Null
**/
void BKP_SRAM_Init(void)
{/* 电源接口时钟使能 (Power interface clock enable) */__HAL_RCC_PWR_CLK_ENABLE();/* DBP 位置 1,使能对备份域的访问 */HAL_PWR_EnableBkUpAccess();/* 通过将 RCC AHB1 外设时钟使能寄存器 (RCC_AHB1ENR) 中的 BKPSRAMEN 位置 1, 使能备份 SRAM 时钟 */__HAL_RCC_BKPSRAM_CLK_ENABLE();/* 应用程序必须等待备份调压器就绪标志 (BRR) 置 1,指示在待机模式和 VBAT 模式下会保持写入 RAM 中的数据。 */HAL_PWREx_EnableBkUpReg();
}
经过以上初始化之后,就可以使用备份域中的各部分功能了(RTC和备份SRAM的初始化有些区别)。
备份域的使用
初始化后对于备份域中各功能(RTC、RTC备份寄存器、备份SRAM)的使用就比较灵活了。
- RTC: 使用相对来说比较复杂,后面独立介绍
- RTC备份寄存器: 读写非常简单,标准外设库和HAL库都提供了函数直接进行读写。
/*----------------------------标准外设库----------------------------*/
/*** @brief Writes a data in a specified RTC Backup data register.* @param RTC_BKP_DR: RTC Backup data Register number.* This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to * specify the register.* @param Data: Data to be written in the specified RTC Backup data register. * @retval None*/
void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data)
{__IO uint32_t tmp = 0;/* Check the parameters */assert_param(IS_RTC_BKP(RTC_BKP_DR));tmp = RTC_BASE + 0x50;tmp += (RTC_BKP_DR * 4);/* Write the specified register */*(__IO uint32_t *)tmp = (uint32_t)Data;
}
/*** @brief Reads data from the specified RTC Backup data Register.* @param RTC_BKP_DR: RTC Backup data Register number.* This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to * specify the register. * @retval None*/
uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR)
{__IO uint32_t tmp = 0;/* Check the parameters */assert_param(IS_RTC_BKP(RTC_BKP_DR));tmp = RTC_BASE + 0x50;tmp += (RTC_BKP_DR * 4);/* Read the specified register */return (*(__IO uint32_t *)tmp);
}/*----------------------------HAL库----------------------------*/
/*** @brief Writes a data in a specified RTC Backup data register.* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains* the configuration information for RTC. * @param BackupRegister: RTC Backup data Register number.* This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to * specify the register.* @param Data: Data to be written in the specified RTC Backup data register. * @retval None*/
void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
{uint32_t tmp = 0U;/* Check the parameters */assert_param(IS_RTC_BKP(BackupRegister));tmp = (uint32_t)&(hrtc->Instance->BKP0R);tmp += (BackupRegister * 4U);/* Write the specified register */*(__IO uint32_t *)tmp = (uint32_t)Data;
}
/*** @brief Reads data from the specified RTC Backup data Register.* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains* the configuration information for RTC. * @param BackupRegister: RTC Backup data Register number.* This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to * specify the register. * @retval Read value*/
uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
{uint32_t tmp = 0U;/* Check the parameters */assert_param(IS_RTC_BKP(BackupRegister));tmp = (uint32_t)&(hrtc->Instance->BKP0R);tmp += (BackupRegister * 4U);/* Read the specified register */return (*(__IO uint32_t *)tmp);
}
- 备份SRAM: 这部分的使用就更加灵活了,可以直接当内存去访问。推荐一种使用
分散加载文件
进行访问的方式。具体为定义自己的结构体,使用结构体定义变量BKP_SRAM myContent __attribute__((section("BKP_SRAM_SECTION")));
,最后使用分散加载文件,将以上定义的变量直接映射到备份SRAM即可。
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x0000C000 { ; load region size_regionER_IROM1 0x08000000 0x0000C000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO)}RW_IRAM1 0x20000000 0x00020000 { ; RW data.ANY (+RW +ZI)}RW_BkSRAM 0x40024000 0x1000 {*.o (BKP_SRAM_SECTION, +First) ; 备份SRAM}
}
备份SRAM问题
在实际产品中使用时,发现备份SRAM中的数据丢失!检查在硬件上并没有出现任何问题,于是从软件一步步分析如下:
- 产品( 使用STM32F407VG )中实现了IAP、APP在线升级,备份域在这两部程序中均有使用(两部分程序中均对备份域进行了初始化)。
- 在由IAP跳转到APP后,发现在APP中初始化的备份SRAM中原有数据全部丢失( 准确的说应该是时钟不起作用,导致数据全是 0,看似数据丢失 )
- 分析原因,STM32芯片在上电后默认以内部低速时钟源(HSI运行),如果用户配置了使用外部时钟源,则再配置外部时钟源,然后将时钟切换为外部。程序在APP中配置时钟前是正常的,一旦时钟源出现切换则导致备份域再次初始化之后就无效了!感觉应该是 备份域的各种初始化必须在时钟初始化之后再进行配置才可以,颠倒顺序将导致备份域时钟初始化后不可用! 但是,其他外设(例如GPIO,同是挂在AHP总线上)却不受以上限制,比较奇怪!
解决
在IAP跳转到APP前,将备份域的各时钟失能,这样APP中配置的备份SRAM才会有效。
后续
后续可以测试一下其他外设是否有此问题。最好测试一下同样是挂在同一总线下的外设(GPIO、DMA、备份域时钟全部是在AHB总线下的)。
STM32 之七 备份域(备份寄存器、备份SRAM)详解及数据丢失问题处理相关推荐
- Android VCard联系人备份恢复(导入/导出)详解
原文地址为: Android VCard联系人备份恢复(导入/导出)详解 首先我们简单的看下在Android中联系人的存储结构. 工作环境:android 2.3.3 联系人的主要数据存放在raw_c ...
- STM32 之三 标准外设版USB驱动库详解(架构+文件+函数+使用说明+示例程序)
写在前面 目前,ST的USB驱动有两套,一套是早期的独立版USB驱动,官方培训文档中称为Legacy library:一套为针对其Cube 系列的驱动,根据芯片不同可能有区别,具体见对应芯片的Cube ...
- HMI智能串口屏——在STM32开发板上的实战应用及其详解
HMI智能串口屏--在STM32开发板上的实战应用及其详解 一.HMI智能串口屏使用步骤 二.附录 一.HMI智能串口屏使用步骤 安装USART HMI软件 (一般买的串口屏里面,商家送的资料里面都有 ...
- 建立备份域控服务器,备份域控制器
备份域控制器 10/25/2013 本文内容 上一次修改主题: 2005-11-11 备份域控制器以确保它们的可用性是很重要的.备份域控制器就像备份 Exchange 成员服务器一样.备份域控制器和备 ...
- Linux-6.5下 MariaDB-10基于percona-XtraBackup备份工具的原理及配置详解
理解部分(及原理部分): XtraBackup是percona公司提供的开源工具,以热备Innodb表著称而被广泛采用. XtraBackup对Innodb的备份之所以是热备,无需锁表,是基于Inno ...
- 计算机操作系统的备份和快速恢复,windows操作系统的备份与恢复详解,免去重装系统的烦恼...
大家好,欢迎回到万魔寺,大家都学会windows系统的安装了吗? 今天,我们继续分享系统备份和还原的相关知识. 相信大家都自己上手安装过自己的windows操作系统了,每次下载镜像.安装系统.安装驱动 ...
- STM32利用SPI读写SD卡的程序详解
STM32利用SPI读写SD卡的一些程序详解 关于SD卡的基础知识这里不做过多陈述,如果有对这方面感兴趣的朋友可以直接百度一下,有很多讲SD卡的文章,这里主要是针对SD卡的读写程序实现做一些详细说明. ...
- STM32-串口通信波特率计算以及寄存器的配置详解
串口通信基本原理 处理器与外部设备通信的两种方式 并行通信 传输原理:数据各个位同时传输. 优点:速度快 缺点:占用引脚资源多 串行通信 传输原理:数据按位顺序传输 优点:占用引脚资源少 缺点:速度相 ...
- 《STM32从零开始学习历程》——CAN通讯代码详解
<STM32从零开始学习历程>@EnzoReventon CAN通讯代码详解 相关链接: <STM32从零开始学习历程>--CAN通讯协议物理层 CAN-bus规范 V2.0版 ...
最新文章
- C++对象模型5——类对象的内存布局
- ViSP安装之Windows系统基于VS2019编译器编译获得VISP动态库
- linux putty xshell vi 小键盘无法使用的解决方法
- 《认清C++语言》---谈谈const
- python psycopg2_如何在Python上用“pip”安装psycopg2?
- treeview自动从表中添加标题和列值做目录的方法2
- 瑞典 林雪平大学 机器人视觉方向 博士招生
- CSS 自由缩放 resize属性
- GDAL源码剖析(四)之命令行程序说明一
- matlab中可调节负载,请教MOC3022控制可控硅的电路调节负载功率的问题
- 计算机cims的英语全称是什么,计算机集成制造系统(CIMS),computer integrated manufacturing system,音标,读音,翻译,英文例句,英语词典...
- 算力网络走向智能社会,云计算初心未改(一)
- 【数学建模】regress()函数进行回归分析| 美国人口预测
- 连载 北漂十二年祭 3 --Leo第二次面试,无意中的霸王面
- 怎么把视频变成GIF
- go 并发goroutines,channal
- android:详细解读DialogFragment
- word中参考文献编号添加及更新方法
- 简析BlockingQueue
- prometheus-简介
热门文章
- 全闪存阵列的“五十度黑”
- C++ STL学习之容器set和multiset (补充材料)
- iOS属性传值传递不过去
- php SqlServer 中文汉字乱码
- android 开机启动服务。
- 问题战略[置顶] 十八年开发经验分享(四)问题解决篇(下)
- eclipse rcp应用程序重启
- 【tensorflow】tf-tf.where(condition, x, y, name)
- hdfs集群数据迁移:使用distcp命令
- ubuntu安装pip包管理器