2013-12-18 131 views
9

上有STM32F4模拟EEPROM的方法有两种:如何使用备份SRAM作为EEPROM中STM32F4

  1. 片4 KB的备份SRAM
  2. 片上闪存,具有特定的软件算法

第二个选项在这里描述:AN3969。

但谷歌,遗憾的是,一直未能提供有关如何使用第一个选项信息 - 使用备份SRAM的4K位的EEPROM ..

任何人都可以对主题的帮助?

+0

你有stm32 f4系列库吗?还是你必须自己修改外设寄存器? –

回答

10

必须做这些:

  1. 启用PWR时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 
    
  2. 启用访问备份域

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

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); 
    
  4. 启用备份SRAM低功耗稳压器,以保持它在VBAT模式内容

    PWR_BackupRegulatorCmd(ENABLE); 
    

,你可以写/读DATAS到sram(这些代码来自STM32F4xx_DSP_StdPeriph_Lib中的BKP_Domain代码)(在我的MCU stm32f417 BKPSRAM_BASE = 0x40024000)

// 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) 
    {} 

您可以在STM32F4xx_DSP_StdPeriph_Lib找到这些功能。

1

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

4 KB备份SRAM是一个类似于EEPROM的区域。

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

例如,当微控制器断电时,需要一个超级电容来维护备份寄存器的内容。

此外,根据该文件:

复位后,备份域(...备份SRAM)保护,以防止不必要的可能写访问。要启用对备份域的访问,请按照以下步骤操作:

它为您提供有关如何通过直接写入某个外设寄存器来访问备份域的说明。如果你有机会到STM32F4xx库,你可以调用像这样(注意:我使用的STM32F2xx库):

PWR_BackupAccessCmd(ENABLE); 

注:还有更多的是比简单地调用上面的函数,如启用备份SRAM接口时钟。请参考STM32F4系列文档。

在库源文件中嵌入了很多非常有价值的文档,如果它是可用的,应该阅读。

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

0x40024000 - 0x40024FFF

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

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

通过参考手册STM32F4和stm32f405xx/stm32f407xx数据表看完后我同意,它不是”不清楚如何实际使用备份SRAM(或它所在的位置)。这是我发现的。只要您拥有电池电量,RTC寄存器和备份SRAM都包含一定数量的存储空间。RTC包含20个寄存器(80字节),备份SRAM(它是AHB1上自己的外设,位于寄存器地址区域内)包含0x1000(4096字节)。默认情况下都不启用。

在DM00037051(stm32f405xx/stm32f407xx数据表,P29)

The 4-Kbyte backup SRAM is an EEPROM-like memory area. It can be used to store 
data which need to be retained in VBAT and standby mode. This memory area is 
disabled by default to minimize power consumption (see Section 2.2.19: 
Low-power modes). It can be enabled by software. 

The backup registers are 32-bit registers used to store 80 bytes of user 
application data when VDD power is not present. Backup registers are not reset 
by a system, a power reset, or when the device wakes up from the Standby mode 
(see Section 2.2.19: Low-power modes). 

参考手册

AHB1 | 0x4002 4000 - 0x4002 4FFF | BKPSRAM 

和datatasheet的73页和P67的的数据表和p65的第71页上参考手册

APB1 | 0x4000 2800 - 0x4000 2BFF | RTC & BKP Registers 

参考手册的第118-119页包含e禁用备份SRAM和RTC寄存器。

注意:如果您已经在备份域中使用RTC,并且只需要存储< = 80字节,那么最好使用RTC备份寄存器,因为启用备份SRAM基本上会使电流消耗增加一倍(请参阅表格25在stm32f405/7数据表中)。

这里有我的写入和读取进行备份SRAM功能和备份RTC寄存器

