說到STM32的FLSAH,咱們的第一反應是用來裝程序的,實際上,STM32的片內FLASH不只用來裝程序,還用來裝芯片配置、芯片ID、自舉程序等等。固然, FLASH還能夠用來裝數據。 編程
FLASH分類 安全
根據用途,STM32片內的FLASH分紅兩部分:主存儲塊、信息塊。 ui
主存儲塊用於存儲程序,咱們寫的程序通常存儲在這裏。 spa
信息塊又分紅兩部分:系統存儲器、選項字節。 指針
系統存儲器存儲用於存放在系統存儲器自舉模式下的啓動程序(BootLoader),當使用ISP方式加載程序時,就是由這個程序執行。這個區域由芯片廠寫入BootLoader,而後鎖死,用戶是沒法改變這個區域的。 調試
選項字節存儲芯片的配置信息及對主存儲塊的保護信息。 接口
FLASH的頁面 開發
STM32的FLASH主存儲塊按頁組織,有的產品每頁1KB,有的產品每頁2KB。頁面典型的用途就是用於按頁擦除FLASH。從這點來看,頁面有點像通用FLASH的扇區。 產品
STM32產品的分類 it
STM32根據FLASH主存儲塊容量、頁面的不一樣,系統存儲器的不一樣,分爲小容量、中容量、大容量、互聯型,共四類產品。
小容量產品主存儲塊1-32KB,每頁1KB。系統存儲器2KB。
中容量產品主存儲塊64-128KB,每頁1KB。系統存儲器2KB。
大容量產品主存儲塊256KB以上,每頁2KB。系統存儲器2KB。
互聯型產品主存儲塊256KB以上,每頁2KB。系統存儲器18KB。
對於具體一個產品屬於哪類,能夠查數據手冊,或根據如下簡單的規則進行區分:
STM32F101xx、STM32F102xx 、STM32F103xx產品,根據其主存儲塊容量,必定是小容量、中容量、大容量產品中的一種,STM32F105xx、STM32F107xx是互聯型產品。
互聯型產品與其它三類的不一樣之處就是BootLoader的不一樣,小中大容量產品的BootLoader只有2KB,只能經過USART1進行ISP,而互聯型產品的BootLoader有18KB,能經過USAT1、4、CAN等多種方式進行ISP。小空量產品、中容量產品的BootLoader與大容量產品相同。
關於ISP與IAP
ISP(In System Programming)在系統編程,是指直接在目標電路板上對芯片進行編程,通常須要一個自舉程序(BootLoader)來執行。ISP也有叫ICP(In Circuit Programming)、在電路編程、在線編程。
IAP(In Application Programming)在應用中編程,是指最終產品出廠後,由最終用戶在使用中對用戶程序部分進行編程,實如今線升級。IAP要求將程序分紅兩部分:引導程序、用戶程序。引導程序老是不變的。IAP也有叫在程序中編程。
ISP與IAP的區別在於,ISP通常是對芯片整片從新編程,用的是芯片廠的自舉程序。而IAP只是更新程序的一部分,用的是電器廠開發的IAP引導程序。綜合來看,ISP受到的限制更多,而IAP因爲是本身開發的程序,更換程序的時候更容易操做。
FPEC
FPEC(FLASH Program/Erase controller 閃存編程/擦除控制器),STM32經過FPEC來擦除和編程FLASH。FPEC使用7個寄存器來操做閃存:
FPEC鍵寄存器(FLASH_KEYR) 寫入鍵值解鎖。
選項字節鍵寄存器(FLASH_OPTKEYR) 寫入鍵值解鎖選項字節操做。
閃存控制寄存器(FLASH_CR) 選擇並啓動閃存操做。
閃存狀態寄存器(FLASH_SR) 查詢閃存操做狀態。
閃存地址寄存器(FLASH_AR) 存儲閃存操做地址。
選項字節寄存器(FLASH_OBR) 選項字節中主要數據的映象。
寫保護寄存器(FLASH_WRPR) 選項字節中寫保護字節的映象。
鍵值
爲了加強安全性,進行某項操做時,需要向某個位置寫入特定的數值,來驗證是否爲安全的操做,這些數值稱爲鍵值。STM32的FLASH共有三個鍵值:
RDPRT鍵 = 0x000000A5 用於解除讀保護
KEY1 = 0x45670123 用於解除閃存鎖
KEY2 = 0xCDEF89AB 用於解除閃存鎖
閃存鎖
在FLASH_CR中,有一個LOCK位,該位爲1時,不能寫FLASH_CR寄存器,從而也就不能擦除和編程FLASH,這稱爲閃存鎖。
當LOCK位爲1時,閃存鎖有效,只有向FLASH_KEYR依次寫入KEY1、KEY2後,LOCK位纔會被硬件清零,從而解除閃存鎖。當LOCK位爲1時,對FLASH_KEYR的任何錯誤寫操做(第一次不是KEY1,或第二次不是KEY2),都將會致使閃存鎖的完全鎖死,一旦閃存鎖完全鎖死,在下一次復位前,都沒法解鎖,只有復位後,閃存鎖才恢復爲通常鎖住狀態。
復位後,LOCK位默認爲1,閃存鎖有效,此時,能夠進行解鎖。解鎖後,可進行FLASH的擦除編程工做。任什麼時候候,均可以經過對LOCK位置1來軟件加鎖,軟件加鎖與復位加鎖是同樣的,均可以解鎖。
主存儲塊的擦除
主存儲塊能夠按頁擦除,也能夠整片擦除。
頁擦除
主存儲塊的任何一頁均可以經過FPEC的頁擦除功能擦除。
建議使用如下步驟進行頁擦除:
1.檢查FLASH_SR寄存器的BSY位。以確認沒有其餘正在進行的閃存操做。必須等待BSY位爲0,才能繼續操做。
2.設置FLASH_CR寄存器的PER位爲1。選擇頁擦除操做。
3.設置FLASH_AR寄存器爲要擦除頁所在地址,選擇要擦除的頁。FLASH_AR的值在哪一頁範圍內,就表示要擦除哪一頁。
4.設置FLASH_CR寄存器的STRT位爲1,啓動擦除操做。
5.等待FLASH_SR寄存器的BSY位變爲0,表示操做完成。
6.查詢FLASH_SR寄存器的EOP位,EOP爲1時,表示操做成功。
7.讀出被擦除的頁並作驗證。擦完後全部數據位都爲1。
整片擦除
整片擦除功能擦除整個主存儲塊,信息塊不受此操做影響。
建議使用如下步驟進行整片擦除:
1.檢查FLASH_SR寄存器的BSY位,以確認沒有其餘正在進行的閃存操做。
2.設置FLASH_CR寄存器的MER位爲1。選擇整片擦除操做。
3.設置FLASH_CR寄存器的STRT位爲1。啓動整片擦除操做。
4.等待FLASH_SR寄存器的BSY位變爲0,表示操做完成。
5.查詢FLASH_SR寄存器的EOP位,EOP爲1時,表示操做成功。
6.讀出全部頁並作驗證。擦完後全部數據位都爲1。
主存儲塊的編程
對主存儲塊編程每次能夠寫入16位。當FLASH_CR寄存器的PG位爲1時,在一個閃存地址寫入一個半字(16位)將啓動一次編程;寫入任何非半字的數據,FPEC都會產生總線錯誤。在編程過程當中(BSY位爲1時),任何讀寫閃存的操做都會使CPU暫停,直到這次閃存編程結束。
建議使用以下步驟對主存儲塊進行編:
1.檢查FLASH_SR寄存器的BSY位,以確認沒有其餘正在進行的編程操做。
2.設置FLASH_CR寄存器的PG位爲1。選擇編程操做。
3.在指定的地址寫入要編程的半字。直接用指針寫。
4.等待FLASH_SR寄存器的BSY位變爲0,表示操做完成。
5.查詢FLASH_SR寄存器的EOP位,EOP爲1時,表示操做成功。
6.讀出寫入的地址並驗證數據。
關於主存儲塊擦除編程操做的一些疑問
1. 爲何每次都要檢查BSY位是否爲0?
由於BSY位爲1時,不能對任何FPEC寄存器執行寫操做,因此必需要等BSY位爲0時,才能執行閃存操做。
2. 若是沒有擦除就進行編程,會出現什麼結果?
STM32在執行編程操做前,會先檢查要編程的地址是否被擦除,若是沒有,則不進行編程,並置FLASH_SR寄存器的PGERR位爲1。惟一例外的是,當要編程的數據爲0X0000時,即便未擦除,也會進行編程,由於0X0000即便擦除也能夠正確編程。
3. 爲何操做後要讀出數據並驗證?
STM32在某些特殊狀況下(例如FPEC被鎖住),可能根本就沒有執行所要的操做,僅經過寄存器沒法判斷操做是否成功。因此,保險起見,操做後都要讀出全部數據檢查。
4. 等待BSY位爲1的時間以多少爲合適?
請參考STM32固件庫中的數據。
5. FLASH編程手冊上說進行閃存操做(擦除或編程)時,必須打開內部的RC振盪器(HSI),是否是必定要用HIS進行閃存的擦除及編程操做?
對於這點,個人理解是,進行閃存操做時,必需要保證HIS沒有被關閉,可是操做時的系統仍然能夠是HSE時鐘。STM32復位後,HIS默認是開的,只要你不爲了低功耗去主動關閉它,則用什麼時鐘均可以進行閃存操做的。我所編的程序也驗證了這一點。
選項字節
選項字節用於存儲芯片使用者對芯片的配置信息。
目前,全部的STM32101xx、STM32102xx、STM32103xx、STM32105xx、STM32107xx產品,選項字節都是16字節。可是這16字節,每兩個字節組成一個正反對,即,字節1是字節0的反碼,字節3是字節2的反碼,...,字節15是字節14的反碼,因此,芯片使用者只要設置8個字節就好了,另外8個字節系統自動填充爲反碼。所以,有時候,也說STM32的選項字節是8個字節,可是佔了16字節的空間。
選項字節的8字節正碼概述以下:
RDP 字節0。讀保護字節,存儲對主存儲塊的讀保護設置。
USER 字節2。用戶字節,配置看門狗、停機、待機。
Data0 字節4。數據字節0,由芯片使用者自由使用。
Data1 字節6。數據字節1,由芯片使用者自由使用。
WRP0 字節8。寫保護字節0,存儲對主存儲塊的寫保護設置。
WRP1 字節10。寫保護字節1,存儲對主存儲塊的寫保護設置。
WRP2 字節12。寫保護字節2,存儲對主存儲塊的寫保護設置。
WRP3 字節14。寫保護字節3,存儲對主存儲塊的寫保護設置。3
選項字節寫使能
在FLASH_CR中,有一個OPTWRE位,該位爲0時,不容許進行選項字節操做(擦除、編程)。這稱爲選項字節寫使能。只有該位爲1時,才能進行選項字節操做。
該位不能軟件置1,但能夠軟件清零。只有向FLASH_OPTKEYR依次寫入KEY1和KEY2後,硬件會自動對該位置1,此時,才容許選項字節操做。這稱爲解鎖(打開)選項字節寫使能。
該位爲1後,能夠由軟件清零,關閉寫使能。
復位後,該位爲0。錯誤操做不會永遠關閉寫使能,只要寫入正確的鍵序列,則又能夠打開寫使能。寫使能已打開時,再次打開,不會出錯,而且依然是打開的。
很顯然,進行選項字節操做前,先要解開閃存鎖,而後打開選項字節寫使能,以後,才能進行選項字節操做。
選項字節擦除
建議使用以下步驟對選項字節進行擦除:
1.檢查FLASH_SR寄存器的BSY位,以確認沒有其餘正在進行的閃存操做。
2.解鎖FLASH_CR寄存器的OPTWRE位。即,打開寫使能。
3.設置FLASH_CR寄存器的OPTER位爲1。選擇選項字節擦除操做。
4.設置FLASH_CR寄存器的STRT位爲1。
5.等待FLASH_SR寄存器的BSY位變爲0,表示操做完成。
6.查詢FLASH_SR寄存器的EOP位,EOP爲1時,表示操做成功。
7.讀出選項字節並驗證數據。
因爲選項字節只有16字節,所以,擦除時是整個選項字節都被擦除了。
選項字節編程
建議使用以下步驟對選項字節進行編程:
1.檢查FLASH_SR寄存器的BSY位,以確認沒有其餘正在進行的編程操做。
2.解鎖FLASH_CR寄存器的OPTWRE位。即,打開寫使能。
3.設置FLASH_CR寄存器的OPTPG位爲1。選擇編程操做。
4.寫入要編程的半字到指定的地址。啓動編程操做。
5.等待FLASH_SR寄存器的BSY位變爲0,表示操做完成。
6.查詢FLASH_SR寄存器的EOP位,EOP爲1時,表示操做成功。
7.讀出寫入的選項字節並驗證數據。
對選項字節編程時,FPEC使用半字中的低字節並自動地計算出高字節(高字節爲低字節的反碼),並開始編程操做,這將保證選項字節和它的反碼始終是正確的。
主存儲塊的保護
能夠對主存儲塊中的數據進行讀保護、寫保護。
讀保護用於保護數據不被非法讀出。防止程序泄密。
寫保護用於保護數據不被非法改寫,加強程序的健壯性。
讀保護
主存儲塊啓動讀保護後,簡單的說具備如下特性:
1.從主存儲塊啓動的程序,能夠對整個主存儲塊執行讀操做,不容許對主存儲塊的前4KB進行擦除編程操做,能夠對4KB以後的區域進行擦除編程操做。
2.從SRAM啓動的程序,不能對主存儲塊進行讀、頁擦除、編程操做,但能夠進行主存儲塊整片擦除操做。
3.使用調試接口不能訪問主存儲塊。
這些特性足以阻止主存儲器數據的非法讀出,又能保證程序的正常運行。
只有當RDP選項字節的值爲RDPRT鍵值時,讀保護才被關閉,不然,讀保護就是啓動的。所以,擦除選項字節的操做,將啓動主存儲塊的讀保護。若是要關閉讀保護,必須將RDP選項字節編程爲RDPRT鍵值。而且,若是編程選項字節,使RDP由非鍵值變爲鍵值(即由保護變爲非保護)時,STM32將會先擦除整個主存儲塊,再編程RDP。
芯片出廠時,RDP會事先寫入RDPRT鍵值,關閉寫保護功能。
寫保護
STM32主存儲塊能夠分域進行寫保護。
若是試圖對寫保護的域進行擦除或編程操做,在閃存狀態寄存器(FLASH_SR)中會返回一個寫保護錯誤標誌。
STM32主存儲塊每一個域4KB,WRP0-WRP3選項字節中的每一位對應一個域,位爲0時,寫保護有效。對於超過128KB的產品,WRP3.15保護了域31及以後的全部域。
顯然,擦除選項字節將致使解除主存儲塊的寫保護。
選項字節與它的寄存器映象
咱們知道,FPEC有兩個寄存器存儲了選項字節的映象。那麼,選項字節本體(在FLASH中)與映象(在寄存器中)究竟有什麼區別呢?
選項字節的本體只是個FLASH,它的做用只是掉電存儲選項字節內容而以,真正起做用的是寄存器中的映象。即,一個配置是否有效,不是看本體,而是看映象。而映象是在復位後,用本體的值加載的,此後,除非復位,映象將再也不改變。因此,更改本體的數據後,不會當即生效,只有復位加載到映象中後,纔會生效。
有一點要注意的是,當更改本體的值,使主存儲塊讀保護變爲不保護時,會先擦除整片主存儲塊,而後再改變本體。這是惟一一個改變本體會引起的動做。但即便這樣,讀保護依然要等到復位後,加載到映象後,纔會解除。
關於FLASH編程手冊中文版的幾處錯誤(不必定是,可是與個人理解不符)
1.選項字節編程一節中:
對FPEC解鎖後,必須分別寫入KEY1和KEY2(見2.3.1節)到FLASH_OPTKEYR寄存器,再設置FLASH_CR寄存器的OPTWRE位爲’1’,此時能夠對選項字節進行編程
實際上,對FLASH_OPTKEYR寫入KEY1和KEY2後,OPTWRE位會被硬件置1,而不是用軟件寫1。這一點在後面的寄存器描述中也能夠獲得驗證。
2.對讀保護的描述中:
對讀保護的數值對沒法理解。正確的應該是,RDP爲RDPRT鍵值時,解除讀保護,爲其它值時,讀保護生效。