欢迎访问 生活随笔!

ag凯发k8国际

当前位置: ag凯发k8国际 > 编程资源 > 编程问答 >内容正文

编程问答

stm32 之七 备份域(备份寄存器、备份sram)详解及数据丢失问题处理 -ag凯发k8国际

发布时间:2024/10/14 编程问答 19 豆豆
ag凯发k8国际 收集整理的这篇文章主要介绍了 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中的数据丢失!检查在硬件上并没有出现任何问题,于是从软件一步步分析如下:

  • 产品( 使用stm32f407vg )中实现了iap、app在线升级,备份域在这两部程序中均有使用(两部分程序中均对备份域进行了初始化)。
  • 在由iap跳转到app后,发现在app中初始化的备份sram中原有数据全部丢失( 准确的说应该是时钟不起作用,导致数据全是 0,看似数据丢失
  • 分析原因,stm32芯片在上电后默认以内部低速时钟源(hsi运行),如果用户配置了使用外部时钟源,则再配置外部时钟源,然后将时钟切换为外部。程序在app中配置时钟前是正常的,一旦时钟源出现切换则导致备份域再次初始化之后就无效了!感觉应该是 备份域的各种初始化必须在时钟初始化之后再进行配置才可以,颠倒顺序将导致备份域时钟初始化后不可用! 但是,其他外设(例如gpio,同是挂在ahp总线上)却不受以上限制,比较奇怪!
  •   在iap跳转到app前,将备份域的各时钟失能,这样app中配置的备份sram才会有效。

    后续可以测试一下其他外设是否有此问题。最好测试一下同样是挂在同一总线下的外设(gpio、dma、备份域时钟全部是在ahb总线下的)。

    总结

    以上是ag凯发k8国际为你收集整理的stm32 之七 备份域(备份寄存器、备份sram)详解及数据丢失问题处理的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得ag凯发k8国际网站内容还不错,欢迎将ag凯发k8国际推荐给好友。

    网站地图