《APM32芯得》系列內(nèi)容為用戶使用APM32系列產(chǎn)品的經(jīng)驗總結(jié),均轉(zhuǎn)載自21ic論壇極海半導(dǎo)體專區(qū),全文未作任何修改,未經(jīng)原文作者授權(quán)禁止轉(zhuǎn)載。
1. Flash與EEPROM簡介
1.1 Flash簡介
Flash,又叫閃存。根據(jù)存儲單元電路的不同,分為NAND Flash和NOR Flash兩種。Nor Flash由于地址線和數(shù)據(jù)線是分開的,可以按字節(jié)讀寫數(shù)據(jù)。這種特性可以用來存儲和運行代碼,MCU內(nèi)部的Flash就是一種NOR Flash。
但是無論是哪種Flash,他們寫之前必須先進行擦除操作(因為只能將數(shù)據(jù)由1寫為0)。
1.2 EEPROM簡介
EEPROM,Electrically Erasable Programmable Read Only Memory,即電可擦除可編程只讀存儲器,也是一種非易失性存儲區(qū)。EEPROM也是可以按字節(jié)讀寫數(shù)據(jù)的,但是寫入之前不需要先擦除數(shù)據(jù)。
1.3 Flash與EEPROM對比
Flash 與 EEPROM都屬于非易失性存儲器,他們都可以掉電保存數(shù)據(jù)。但他們也有很多的區(qū)別,下表列出了Flash與EEPROM的主要區(qū)別:
注:這里對比的Flash是MCU內(nèi)部的Flash
其實,在Linux的設(shè)備驅(qū)動歸類中,F(xiàn)lash其實是歸類到塊設(shè)備的,因為它的最小操作單元是扇區(qū)/塊,而EEPROM則是一種字符設(shè)備,最小操作單元是字節(jié)。
1.4 Flash模擬EEPROM的優(yōu)勢
節(jié)約成本,可減少EEPROM芯片的使用
讀寫速率快,MCU內(nèi)部的Flash讀寫速率要遠遠高于EEPROM
抗干擾能力強,MCU內(nèi)部的Flash沒有使用I2C、SPI這類通訊總線,不存在這類總線被干擾的問題。
2. Flash模擬EEPROM原理
在前面的對比,我們可以了解到,F(xiàn)lash與EEPROM最大的區(qū)別就是:
Flash寫之前需要擦除
Flash與EEPROM一次操作的數(shù)據(jù)大小不同。雖然MCU內(nèi)部的Flash和EEPROM一樣,可以實現(xiàn)按字節(jié)的讀寫,但是在寫入的時候,是必須要先按扇區(qū)擦除的,這里也可以說相當(dāng)于是一次操作的數(shù)據(jù)大小不同。
那么,我們Flash模擬EEPROM主要是模擬實現(xiàn)什么呢?主要實現(xiàn)的關(guān)鍵點有:
無需用戶擦除即可按字節(jié)讀寫(擦除操作封裝在函數(shù)內(nèi)部)
擦除數(shù)據(jù)時不能改變原來已經(jīng)存儲的數(shù)據(jù)(讀改寫策略)
盡量減少Flash擦除次數(shù),延長Flash壽命(擦除之前先判斷是否已經(jīng)是擦除狀態(tài))
具體如何實現(xiàn)?
讀操作
MCU內(nèi)部的Flash讀操作很簡單,直接像內(nèi)存一樣讀即可。例如讀0x08000000地址處的數(shù)據(jù):
*(uint32_t *)0x08000000;
把0x08000000強制轉(zhuǎn)換為一個地址(指針),然后再解引用即可。
寫操作
由于Flash寫之前,都必須先要按照扇區(qū)進行擦除,所以會麻煩一點。而且,擦除數(shù)據(jù)的時候,我們不能把原有的數(shù)據(jù)都給擦了,所以可以使用讀改寫的策略。
寫數(shù)據(jù)之前,先在RAM中開辟一個與扇區(qū)相同大小的緩沖區(qū)。然后把要寫的扇區(qū)數(shù)據(jù)讀到緩存中,然后在緩存中改寫數(shù)據(jù)。最后再擦除扇區(qū)(會進行判斷,如果已經(jīng)是擦除狀態(tài),則無需再次擦除),再把數(shù)據(jù)寫到扇區(qū)。
3. APM32F4系列Flash模擬EEPROM難點
3.1 APM32F4 Flash存儲器結(jié)構(gòu)
我們先了解下APM32F4的Flash存儲結(jié)構(gòu):
我們主要看主存儲模塊,一共分為12個扇區(qū),最小的是前面4個扇區(qū)16KB,最大的扇區(qū)大小是128KB。
前面我們說過,F(xiàn)lash模擬EEPROM的一個關(guān)鍵點就是,在寫數(shù)據(jù)的時候,不能改變Flash原有的數(shù)據(jù)。而且,解決辦法就是在RAM中開辟一塊和Flash扇區(qū)同樣大小的緩沖區(qū)。
3.2 難點和解決辦法
難點:
但問題是:APM32F4系列的RAM大小,給用戶使用的最大大小是128KB,和最大的Flash扇區(qū)大小是一樣大。我們不可能使用APM32F4后面的Flash扇區(qū),作為模擬EEPROM實現(xiàn)的空間,因為根本沒有那么大的RAM空間作為緩存。
但也不能使用第一塊16KB的扇區(qū)大小進行模擬,因為第一個扇區(qū)是MCU上電啟動會自動取指令的扇區(qū),如果這個區(qū)域存儲的不是合法的指令,那么會造成程序跑飛。
總結(jié)起來就是:
Flash扇區(qū)太大,導(dǎo)致RAM不足以開辟同樣大小的緩沖區(qū)
不能使用第一個扇區(qū),因為那個扇區(qū)是MCU啟動固定使用的
如何解決:
提供上面分析,能留給我們進行Flash模擬EEPROM所使用的扇區(qū)就只有 1~3 這3個扇區(qū)符合要求。那么我們?nèi)绾问褂肍lash中間的扇區(qū)進行實驗?zāi)兀?/p>
我們可以定義一個const數(shù)組,然后使用編譯器屬性指定該數(shù)組在Flash的起始地址(比如我們指定起始地址就位于第1塊扇區(qū)的首地址),大小是用戶定義的Flash模擬EEPROM的大小。但是必須要必須要是扇區(qū)大小的整數(shù)倍。
代碼如下:
/* Specifies the start address of the sector. The purpose is to occupy a space at the specified address of MCU flash. */
static const uint8_t Flash_Para_Area[FLASH_EE_TOTAL_SIZE] __attribute__((section(".ARM.__at_0x08004000")));
/* The buffer that write or erase sector data */
static uint8_t Flash_EE_Ram_Buffer[FLASH_SECTOR_SIZE];
這個const的數(shù)組,其實在代碼中并沒有任何作用,它的目的就是占據(jù)這塊Flash空間,而不讓編譯器鏈接時,把代碼鏈接到這塊區(qū)域,因為這塊區(qū)域是要用于用戶存儲數(shù)據(jù)的,在這個過程中可能會被擦除。
3.3 APM32F4 Flash的存儲區(qū)域規(guī)劃
進過前面的分析和規(guī)劃,最終APM32F4 Flash的存儲區(qū)域劃分,如下圖:
第1~3這3個扇區(qū)可以劃分,作為Flash模擬EEPROM的區(qū)域,其他的扇區(qū)都是用于存放代碼的區(qū)域。
4. APM32F4系列Flash模擬EEPROM代碼介紹
可以先到Geehy官網(wǎng),下載F4系列的SDK,然后隨便復(fù)制其中一個例程,在該例程編寫Flash模擬EEPROM的代碼實現(xiàn)。
4.1 相關(guān)宏定義
/* flash sector satrt address */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* 16 Kbytes */
/* flash sector size */
#define FLASH_SECTOR_SIZE ((uint32_t)(1024 * 16))
/* flash emulation eeprom total size. This value must be a multiple of 16KB */
#define FLASH_EE_TOTAL_SIZE ((uint32_t)(1024 * 16 * 2))
/* flash emulation eeprom sector start address, it's must be sector aligned */
#define FLASH_EE_START_ADDR ADDR_FLASH_SECTOR_1
/* flash emulation eeprom sector start address */
#define FLASH_EE_END_ADDR (ADDR_FLASH_SECTOR_1 + FLASH_EE_TOTAL_SIZE)
FLASH_SECTOT_SIZE:定義的Flash的扇區(qū)大小。不同系列的MCU,扇區(qū)大小不一樣。
FLASH_EE_TOTAL_SIZE:Flash模擬EEPROM的Flash總大小,該大小必須是扇區(qū)大小的整數(shù)倍。在F4上最多也只有3*16KB總大小。
FLASH_EE_START_ADDR:Flash模擬EEPROM的Flash起始地址,起始地址是必須要扇區(qū)對齊的。即只能是扇區(qū)的起始地址。
4.2 讀寫接口函數(shù)
我們在使用過程中,只需要使用讀數(shù)據(jù)、寫數(shù)據(jù)接口函數(shù)即可。
/*
* readAddr: 讀數(shù)據(jù)起始地址
* pData: 指針,指向保存讀出的數(shù)據(jù)的緩沖區(qū)
* len: 讀取數(shù)據(jù)的長度
*/
void Flash_EE_Read(uint32_t readAddr, uint8_t* pData, uint32_t len);
/*
* readAddr: 寫數(shù)據(jù)起始地址
* pData: 指針,指向需要寫入數(shù)據(jù)的緩沖區(qū)
* len: 寫入數(shù)據(jù)的長度
*/
void Flash_EE_Write(uint32_t writeAddr, uint8_t* pData, uint32_t len);
5. 另一種Flash模擬EEPROM方案介紹
前面介紹的,是Flash模擬EEPROM的其中一種方案。特點是直接對Flash進行操作,但也是實現(xiàn)了對Flash按字節(jié)的讀寫操作,而且不會改變Flash原有的存儲數(shù)據(jù),而且還可以跨扇區(qū)進行讀寫數(shù)據(jù)。
另外,還有另一種Flash模擬EEPROM的實現(xiàn)方案。
5.1 數(shù)據(jù)存儲格式
該方案需要使用至少兩塊相同的扇區(qū)/頁,使用至少兩個相同大小的扇區(qū)/頁,其中一個扇區(qū)處于有效狀態(tài),而另一個扇區(qū)處于擦除狀態(tài)。然后每4個字節(jié)分為:2字節(jié)data + 2字節(jié)virtual address 的存儲格式。具體數(shù)據(jù)存儲格式如下:
其中:
每個頁的第一個存儲區(qū),保存當(dāng)前的頁狀態(tài)。
flash address:就是MCU flash的實際地址,在代碼中并沒有使用到,只用到頁起始和結(jié)束地址。
data:用戶存儲的數(shù)據(jù)。
virtual address:對應(yīng)數(shù)據(jù)的虛擬地址,在讀數(shù)據(jù)時,我們需要根據(jù)這個虛擬地址進行尋址。
存儲變量的個數(shù):扇區(qū)大小 / 4 - 1。比如 2KB / 4 – 1 = 511,即最多可以存儲511個變量。
5.2 扇區(qū)/頁狀態(tài)
每個扇區(qū)/頁都有三種狀態(tài):
有效狀態(tài):該頁包含所有的有效數(shù)據(jù),讀寫數(shù)據(jù)在該頁進行
擦除狀態(tài):就是一個空的頁
數(shù)據(jù)傳輸狀態(tài):當(dāng)一個頁寫滿時,把已經(jīng)寫滿的頁的有效數(shù)據(jù)復(fù)制到本頁的狀態(tài)
5.3 數(shù)據(jù)更新過程
該方案有數(shù)據(jù)讀、寫、轉(zhuǎn)移三種過程:
寫數(shù)據(jù):從頁起始地址開始尋址,找到第一個已經(jīng)被擦除的區(qū)域(比如前面的數(shù)據(jù)存儲格式的圖片,flash address = 24的位置),然后把數(shù)據(jù)和對應(yīng)的虛擬地址一起寫入。當(dāng)?shù)诙胃膶懲惶摂M地址處的值時,會在Flash新的位置,存儲該虛擬地址的值。比如比如前面圖片的flash address = 20的地址處,存儲的虛擬地址是0x7777,是第二次出現(xiàn)的虛擬地址,修改數(shù)據(jù)就是會這樣在新的位置存儲新的值。其中最后一次存儲的數(shù)據(jù),才是有效數(shù)據(jù)。
讀數(shù)據(jù):從頁結(jié)束地址開始尋址,找到對應(yīng)地址最后一次改變的數(shù)據(jù)(其實就是有效數(shù)據(jù))。比如前面的數(shù)據(jù)存儲格式的圖片,有兩個0x7777地址對應(yīng)的數(shù)據(jù),只會返回最后一次改變的數(shù)據(jù)。
數(shù)據(jù)轉(zhuǎn)移:當(dāng)頁0寫滿時,會把該頁的有效數(shù)據(jù)全部復(fù)制到另外一個空頁(頁1)。然后再擦除頁0,把頁1標記為有效狀態(tài),再頁1繼續(xù)寫數(shù)據(jù)。
6. 后續(xù)補充
目前,我只實現(xiàn)了Flash模擬EEPROM第一種方法的代碼。這里留個坑,我后續(xù)會實現(xiàn)APM32F4系列的第二種Flash模擬EEPROM的代碼。
如果還有時間的話,把APM32F1系列的MCU,也一起實現(xiàn)了Flash模擬EEPROM的代碼吧。
反正暫且先留個坑吧。
-
EEPROM
+關(guān)注
關(guān)注
9文章
1002瀏覽量
81054 -
數(shù)據(jù)線
+關(guān)注
關(guān)注
8文章
277瀏覽量
37458 -
代碼
+關(guān)注
關(guān)注
30文章
4670瀏覽量
67760
原文標題:APM32芯得 EP.26 | APM32F4 Flash模擬EEPROM介紹和代碼實現(xiàn)
文章出處:【微信號:geehysemi,微信公眾號:Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論