Flash(閃存)是一種可擦除的只讀存儲器,按照實現(xiàn)方式和運(yùn)行特性Flash一般還會分為NOR和NAND兩種。其中NOR Flash支持隨機(jī)地址的讀取方式,在讀取操作上類似于RAM,比較適合程序的直接讀取運(yùn)行,而NAND Flash讀取是基于頁的方式,一般無法隨機(jī)讀取。在MCU中,F(xiàn)lash需要支持程序和數(shù)據(jù)的存儲,所以實現(xiàn)方式上也都是NOR Flash。
基本特性
YTM32系列MCU中Flash的控制是通過EFM(Embedded Flash Module)控制的,這里以ME0x系列MCU為例,EFM模塊支持如下的一些功能:
- 512KB * 2 的程序存儲區(qū)域,帶有ECC功能,Sector大小為2K
- 256KB 單獨的數(shù)據(jù)存儲塊,帶有ECC功能,Sector大小為1K
- 4KB的NVR區(qū)域,帶有ECC功能,Sector大小為1K
- 支持Flash按區(qū)域(16KB單位)的寫保護(hù)功能
- 支持調(diào)試器禁用
- 支持Flash命令執(zhí)行結(jié)束和異常中斷
- 支持Block Swap的OTA升級功能
- 支持ECC錯誤地址記錄和單比特、多比特中斷
- 支持OTP(One Time Program,一次可編程)區(qū)域
- 支持HCU 密鑰存儲(可擦寫,不可讀取)
- 支持塊擦除、扇區(qū)(sector)擦除和整個chip的擦除操作
- 寫入頁大小為8Bytes
Flash的基本術(shù)語約定
為了便于理解,這里整理一下Flash使用中常用的一些基本術(shù)語:
- PFlash,程序Flash,實際也可以保存數(shù)據(jù),屬于基于應(yīng)用場景的一種約定名稱
- DFlash,數(shù)據(jù)Flash,實際也可以運(yùn)行程序,同樣屬于基于應(yīng)用場景的一種約定名稱
- Block,F(xiàn)lash塊,表示物理上的一個Flash塊,不同物理塊的flash可以支持Read While Write(RWW)特性
- Sector,扇區(qū),這個是Flash擦除的最小單位,屬于Flash的物理特性,軟件無法修改
- Page,F(xiàn)lash 編程的最小單位,同樣屬于Flash物理特性,軟件無法修改
- RWW,Read While Write,指的是Flash在運(yùn)行擦除或者編程操作時候支持Flash的讀取操作
- ECC校驗,糾錯算法的一種,可以糾正單比特錯誤,檢測多比特錯誤
Memory Map定義
這里以ME0x為例,芯片系統(tǒng)存儲的memory map如下
Name | Start Address | End Address | Size(KB) | Block | Protect |
---|---|---|---|---|---|
PFlash0 | 0x0000_0000 | 0x0007_FFFF | 512 | 0 | ADDR_PROT0 |
PFlash1 | 0x0008_0000 | 0x000F_FFFF | 512 | 1 | ADDR_PROT1 |
DFlash | 0x0010_0000 | 0x0013_FFFF | 256 | 2 | ADDR_PROT2 |
AES_NVR | 0x1000_0000 | 0x1000_03FF | 1 | 0 | No Read + Customer Key |
OTP_NVR | 0x1001_0000 | 0x1001_03FF | 1 | 0 | No Erase |
BOOT_NVR | 0x1002_0000 | 0x1002_03FF | 1 | 1 | SWAP CMD only |
CUS_NVR | 0x1003_0000 | 0x1003_03FF | 1 | 1 | Customer Key |
上述表格中PFlash0和PFlash1是用于存儲用戶程序的,當(dāng)使用OTA功能的時候,這兩個Block可以通過物理地址的重映射互換,實現(xiàn)應(yīng)用升級。
AES_NVR
主要用于保存HCU中使用的密鑰,該部分占用1KB空間,可以實現(xiàn)32*256Bit的密鑰存儲。該部分區(qū)域支持用戶的Program和Erase,但是不支持讀取操作,可以保證密鑰的安全。當(dāng)HCU需要使用密鑰的時候,軟件可以直接調(diào)用Flash的命令將需要用到的Key直接load到HCU中使用,整個過程軟件只能選擇key而不能讀取或者修改key。注意program和erase AES key區(qū)域需要用customer key解鎖。
OTP_NVR
該部分可以用于保存一次可編程數(shù)據(jù),OTP(One Time Program)區(qū)域的特點是只能一次program,不支持擦寫和重新program。應(yīng)用中可以在該部分保存一些產(chǎn)品ID信息或者其它不能希望后續(xù)修改的信息。注意該部分的讀取并沒有限制。
BOOT_NVR
這部分用來保存和OTA升級相關(guān)的數(shù)據(jù),軟件應(yīng)該避免對該區(qū)域進(jìn)行操作,需要使用OTA Swap功能的時候,軟件需要發(fā)送SWAP命令實現(xiàn)Flash的Block Swap。
CUS_NVR
這部分區(qū)域包含F(xiàn)lash擦寫保護(hù)配置和Debugger禁用Tag,用戶可以向該區(qū)域的特定地址program特定值來實現(xiàn)對Flash的擦寫保護(hù)和調(diào)試端口禁用。CUS_NVR
的剩余部分是用戶可以自由使用的,對CUS_NVR
的讀寫操作需要先通過寫入customer key
來解鎖。
Flash的讀寫擦操作
讀取、寫入和擦除是Flash的基本操作,F(xiàn)lash的特性是擦除之后bit變成1,寫入操作是將相應(yīng)的bit改寫成0,不過因為有ECC的限制,YTM32系列MCU都不支持Reprogram,也就是不支持Flash 頁數(shù)據(jù)有非1情況下的頁編程,EFM模塊在執(zhí)行Program命令之前會先從Flash中讀取頁數(shù)據(jù)并驗證數(shù)據(jù)為全1,驗證失敗則該頁無法編程。
另外Flash的物理塊同一個時間只能執(zhí)行讀取、寫入或者擦除的任一操作,這就限制了我們在對一個物理塊(Block)進(jìn)行寫入或者擦除操作時候不能讀取Flash內(nèi)容。這也意味著Flash在執(zhí)行寫入或者擦除的時候,處理器不能從Flash中繼續(xù)讀取程序執(zhí)行代碼,否則EFM模塊會直接產(chǎn)生bus error(M0+中對應(yīng)為hardfault)。這也是L系列MCU在進(jìn)行Flash操作(包括DFlash)的時候必須關(guān)閉中斷的原因。
在ME0x MCU中總共有3個物理Block,在使用過程中,按照上述原則,處理器在不能對同一個block同時進(jìn)行讀寫操作,所以典型的使用方式有如下幾種:
- PFlash0和PFlash1用于保存程序和運(yùn)行數(shù)據(jù),DFlash用于保存Bootloader程序和模擬EEPROM的代碼,這樣在boot模式下,軟件可以直接對兩塊PFlash進(jìn)行讀寫操作而不必禁用系統(tǒng)中斷;而在應(yīng)用軟件運(yùn)行過程中,軟件可以直接操作模擬EEPROM區(qū)域而不必禁用系統(tǒng)中斷。
- 在上述配置的基礎(chǔ)上使用OTA功能,PFlash0和PFlash1分別保存一套程序代碼,通過SWAP指令決定下次復(fù)位之后從哪個block啟動。當(dāng)使用OTA功能的時候,當(dāng)前Block運(yùn)行的程序可以直接對另一個Block的Flash進(jìn)行擦寫操作而不用關(guān)閉中斷,因為這個時候軟件是不會跳轉(zhuǎn)到另外一個block運(yùn)行的,當(dāng)然如果軟件在操作另外一個block的時候,同時對這個block進(jìn)行讀操作也是不允許的。
當(dāng)前EFM設(shè)計中,為了方便軟件使用,對于Flash的編程操作是直接將數(shù)據(jù)寫入Flash對應(yīng)的地址(數(shù)據(jù)都需要4字節(jié)對齊),EFM模塊會從寫入操作捕獲寫入操作的地址和數(shù)據(jù)信息。在這種設(shè)計下,軟件對Flash地址的寫操作并不會產(chǎn)生錯誤,這個和Flash不支持直接寫操作是有一定沖突的,所以嚴(yán)格來說軟件需要通過MPU模塊對不需要編程的Flash進(jìn)行禁止寫操作保護(hù)。注意Flash的寫保護(hù)操作只能保護(hù)Flash內(nèi)容不被擦除和重新編程,處理器直接對這些地址進(jìn)行寫操作的時候,EFM模塊并不會報錯,只有軟件Launch了扇區(qū)擦寫(Sector Erase)或者頁編程(Program)命令的時候,EFM模塊才會檢查當(dāng)前區(qū)域時候被保護(hù),如果為保護(hù)區(qū)域,EFM會abort命令并返回access error錯誤。
Flash command流程
對于Flash的操作都是基于Command來操作的,ME0x支持的command列表如下:
Code | Description | Need Address |
---|---|---|
0x02 | Program 64 bits | Y |
0x03 | Program 64bits and read back verify | Y |
0x10 | Sector erase | Y |
0x11 | Sector erase and verify | Y |
0x12 | Erase block (only main array) | |
Y | ||
0x13 | Erase block and then verify (only main array) | Y |
0x1E | Erase chip | |
N | ||
0x20 | Load AES Key | |
N (Y in MD1) | ||
0x30 | Boot Swap | |
N | ||
0x40 | Program NVR | |
Y | ||
0x41 | Erase NVR | |
Y | ||
0x42 | Read NVR | Y |
以Flash Program為例,Program一個64 bits并verify的command流程如下:
- 確認(rèn)EFM的Prescaler參數(shù)設(shè)置正確
- 跳轉(zhuǎn)到RAM中執(zhí)行代碼,并根據(jù)需要決定是否需要關(guān)閉全局中斷
- 讀取EFM_STS寄存器,判斷當(dāng)前EFM是否正在執(zhí)行命令
- 向需要PROGRAM的flash地址寫入64bit長度數(shù)據(jù)
- 寫
0xfd9573f5
到EFM_CMD_UNLOCK
解鎖FLASH command - 寫0x03到EFM_CMD開始執(zhí)行command
- 輪詢讀取EFM_STS寄存器等待命令執(zhí)行結(jié)束
- 讀取EFM_STS驗證command執(zhí)行結(jié)果
EFM寄存器介紹
EFM對Flash的所有操作都是通過寄存器接口實現(xiàn)的,這里對EFM寄存器的主要域做一個簡單介紹。
CTRL寄存器
CTRL寄存器用于配置EFM操作的基礎(chǔ)配置,比如低功耗模式是否關(guān)閉Flash,選擇HCU的KEY,EFM模塊的時鐘基準(zhǔn),是否開啟數(shù)據(jù)預(yù)取加速,數(shù)據(jù)讀取的等待周期和各種中斷源的開關(guān)。
EFM CTRL寄存器
AES_KEY_SEL
用于選擇load到HCU中AES key的ID,這個操作后續(xù)都換成Flash 命令操作了,僅在ME0x中有該域。
PRESCALER
是Flash操作的一個基礎(chǔ)分頻,軟件初始化的時候需要將PRESCALER設(shè)置為主頻/2MHz,比如Core時鐘為120MHz,那么,EFM模塊會根據(jù)這個值來產(chǎn)生program和erase的時間,如果這個值設(shè)置不準(zhǔn)確(主要是偏小)可能會導(dǎo)致Flash編程或者擦除異常。SDK中在時鐘初始化的時候自動適配該值。
RWS
是Flash讀操作的等待周期,ME0x中Flash的最高頻率是40MHz,當(dāng)主頻為120MHz時候,,RWS設(shè)置過大會導(dǎo)致系統(tǒng)性能下降,過小則會導(dǎo)致Flash讀取數(shù)據(jù)異常。RWS通過時鐘的.flashDiv = *SCU_SYS_CLK_DIV_BY_3
* 配置,SCU_SYS_CLK_DIV_BY_3
表示3分頻,RWS=2。
STS寄存器
STS寄存器保存了Flash操作的狀態(tài)信息,包含F(xiàn)lash當(dāng)前是否在執(zhí)行命令,當(dāng)前的啟動Block,F(xiàn)lash命令的執(zhí)行結(jié)果和錯誤原因以及ECC錯誤的標(biāo)志位。
CMD寄存器
軟件通過向CMD寫入命令來啟動flash的相關(guān)操作,為了保護(hù)CMD不被意外觸發(fā),對CMD操作之前需要向CMD_UNLOCK
寄存器寫入0xfd9573f5
來解鎖,解鎖后軟件必須立即寫入CMD而不能進(jìn)行其他寄存器訪問,否則CMD會產(chǎn)生Access Error。
TIMING1和TIMING2寄存器
這兩個寄存器是用來做Flash命令的時序微調(diào),當(dāng)CTRL_PRESCALER
域正確配置時,這兩個寄存器保持復(fù)位值就可以了,錯誤的修改這兩個值會導(dǎo)致Flash擦寫異常。
NVR_ADDR和NVR_DATA
這一組寄存器用來傳遞NVR操作的地址和數(shù)據(jù)信息。
ADDR_PROT寄存器
ADDR_PROT
是一組寄存器,ME0x中是3個32位的寄存器,每個寄存器保護(hù)一個block,ADDR_PROT
的所有bit只能由1寫0,bit為1表示對應(yīng)區(qū)域是未保護(hù)的,為0則表示對應(yīng)區(qū)域不能進(jìn)行擦除和寫入操作,ADDR_PROT
上電時會自動從CFG_NVR
的特定地址載入。
ADDR_PROT0
:定義了Block0(PFlash0)的保護(hù)區(qū)域,每個bit保護(hù)16KB。
ADDR_PROT1
:定義了Block1(PFlash1)的保護(hù)區(qū)域,每個bit保護(hù)16KB。
ADDR_PROT0
:定義了Block0(DFlash)的保護(hù)區(qū)域,每個bit保護(hù)8KB。
ECC_ERR_ADDR寄存器
該寄存器保存了發(fā)生ECC錯誤的地址,軟件可以配合ECC錯誤的STS標(biāo)志實現(xiàn)對Flash ECC錯誤的定位。
Flash操作時間
軟件應(yīng)用中對于Flash的編程和擦寫的時間一般比較敏感,這里將Flash一些基本操作的時間列舉如下:
操作 | M系列 | L系列 |
---|---|---|
Sector Erase | 16ms | 4.5ms |
Block Erase | 16ms | 35ms |
Chip Erase | 16ms | 35ms |
Page Program | 45us | 50us |
因為Flash操作時間和Prescaler和TIMING寄存器配置有關(guān),上述表格的數(shù)據(jù)是在Prescaler正確配置和TIMING保持默認(rèn)值下的數(shù)據(jù)。
M系列擦除的時間都是16ms,F(xiàn)lash array支持多扇區(qū)同時擦寫,所以整個block甚至整個芯片的擦除時間都是16ms,當(dāng)采用erase retry的擦除方式時,EFM會按照800us的周期對flash進(jìn)行擦除嘗試,這種方式下擦寫的時間是800us~16ms。Erase retry僅支持單個sector的擦寫。
L系列因為只有一個Block的緣故,Block Erase和Chip Erase并沒有什么區(qū)別,也不支持erase retry功能,另外L系列的Dflash實際和Pflash屬于相同的block,所以對Dflash進(jìn)行擦寫操作時候,也不支持對PFlash進(jìn)行讀操作。因此用Dflash模擬EEPROM的時候還是需要禁用系統(tǒng)中斷的。
調(diào)試禁用和Flash保護(hù)
為了保護(hù)用戶的軟件代碼,ME0x系列支持通過Flash禁用芯片調(diào)試端口,這個過程是在芯片初始化過程中通過硬件實現(xiàn)的。同樣為了避免程序在運(yùn)行過程中對Flash進(jìn)行意外操作,F(xiàn)lash同樣支持基于地址的擦寫保護(hù),應(yīng)用程序可以根據(jù)實際應(yīng)用需求限制。
在YTM32B1ME0x中,CUS_NVR
的起始地址是0x1001_0000U
,這部分NVR區(qū)域中數(shù)據(jù)定義如下:
Region(32bits) | Address | Description |
---|---|---|
Debugger Disable Tag 0 | 0x10010000 | TAG=0x5a5a5a5a Disable debugger |
Debugger Disable Tag 1 | 0x10010004 | TAG=0x5a5a5a5a Disable debugger |
PROT0 Tag | 0x10010008 | TAG=0x5a5a5a5a |
PROT0 Value | 0x1001000C | ADDR_PROT0 Init value |
PROT1 Tag | 0x10010010 | TAG=0x5a5a5a5a |
PROT1 Value | 0x10010014 | ADDR_PROT1 Init value |
PROT2 Tag | 0x10010018 | TAG=0x5a5a5a5a |
PROT2 Value | 0x1001001C | ADDR_PROT2 Init value |
User NVR | User can use other left space |
因為NVR區(qū)域的頁大小也是8 Bytes(64bits),實際單次至少寫入兩個words。比如當(dāng)希望在上電后禁用調(diào)試端口,那么只需要向0x10010000U
地址寫入0x5a5a5a5a
, 0x5a5a5a5a
,那么下次芯片復(fù)位之后調(diào)試端口默認(rèn)就不會開啟了。
PROT相應(yīng)的tag和value也是一起編程的,當(dāng)tag匹配的時候,下次上電對應(yīng)的value就會自動load到相應(yīng)的寄存器實現(xiàn)Flash的保護(hù)。
HCU KEY區(qū)域
ME0x芯片內(nèi)置HCU加速模塊,可以實現(xiàn)硬件的AES/SHA/SM4運(yùn)算加速,F(xiàn)LASH模塊支持存儲32組長度為256bit的AES KEY,軟件在使用這些key的時候可以直接將KEY load到HCU模塊,這個過程中軟件無法讀取KEY的值,可以保證KEY的安全性。
在ME0x中,HCU的KEY是通過EFM_CTRL_AES_KEY_SEL
域來選擇然后發(fā)Flash命令讀取的,不過后續(xù)項目中將這個操作統(tǒng)一成標(biāo)準(zhǔn)Flash command,用戶直接給出KEY存儲的地址,然后直接通過命令load。因為KEY的load本身也是一個Flash操作,所以執(zhí)行該命令的時候同樣不支持RWW操作,軟件需要關(guān)閉中斷,并在RAM中執(zhí)行該命令。
NVR操作注意事項
因為NVR區(qū)域和block有一定的對應(yīng)關(guān)系,并且block swap還會改動這個對應(yīng)關(guān)系,除非明確軟件和NVR不在一個block,否則對于NVR區(qū)域的操作還是需要關(guān)中斷和在RAM中執(zhí)行。
對于NVR區(qū)域的擦除和寫入操作的時間與Main Array一致。
-
mcu
+關(guān)注
關(guān)注
146文章
16992瀏覽量
350310 -
閃存
+關(guān)注
關(guān)注
16文章
1777瀏覽量
114811 -
寄存器
+關(guān)注
關(guān)注
31文章
5317瀏覽量
120007 -
FlaSh
+關(guān)注
關(guān)注
10文章
1621瀏覽量
147753 -
存儲器
+關(guān)注
關(guān)注
38文章
7452瀏覽量
163606
發(fā)布評論請先 登錄
相關(guān)推薦
評論