2013-12-18 6 views
9

Есть два способа эмуляции EEPROM на STM32F4:Как использовать резервный SRAM в EEPROM в STM32F4

  1. На чипе 4 кбайта резервного SRAM
  2. На чипе флэш, со специфическим программным алгоритмом

Второй вариант описан здесь: AN3969.

Но Google, к сожалению, не в состоянии предоставить информацию о том, как использовать первый вариант - с помощью 4Kb резервного SRAM как EEPROM ..

Может кто-нибудь помочь по этой теме?

+0

У вас есть библиотека stm32 f4 series или вам нужно самостоятельно изменить периферийные регистры? –

ответ

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); 
    

и вы можете писать/читать ДАННЫЕ для sram (эти коды из кодов BKP_Domain в STM32F4xx_DSP_StdPeriph_Lib) (в моем 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. Согласно техническому паспорту:

Резервная SRAM с 4-Кбайт - это 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 таблицы Я согласен, что это ISN» t ясно, как на самом деле использовать резервный 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). 

на стр 71 таблицы и р65 в справочном руководстве

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

и странице 73 datatasheet и P67 из Справочное руководство

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

В Справочном руководстве приведена информация по 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

Мне нужно было перейти от основной программы к загрузчику по запросу пользователя. Итак, я поместил некоторое «магическое число» в BKPSRAM в основной программе, перезагрузился программным сбросом CPU. Начальный загрузчик всегда начинается первым. Он проверяет «магическое число», если он присутствует, он выполняет, в противном случае начинается основная программа

при использовании HAL это то, как перейти к загрузчику:

__HAL_RCC_PWR_CLK_ENABLE(); 

HAL_PWR_EnableBkUpAccess(); 

__BKPSRAM_CLK_ENABLE(); 

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

HAL_NVIC_SystemReset(); 

внутри загрузчика читать магическое число это достаточно, чтобы включить только синхронизирующие часы резервного копирования (загрузчик использует StdPeriphDriver).

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); 

extRequest = *(__IO uint8_t *)0x40024000; 

if(extRequest == 42) 
    //run bootloader 

процессор 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; 

В Init:

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