2013-12-18 142 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; 
}