STM32的FLASH操作介紹與總結

說到STM32的FLSAH,我們的第一反應是用來裝程序的,實際上,STM32的片內FLASH不僅用來裝程序,還用來裝芯片配置、芯片ID、自舉程序等等。當然, FLASH還可以用來裝數據。

FLASH分類

根據用途,STM32片內的FLASH分成兩部分:主存儲塊、信息塊。

主存儲塊用於存儲程序,我們寫的程序一般存儲在這裏。

信息塊又分成兩部分:系統存儲器、選項字節。

系統存儲器存儲用於存放在系統存儲器自舉模式下的啓動程序(BootLoader),當使用ISP方式加載程序時,就是由這個程序執行。這個區域由芯片廠寫入BootLoader,然後鎖死,用戶是無法改變這個區域的。

選項字節存儲芯片的配置信息及對主存儲塊的保護信息。

FLASH的頁面

STM32的FLASH主存儲塊按頁組織,有的產品每頁1KB,有的產品每頁2KB。頁面典型的用途就是用於按頁擦除FLASH。從這點來看,頁面有點像通用FLASH的扇區。

STM32產品的分類

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 = 0×45670123 用於解除閃存鎖

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鍵值時,解除讀保護,爲其它值時,讀保護生效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章