int8_t write_to_backup_sram(uint8_t *data, uint16_t bytes, uint16_t offset) { 
    const uint16_t backup_size = 0x1000; 
    uint8_t* base_addr = (uint8_t *) BKPSRAM_BASE; 
    uint16_t i; 
    if(bytes + offset >= backup_size) { 
    /* ERROR : the last byte is outside the backup SRAM region */ 
    return -1; 
    } 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); 
    /* disable backup domain write protection */ 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // set RCC->APB1ENR.pwren 
    PWR_BackupAccessCmd(ENABLE);       // set PWR->CR.dbp = 1; 
    /** enable the backup regulator (used to maintain the backup SRAM content in 
    * standby and Vbat modes). NOTE : this bit is not reset when the device 
    * wakes up from standby, system reset or power reset. You can check that 
    * the backup regulator is ready on PWR->CSR.brr, see rm p144 */ 
    PWR_BackupRegulatorCmd(ENABLE);  // set PWR->CSR.bre = 1; 
    for(i = 0; i < bytes; i++) { 
    *(base_addr + offset + i) = *(data + i); 
    } 
    PWR_BackupAccessCmd(DISABLE);      // reset PWR->CR.dbp = 0; 
    return 0; 
} 

int8_t read_from_backup_sram(uint8_t *data, uint16_t bytes, uint16_t offset) { 
    const uint16_t backup_size = 0x1000; 
    uint8_t* base_addr = (uint8_t *) BKPSRAM_BASE; 
    uint16_t i; 
    if(bytes + offset >= backup_size) { 
    /* ERROR : the last byte is outside the backup SRAM region */ 
    return -1; 
    } 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); 
    for(i = 0; i < bytes; i++) { 
    *(data + i) = *(base_addr + offset + i); 
    } 
    return 0; 
} 

int8_t write_to_backup_rtc(uint32_t *data, uint16_t bytes, uint16_t offset) { 
    const uint16_t backup_size = 80; 
    volatile uint32_t* base_addr = &(RTC->BKP0R); 
    uint16_t i; 
    if(bytes + offset >= backup_size) { 
    /* ERROR : the last byte is outside the backup SRAM region */ 
    return -1; 
    } else if(offset % 4 || bytes % 4) { 
    /* ERROR: data start or num bytes are not word aligned */ 
    return -2; 
    } else { 
    bytes >>= 2;  /* divide by 4 because writing words */ 
    } 
    /* disable backup domain write protection */ 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // set RCC->APB1ENR.pwren 
    PWR_BackupAccessCmd(ENABLE);       // set PWR->CR.dbp = 1; 
    for(i = 0; i < bytes; i++) { 
    *(base_addr + offset + i) = *(data + i); 
    } 
    PWR_BackupAccessCmd(DISABLE);      // reset PWR->CR.dbp = 0; 
    // consider also disabling the power peripherial? 
    return 0; 
} 

int8_t read_from_backup_rtc(uint32_t *data, uint16_t bytes, uint16_t offset) { 
    const uint16_t backup_size = 80; 
    volatile uint32_t* base_addr = &(RTC->BKP0R); 
    uint16_t i; 
    if(bytes + offset >= backup_size) { 
    /* ERROR : the last byte is outside the backup SRAM region */ 
    return -1; 
    } else if(offset % 4 || bytes % 4) { 
    /* ERROR: data start or num bytes are not word aligned */ 
    return -2; 
    } else { 
    bytes >>= 2;  /* divide by 4 because writing words */ 
    } 
    /* read should be 32 bit aligned */ 
    for(i = 0; i < bytes; i++) { 
    *(data + i) = *(base_addr + offset + i); 
    } 
    return 0; 
} 
2

我不得不根据用户请求从主程序跳转到bootloader。 所以我在主程序中加入了一些'神奇数字'到BKPSRAM中,做了CPU软复位。引导加载程序总是首先启动。 它检查“幻数”,如果它存在,它执行,否则启动主程序

使用HAL时,这是多么跳转到引导程序:

__HAL_RCC_PWR_CLK_ENABLE(); 

HAL_PWR_EnableBkUpAccess(); 

__BKPSRAM_CLK_ENABLE(); 

*(__IO uint8_t *)0x40024000 = 42;//magic number 

HAL_NVIC_SystemReset(); 

内举程序读神奇的数字是足以仅启用备份sram时钟(引导加载程序使用StdPeriphDriver)。

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); 

extRequest = *(__IO uint8_t *)0x40024000; 

if(extRequest == 42) 
    //run bootloader 

CPU是STM32F407

0

可用例如 在报头:

//------------------------------------ 
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; 
     } 
} 
//------------------------------------------------- 
+0

这个问题在5年前回答 –

0

这里是HAL库的例子使用的备份SRAM。

#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; 
}