概 述
在MCU的使用中,經常遇到需要存儲參數或掉電保持數據等功能。其中,Flash和EEPROM是常見的非易失性存儲器,都可以做到設備掉電重啟后,數據還會保留。但二者有明顯的區別:EEPROM可以被編程和電擦除,而且大多數的EEPROM可以被編程和電擦除,大多數串行EEPROM允許逐字節程序或擦除操作。與EEPROM相比,閃存具有更高的密度,這允許在芯片上實現更大的內存陣列(扇區)。通過對每個單元施加時間控制的電壓來執行閃存擦除和寫入周期。典型的Flash寫時間是50μs/8位字;然而,EEPROM通常需要5到10 ms。EEPROM不需要進行頁面(扇區)擦除操作,可以擦除一個需要指定時間的特定字節。與EEPROM相比,Flash具有更高的密度和更低的價格。
先楫產品可以外接大容量Flash芯片,支持可達256Mbyte程序或數據存儲;部分產品如HPM6754、HPM6364、HPM6284內置4Mbyte Flash,HPM53XX系列全系支持1Mbyte Flash。在使用Flash模擬EEPROM時,最重要的挑戰是滿足Flash程序/擦除持久性和數據保留方面的可靠性目標。
其次,在應用程序的控制下,需要滿足更新和讀取數據的實時應用要求。請注意,在Flash擦寫期間,它不能執行Flash應用程序,因為在此時間內不能執行在Flash中的程序,通常程序是將Flash擦寫程序拷貝到RAM中執行。先楫半導體為了方便客戶程序應用,已經將Flash驅動程序集成到ROM中,減少了系統對RAM的需求,用戶使用時更加靈活方便。
由于Flash的塊擦除要求,必須完全為模擬的EEPROM保留至少一個Flash扇區。例如,一個4K x 8bit大小的Flash扇區可以分為16頁,每個頁的大小為256 x 8bit。這使得每個頁面相當于一個256 x 8字節的EEPROM。要保存的數據首先寫入RAM中的緩沖區中,每個部分RAM可以模擬EEPROM的存儲的數據。
如何實現?
根據Flash扇區和模擬的EEPROM的大小,劃分相應的Flash和RAM空間。
功能:
? 讀取片內或片外flash信息。
? 批量讀取flash中數據到RAM緩存中。
? 用戶可以自由讀寫RAM緩存中數據。
? 用戶可以將RAM緩存中數據寫入flash。
? 用戶可以根據自己的需要定制存儲空間大小和存儲地址。
由于先楫半導體MCU已經集成了Flash驅動,用戶可以不再需要把精力放到繁瑣的底層Flash驅動部分。
為了實現此功能,需要8個函數來進行編程、讀取和擦除,3個宏定義確定存儲空間和位置。
/* Sector size */
#defineSECTOR_SIZE (uint32_t) (0x1000)
/* Sectors 0 and 1 base and end addresses */
#defineFlash_base 0x80000000L
#defineSECTOR1_BASE_ADDRESS (Flash_base+0x3FE000)
#defineSECTOR1_END_ADDRESS (SECTOR1_BASE_ADDRESS+SECTOR_SIZE*2-1)
其中,SECTOR_SIZE定義了flash扇區大小,單位是byte。若不確定flash扇區大小可以在Initial_EEProm函數中獲取flash信息。Flash_base定義flash起始地址,具體可以參考user guider中系統內存映射 System Memory Map地址。SECTOR1_BASE_ADDRESS和SECTOR1_END_ADDRESS為數據存放起始地址,SECTOR1_BASE_ADDRESS必須是特定扇區起始地址。
ATTR_PLACE_AT_WITH_ALIGNMENT(".ahb_sram",8) uint8_tEEPROM_data[SECTOR1_END_ADDRESS-SECTOR1_BASE_ADDRESS+1];
Flash模擬EEPROM時需在RAM中開辟緩存用于常態數據讀寫,開辟數據時應注意RAM區數據應放到ahb_sram或noncacheable區域。
ifdefined(FLASH_XIP) &&FLASH_XIP
ATTR_RAMFUNC hpm_stat_tInitial_EEProm(void)
#else
hpm_stat_tInitial_EEProm(void)
#endif
{
xpi_nor_config_option_toption;
option.header.U= BOARD_APP_XPI_NOR_CFG_OPT_HDR;
option.option0.U= BOARD_APP_XPI_NOR_CFG_OPT_OPT0;
option.option1.U= BOARD_APP_XPI_NOR_CFG_OPT_OPT1;
hpm_stat_tstatus= rom_xpi_nor_auto_config(HPM_XPI0, &s_xpi_nor_config, &option);
if(status!= status_success) {
returnstatus;
}
rom_xpi_nor_get_property(HPM_XPI0, &s_xpi_nor_config, xpi_nor_property_total_size,
&flash_size);
rom_xpi_nor_get_property(HPM_XPI0, &s_xpi_nor_config, xpi_nor_property_sector_size,
§or_size);
rom_xpi_nor_get_property(HPM_XPI0, &s_xpi_nor_config, xpi_nor_property_page_size, &page_size);
printf("Flash Size:%dMBytes Flash Sector Size:%dKBytes Flash Page Size:%dBytes ",
flash_size/ 1024U/ 1024U, sector_size/ 1024U, page_size);
EEProm_Flush();
}/* End Initial_EEProm */
通過調用rom_xpi_nor_auto_config()、rom_xpi_nor_get_property()獲取flash信息。
/*******************************************************************************
* Routine: EEPromFlush
* Purpose: Refresh data from flash to buffer.
*******************************************************************************/
inlinevoidEEProm_Flush(void)
{
memcpy((void*)EEPROM_data,(constvoid*)SECTOR1_BASE_ADDRESS,(SECTOR1_END_ADDRESS-SECTOR1_BASE_ADDRESS));
}/* End EEProm_Flush */
從flash中讀取數據無需單獨調用API函數,直接尋址讀取效率更高,文中通過memcpy()函數直接從flash中讀取數據到RAM緩存中,后面讀寫參數直接讀寫RAM緩存即可。
如果需要將參數寫入flash中,需將整塊flash擦寫,由于數據已經存在RAM緩存,不會存在flash擦寫時數據丟失的問題。
/*******************************************************************************
* Routine: writeEEProm_withflush
* Purpose: Writes variable to EEPROM and flush flash later.
* Input : none
* Output: None.
* Return: Returns 0
*******************************************************************************/
#ifdefined(FLASH_XIP) &&FLASH_XIP
ATTR_RAMFUNC hpm_stat_twriteEEProm_withflush(uint16_tindex, uint8_t*data, uint16_tsize)
#else
hpm_stat_twriteEEProm_withflush(uint16_tindex, uint8_t*data, uint16_tsize)
#endif
{
hpm_stat_tstatus;
if(flash_size==0) returnstatus_fail;
memcpy((void*)&EEPROM_data[index],(constvoid*)data,size);
status= rom_xpi_nor_erase(HPM_XPI0, xpi_xfer_channel_auto, &s_xpi_nor_config,
SECTOR1_BASE_ADDRESS-Flash_base, SECTOR1_END_ADDRESS-SECTOR1_BASE_ADDRESS);
if(status!= status_success) {
returnstatus;
}
status= rom_xpi_nor_program(HPM_XPI0, xpi_xfer_channel_auto, &s_xpi_nor_config,
(constuint32_t*)EEPROM_data, SECTOR1_BASE_ADDRESS-Flash_base, SECTOR1_END_ADDRESS-SECTOR1_BASE_ADDRESS);
if(status!= status_success) {
returnstatus;
}
}
考慮到flash擦寫期間不能讀取flash,flash擦寫函數需放置在RAM執行的程序存儲空間。先楫SDK中已經定義好了ram運行區域,并在HPM_COMMON.H文件中將函數和數字放置屬性重新封裝,通過ATTR_RAMFUNC等效定義__attribute__((section(“.fast”)))。為確保擦寫flash期間不會被中斷打斷從而調用其他flash中的程序,需在運行中關閉中斷。
//disable all interrupt before programming flash
CSR_reg= disable_global_irq(CSR_MSTATUS_MIE_MASK);
disable_global_irq(CSR_MSTATUS_SIE_MASK);
disable_global_irq(CSR_MSTATUS_UIE_MASK);
writeEEProm_withflush(0,(uint8_t*)s_write_buf,0x1000);//update eeprom with flash
//restore interrupt
restore_global_irq(CSR_reg);
小 結
本文首先介紹了基于HPM6000系列芯片如何使用Flash模擬EEPROM存儲參數。由于先楫SDK中已經提供了強大的驅動庫,用戶可以方便地通過Flash存儲數據,降低成本和提高使用靈活性。
審核編輯:劉清
-
FlaSh
+關注
關注
10文章
1633瀏覽量
147940 -
EEPROM
+關注
關注
9文章
1019瀏覽量
81560 -
非易失性存儲器
+關注
關注
0文章
107瀏覽量
23438 -
SRAM存儲器
+關注
關注
0文章
88瀏覽量
13290 -
MCU控制器
+關注
關注
0文章
27瀏覽量
6885
原文標題:經驗分享 | 如何使用Flash模擬EEPROM存儲參數
文章出處:【微信號:HPMicro,微信公眾號:先楫半導體HPMicro】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論