STM32F4でEEPROMをエミュレートするには、2つの方法があります。
2番目のオプションはここで説明されています:AN3969。
しかし、残念ながらグーグルは最初のオプションの使用方法に関する情報を提供できませんでした-4KbのバックアップSRAMをEEPROMとして使用しますか?.
誰でもこのトピックについて手伝ってくれる?
これらを行う必要があります:
PWRクロックを有効にする
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
バックアップドメインへのアクセスを有効にする
PWR_BackupAccessCmd(ENABLE);
バックアップSRAMクロックを有効にする
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
バックアップSRAM低電力レギュレータを有効にして、VBATモードでコンテンツを保持します
PWR_BackupRegulatorCmd(ENABLE);
また、データを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にあります。
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).
データシートの71ページおよびリファレンスマニュアルのp65
AHB1 | 0x4002 4000 - 0x4002 4FFF | BKPSRAM
およびデータシートの73ページとリファレンスマニュアルのp67
APB1 | 0x4000 2800 - 0x4000 2BFF | RTC & BKP Registers
リファレンスマニュアルの118〜119ページには、バックアップSRAMおよびRTCレジスタの有効化に関する情報が含まれています。
注:バックアップドメインですでにRTCを使用しており、80バイト以下の格納のみが必要な場合は、RTC backupを使用することをお勧めしますバックアップSRAMを有効にすると、消費電流が基本的に2倍になるためです(stm32f405/7データシートの表25を参照)。
バックアップ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;
}
ユーザーの要求により、メインプログラムからブートローダーにジャンプする必要がありました。そこで、メインプログラムの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です
バックアップSRAMを使用するHALライブラリの例を次に示します。
#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;
}
現在、STM32F2xxマイクロコントローラーを使用しています。データシートによると:
4Kバイトのバックアップ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;
STM32H7がバックアップSRAMにアクセスするためのHAL構成:
#define BKP_RAM (*(__IO uint32_t *) (D3_BKPSRAM_BASE)) //Start address: 0x38800000
Main() {
__HAL_RCC_BKPRAM_CLK_ENABLE();
HAL_PWREx_EnableBkUpReg();
BKP_RAM = 0xA5AA5A55;
}
さらに、systemInit()に以下の行を追加して、バックアップSRAMへのライトスルーアクセスを有効にする必要があります。
SCB->CACR |= 1<<2;
ヘッダーの使用可能な例:
//------------------------------------
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;
}
}
//-------------------------------------------------