如何在STM32F4中使用备份SRAM作为EEPROM

如何在STM32F4中使用备份SRAM作为EEPROM,stm32,eeprom,stm32f4discovery,Stm32,Eeprom,Stm32f4discovery,在STM32F4上模拟EEPROM有两种方法: 片上4千字节备份SRAM 带特定软件算法的片上闪存 这里描述了第二个选项:AN3969 但不幸的是,谷歌未能提供关于如何使用第一个选项的信息——使用4Kb的备份SRAM作为EEPROM 有人能帮忙吗?我目前正在使用的是STM32F2xx微控制器。根据数据表: 4-Kbyte备份SRAM是一个类似EEPROM的区域 要保留RTC备份寄存器的内容…当VDD关闭时,VBAT引脚可以连接到由电池或其他电源提供的可选备用电压 例如,在微控制器断电时,需要超级

在STM32F4上模拟EEPROM有两种方法:

  • 片上4千字节备份SRAM
  • 带特定软件算法的片上闪存
  • 这里描述了第二个选项:AN3969

    但不幸的是,谷歌未能提供关于如何使用第一个选项的信息——使用4Kb的备份SRAM作为EEPROM


    有人能帮忙吗?

    我目前正在使用的是STM32F2xx微控制器。根据数据表:

    4-Kbyte备份SRAM是一个类似EEPROM的区域

    要保留RTC备份寄存器的内容…当VDD关闭时,VBAT引脚可以连接到由电池或其他电源提供的可选备用电压

    例如,在微控制器断电时,需要超级映射来维护备份寄存器的内容

    此外,根据该文件:

    重置后,备份域(…备份SRAM)将受到保护,以防可能出现不必要的写入访问。要启用对备份域的访问,请按以下步骤进行

    它为您提供了有关如何通过直接写入特定外围寄存器来访问备份域的说明。如果您有权访问STM32F4xx库,则可以调用如下内容(注意:我使用的是STM32F2xx库):

    注意:除了简单地调用上述函数(如启用备份SRAM接口时钟)之外,还有更多的功能。请参阅STM32F4系列文档

    库源代码中嵌入了大量的文档,这些文档非常宝贵,如果有,请阅读

    在STM32F2系列微控制器上,SRAM位于以下存储器地址范围:

    0x40024000-0x40024FFF

    并且可以写入位置的某个位置,例如,如下所示:

    #define VAR_LOC ((volatile uint8_t *)(0x40024000))
    volatile uint8_t *pVar = VAR_LOC;
    *pVar = 5;
    

    在阅读了stm32f4参考手册和stm32f405xx/stm32f407xx数据表后,我同意不清楚如何实际使用备份sram(或其位置)。这是我发现的。RTC寄存器和备用SRAM都包含一定量的存储空间,只要您有电池电源,就可以保持这些空间。RTC包含20个寄存器(80字节),而备份sram(AHB1上自己的外围设备,位于寄存器地址区域内)包含0x1000(4096字节)。默认情况下,两者都不启用

    在DM00037051(stm32f405xx/stm32f407xx数据表,第29页)中:

    数据表第71页和参考手册第65页

    AHB1   |   0x4002 4000 - 0x4002 4FFF   |   BKPSRAM
    
    APB1   |   0x4000 2800 - 0x4000 2BFF   |   RTC & BKP Registers
    
    以及数据表第73页和参考手册第p67页

    AHB1   |   0x4002 4000 - 0x4002 4FFF   |   BKPSRAM
    
    APB1   |   0x4000 2800 - 0x4000 2BFF   |   RTC & BKP Registers
    
    参考手册第118-119页包含有关启用备用SRAM和RTC寄存器的信息

    注意:如果您已经在备份域中使用RTC,并且只需要存储=备份大小){ /*错误:最后一个字节在备份SRAM区域之外*/ 返回-1; } RCC_AHB1PeriphLockCmd(RCC_AHB1Periph_BKPRAM,启用); /*禁用备份域写保护*/ RCC_APB1PeriphLockCmd(RCC_APB1Periph_压水堆,启用);//设置RCC->APB1ENR.pwren PWR_BackupAccessCmd(启用);//设置PWR->CR.dbp=1; /**启用备份调节器(用于在中维护备份SRAM内容 *待机和Vbat模式)。注意:当设备启动时,此位不会重置 *从待机、系统重置或电源重置中唤醒。你可以查一下 *备用调节器已在PWR->CSR.brr上准备就绪,请参见rm p144*/ PWR_备份调节器cmd(启用);//设置PWR->CSR.bre=1; 对于(i=0;iCR.dbp=0; 返回0; } 从备份sram读取的int8字节(uint8字节*数据,uint16字节,uint16字节偏移量){ const uint16\u t backup\u size=0x1000; uint8_t*基地址=(uint8_t*)BKPSRAM_基; uint16_t i; 如果(字节+偏移量>=备份大小){ /*错误:最后一个字节在备份SRAM区域之外*/ 返回-1; } RCC_AHB1PeriphLockCmd(RCC_AHB1Periph_BKPRAM,启用); 对于(i=0;iBKP0R); uint16_t i; 如果(字节+偏移量>=备份大小){ /*错误:最后一个字节在备份SRAM区域之外*/ 返回-1; }else if(偏移量%4 | |字节%4){ /*错误:数据开始或num字节未对齐*/ 返回-2; }否则{ 字节>>=2;/*除以4,因为写入单词*/ } /*禁用备份域写保护*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,启用);//设置RCC->APB1ENR.pwren PWR_BackupAccessCmd(ENABLE);//设置PWR->CR.dbp=1; 对于(i=0;iCR.dbp=0; /还考虑禁用电源外围设备吗? 返回0; } 从备份rtc读取的int8(uint32数据、uint16字节、uint16偏移量){ const uint16\u t backup\u size=80; 易失性uint32*base\u addr=&(RTC->BKP0R); uint16_t i; 如果(字节+偏移量>=备份大小){ /*错误:最后一个字节在备份SRAM区域之外*/ 返回-1; }else if(偏移量%4 | |字节%4){ /*错误:数据开始或num字节未对齐*/ 返回-2; }否则{ 字节>>=2;/*除以4,因为写入单词*/ } /*读取应为32位对齐*/ 对于(i=0;i必须执行以下操作:

  • 启用PWR时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    
  • 启用对备份域的访问

    PWR_BackupAccessCmd(ENABLE);
    
  • 启用备份SRAM时钟

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
    
  • 启用备用SRAM低功耗调节器以将其内容保留在VBAT中
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
    
    PWR_BackupRegulatorCmd(ENABLE);
    
       // Write to Backup SRAM with 32-Bit Data 
       for (i = 0x0; i < 0x100; i += 4) {
           *(__IO uint32_t *) (BKPSRAM_BASE + i) = i;
       }
    
       // Check the written Data 
       for (i = 0x0; i < 0x100; i += 4) {
              if ((*(__IO uint32_t *) (BKPSRAM_BASE + i)) != i){
                  errorindex++;
              }
       }
    
        // Wait until the Backup SRAM low power Regulator is ready
        while(PWR_GetFlagStatus(PWR_FLAG_BRR) == RESET)
        {}
    
    __HAL_RCC_PWR_CLK_ENABLE();
    
    HAL_PWR_EnableBkUpAccess();
    
    __BKPSRAM_CLK_ENABLE();
    
    *(__IO uint8_t *)0x40024000 = 42;//magic number
    
    HAL_NVIC_SystemReset();
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
    
    extRequest = *(__IO uint8_t *)0x40024000;
    
    if(extRequest == 42)
        //run bootloader
    
    //------------------------------------
    typedef struct
    {
        uint32_t    isDefault;          //must by 0x12345678
        uint32_t    LastTestNumber;     
        uint32_t    LastUserNumber;     
        uint32_t    LastModeTest;       
        uint32_t    calibv;
        uint32_t    calibc;
        uint32_t    WorkTime;           
        int32_t     RTCCalib;
        uint32_t    LCDContrast;
    
    } sBKPSRAM;
    extern sBKPSRAM *BKPSRAM;//  = (sSDRAM *)SDRAM_BANK_ADDR;
    //------------------------------------
    
    sBKPSRAM    *BKPSRAM    = (sBKPSRAM *)BKPSRAM_BASE;
    
    void main(void)
    {
    (....)
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
      PWR_BackupAccessCmd(ENABLE);
      PWR_BackupRegulatorCmd(ENABLE);
      ifDefault();
    (....)
    }
    
    //-------------------------------------------------
    void ifDefault(void)
    {
        if (BKPSRAM->LastModeTest!=0x12345678)
            {
                printf("BKPSRAM to default\r\n");
                memset(BKPSRAM,0,sizeof(sBKPSRAM));
                BKPSRAM->calibv         =66920;
                BKPSRAM->calibc         =79230;
                BKPSRAM->RTCCalib       =1;
                BKPSRAM->LCDContrast    =2;         
                BKPSRAM->LastModeTest   =0x12345678;
            }
    }
    //-------------------------------------------------
    
    #define  WRITE_READ_ADDR  0x01 //offset value.you can change according to your application
    uint32_t write_arr = 0xA5A5A5A6;
    uint32_t read_arr;
    
    int main()
    {
       enable_backup_sram();
       writeBkpSram(write_arr);
       while(1)
       {
          read_arr = readBkpSram();
       }
    }
    void enable_backup_sram(void)
    {
        /*DBP : Enable access to Backup domain */
        HAL_PWR_EnableBkUpAccess();
        /*PWREN : Enable backup domain access  */
        __HAL_RCC_PWR_CLK_ENABLE();
        /*BRE : Enable backup regulator
          BRR : Wait for backup regulator to stabilize */
        HAL_PWREx_EnableBkUpReg();
       /*DBP : Disable access to Backup domain */
        HAL_PWR_DisableBkUpAccess();
    }
    
    void writeBkpSram(uint32_t l_data)
    {
       /* Enable clock to BKPSRAM */
      __HAL_RCC_BKPSRAM_CLK_ENABLE();
      /* Pointer write on specific location of backup SRAM */
      (uint32_t *) (BKPSRAM_BASE + WRITE_READ_ADDR) = l_data;
     /* Disable clock to BKPSRAM */
     __HAL_RCC_BKPSRAM_CLK_DISABLE();
    }
    
    uint32_t readBkpSram(void)
    {
       uint32_t i_retval;
    
      /* Enable clock to BKPSRAM */
      __HAL_RCC_BKPSRAM_CLK_ENABLE();
      /* Pointer write from specific location of backup SRAM */
      i_retval =  *(uint32_t*) (BKPSRAM_BASE + WRITE_READ_ADDR);
      /* Disable clock to BKPSRAM */
      __HAL_RCC_BKPSRAM_CLK_DISABLE();
      return i_retval;
    }
    
    #define BKP_RAM (*(__IO uint32_t *) (D3_BKPSRAM_BASE)) //Start address: 0x38800000
    
    Main() {
    
    __HAL_RCC_BKPRAM_CLK_ENABLE();
    
    HAL_PWREx_EnableBkUpReg();
    
    BKP_RAM = 0xA5AA5A55;
    
    }
    
    SCB->CACR |= 1<<2;