
FLASH閃存程序現象1、讀寫內部FLASH這個代碼的目的就是利用內部flash程序存儲器的剩余空間來存儲一些掉電不丟失的參數。所以這里的程序是按下K1變換一下測試數據然后存儲到內部FLASH按下K2把所有參數清0最后OIED顯示一下。這里OLED顯示Flag、Data 。Flag當做標志位內容定義為A5A5。Flag作用判斷之前是不是存儲過數據如果存儲過直接讀取如沒有存儲過就先初始化。Data是要掉電存儲的數據。2讀取芯片ID在stm32里指定地址下存儲有原廠寫入的ID號使用指針的方式讀取就可以得到ID號。OLED可以看到有2個ID號第一個是F_SIZE表示芯片FLASH容量。0040表示FLASH容量單位是KB換成十進制是64KB。第二個是U_ID是96位芯片唯一ID號每個芯片ID號都不一樣。STM32內部FLASH閃存簡介讀寫FLASH的用途利用程序存儲器的剩余空間來保存掉電不丟失的用戶數據通過在程序中編程IAP實現程序的自我更新第一個用途對于我們這個C8T6芯片來說它的程序存儲器容量是64K一般我們寫個簡單的程序可能就只占前面的很小一部分空間剩下的大片空余空間我們就可以加以利用比如存儲一些我們自定義的數據而且可以充分利用資源。不過這里要注意我們在選取存儲區域時一定不要覆蓋了原有的程序要不然程序自己把自己給破壞了一般存儲少量的參數我們就選最后幾頁存儲就行了、第二個用途通過在程序中編程IAP實現程序的自我更新。我們在存儲用戶數據時要避開程序本身以免破壞程序但如果我們就非要修改程序本身這會發生什么呢在程序中編程利用程序來修改程序本身實現程序的自我更新這個在程序中編程就是IAP是用來實現程序升級的。在線編程 ICP這個JTAG SWD就是仿真器下載程序每次下載都是把整個程序完全更新掉那系統加載程序就是系統存儲器的BOOTLOADER也就是串口下載串口下載也是更新整個程序這就是我們一直在用的ICP下載方式。在程序中編程 IAP它可以使用微控制器支持的任意一種通信接口下載程序。實現過程比如這是整個程序存儲器我們首先需要自己寫一個BOOTLOADER程序并且存放在程序更新時不會覆蓋的地方然后需要更新程序時我們控制程序跳轉到這BOOTLOADER這里來在這里面我們就可以接收任意一種通訊接口傳過來的數據比如串口、USB、藍牙轉串口、WIFI轉串口等等這個傳過來的數據就是待更新的程序然后我們控制flash讀寫把收到的程序寫入到前面程序正常運行的地方寫完之后再控制程序跳轉回正常運行的地方或者直接復位這樣程序就完成了自我升級。區別IAP就是和系統存儲器這個的BOOTLOADER一樣。系統存儲器的BOOTLOADER只能配置boot引腳觸發啟動。而我們自己寫BOOTLOADER的話就可以想怎么收怎么收并且在整個升級過程程序都可以自主完成。回顧一下存儲器影像閃存模塊組織C8T6芯片的flash閃存容量是64K屬于中容量產品。這里分為了三個塊第一個是主存儲器也是程序存儲器用來存放程序代碼的這是最主要也是容量最大的一塊。第二個是信息塊里面又可以分為啟動程序代碼和用戶選擇字節其中啟動程序代碼就是系統存儲器存放的是原廠寫入BOOTLOADER用于串口下載。第三塊是閃存存儲器接口寄存器這一塊的存儲器實際上并不屬于閃存地址都是40開頭的說明這個存儲器接口寄存器就是一個普通的外設和之前講的GPIO定時器、串口等等都是一個性質的東西這些存儲器它們的存儲介質也都是SRAM。這個閃存存儲器接口寄存器就上面主存儲器和信息塊的管理員閃存存儲器接口寄存器就是用來控制擦除和編程這個過程的。對于主存儲器這里對它進行了分頁1024byte 0x400byte,進制不同分頁是為了更好的管理閃存擦除和寫保護都是以頁為單位的。這點和之前W25Q64芯片的閃存一樣寫入前必須擦除擦除必須以最小單位進行擦除后數據位全變為1數據只能1寫0不能0寫1擦除和寫入之后都需要等待忙這些都是一樣的。這里就比較簡單了它只有一個基本單位就是頁每一頁的大小都是1K0到127總共128頁總量就是128K對于C8T6來說它只有64K所以C8T6的頁只有一半0~63總共64頁共64K然后看一下頁的地址范圍。所以地址只要以000、400、800、400結尾的都一定是頁的起始地址。FLASH基本結構整個閃存分為程序存儲器、系統存儲器和選項字節三部分這里程序存儲器為以C8T6為例它是64K的所以總共只有64頁最后一頁的起始地址是0800FC00。左邊這里是閃存存儲器接口手冊里還有個名稱閃存編程和擦除控制器LPEC。然后閃存存儲器接口可以對程序存儲器進行擦除和編程也可以對選項字節進行擦除和編程系統存儲器是不能擦除和編程的。這個選項字節里面有很大一部分配置位其實是配置主程序存儲器的讀寫保護的所以右邊畫的寫入選項字節可以配置程序存儲器的讀寫保護。如何操作這個控制器FPEC來對程序存儲器和選項字節進行擦除和編程。FLASH解鎖首先第一步是flash解鎖flash操作之前需要解鎖目的都是為了防止誤操作是通過在鍵寄存器寫入指定的鍵值來實現使用鍵寄存容器的好處就是更能防止誤操作每一個指令必須輸密碼才能完成叫密鑰寄存器。首先FPEC共有三個鍵值也就是三把開鎖的鑰匙RDPRT鍵是解除讀保護的密鑰值是0XA5實際上是隨便定義的只要你定義的不是很簡單就行。解鎖第一個是復位后FPEC被保護不能寫入FLASH_CR也就是復位后flash默認是鎖著的。在FLASH_KEYR鍵寄存器中先寫入KEY1再寫入KEY2解鎖這個鎖是KEYR寄存器所以這個有兩道鎖解鎖的話要先用K1鑰匙解再用K2鑰匙解最終才能解鎖成功所以非人為情況下基本不可能解鎖。然后就是錯誤的操作序列會在下次復位前鎖死FPEC和FLASH_CR于是他發現有程序在嘗試撬鎖時一旦沒有先寫入KEY1再寫入KEY2整個模塊就會完全鎖死除非復位這是整個解鎖操作。加鎖我們操作完成之后要盡快把flash重新加鎖以防止意外情況加鎖的操作是設置FLASH_CR中的LOCK位鎖住FPEC和FLASH_CR就是控制寄存器里面有個LOCK位我們在這一位寫1就能重新鎖住閃存。使用指針訪問存儲器uint16_t Data *((__IO uint16_t *)(0x08000000));第一步讀取給定存儲器器的地址比如0x08000000例讀取這個地址下的數據。第二步在地址前面加上強制類型轉換轉換成uint16_t * 。__IO 在stm32庫函數中這是宏定義。#define __IO volatile這個宏定義對應C語言關鍵字 volatile。在uint16_t *數據類型前加volatile起一個保障作用目的是防止編譯器優化。第三步使用*號指針取內容把這個指針指向的存儲器取出來了這個值就是指定存儲器的值取出來可以把它賦值給自定義變量Data這樣就完成指定地址讀的任務。如果你這個地址寫的是SRAM的地址比如0X20000000那可以直接寫入了因為SRAM在程序運行時是可讀可寫的這是使用指針訪問存儲器的C語言代碼。其中讀取可以直接讀寫入需要解鎖并且執行后面的流程。程序存儲器全擦除第一步是讀取lock位看一下芯片鎖沒鎖如果lock位1鎖住了就執行解鎖過程。解鎖過程就是在KEYR寄存器先寫入KEY1再寫入KEY2如果lock位0當前沒鎖住就不用解鎖了。這是流程圖里給的解鎖步驟如果鎖住了就解鎖如果沒鎖住就不用解鎖。但是在庫函數中并沒有這個判斷庫函數是直接執行解鎖過程管你鎖沒鎖都執行解鎖。第二步然后繼續解鎖之后首先置控制寄存器里的MER(Mass Erase)位為1然后再置STRT(Start)位為1。其中STRT為1是觸發條件STRT為1之后芯片開始干活然后現在看到MER位是1它就知道接下來要干的活就是全擦除這樣內部電路就會自動執行全擦除的過程。第三步然后繼續擦除擦除過程開始后程序要執行等待。判斷狀態寄存器的BSY(Busy)位是否為1BSY位表示芯片是否處于忙狀態BSY位為1表示芯片忙所以這里如果判斷BSY位等于1就跳轉回來繼續循環判斷直到BSY位0跳出循環。第四步讀出并驗證所有頁的數據這個是測試程序才要做的如要全讀出來驗證一下這個工作量太大了所以這里的最后一步就不管了正常情況下全刪除完成了我們默認就成功了這是全擦除的流程。程序存儲器頁擦除第一步是解鎖的流程同上。第二步這個方框里的置控制寄存器的PER(Page Erase)位為1在FLASH_AR(Address Register)地址寄存器中選擇要擦除的頁最后置控制寄存器的STRT位為1置STRT位為1也是觸發條件芯片開始干活然后芯片看到PER等于1它就知道接下來要執行頁擦除。然后閃存不止一頁頁擦除芯片就要知道要具體擦哪一頁所以它會繼續看AR寄存器的數據AR寄存器為提前寫入一個頁的起始地址這樣芯片就會把我們指定的一頁給擦除掉。第三步然后擦除開始之后我們也要等待BSY位最后讀出并驗證數據。程序存儲器編程閃存的寫入閃存的寫入擦除之后我們就可以執行寫入的流程了。另外說明一下STM32的閃存在寫入之前會檢查指定地址有沒有擦除如果沒有擦除就寫入STM32則不執行寫入操作除非寫入的全是0這個數據是例外因為不擦除就寫入可能會寫入錯誤。第一步是解鎖。第二步置控制寄存器的PG(Programming)位為1表示我們即將寫入數據。第三步在指定的地址寫入半字這一步我們需要*((__IO uint16_t *)(0x08000000)) 0x1234使用指針在指定地址寫入數據。注意寫入操作只能以半字的形式寫入在STM32中有幾個術語字、半字和字節其中字word就是32位數據半字half word就是16位數據字節byte就是8位數據。那這里只能以半字寫入意思就是只能以16位的形式寫入一次性寫入兩個字節如果你要寫入32位就分兩次完成。如果你只要寫入8位比較麻煩了如果你想單獨寫入一個字節還要保留另一個字節的原始數據的話那只能把整頁數據都讀到SRAM再隨意修改SRAM數據修改全部完成之后再把整頁都擦除最后再把整頁都寫回去。所以如果你想像SRAM一樣隨心所欲的讀寫那最好的辦法就先把閃存的一頁讀到SRAM中讀寫完成后再擦除一頁整體寫回去。第四步寫了半字之后芯片會處于忙狀態我們等待一下BUSY清0這樣寫入數據的過程就完成。那每執行這樣一個流程只能寫入一個半字如果要寫出很多數據要不斷循環調用這個流程就可以。選項字節圖里的起始地址就是選項字節的起始地址1FFF800這塊的這些數據就前面這里這個表的這一行里面總共只有16個字節把這些存儲器給展開就這個圖。這里是對應的16個字節其中有一半的名稱前面都帶了個N比如RDP和nRDPUSER和nUSER等意思是你在寫入RDP數據時要同時在NRDP寫入數據的反碼要在帶n的對應的存儲器寫入反碼這樣寫入操作才是有效的。如果芯片檢測到這兩個存儲器不是反碼的關系那就代表數據無效有錯誤對應的功能就不執行這是一個安全保障措施。但這個寫入反碼的過程硬件會自動計算并寫入。那然后每個存儲器的功能去掉所有帶n的剩下八個字節存儲器第一個RDP(Read Protect)讀保護配置位解釋在RDP存儲器寫入RDPRT鍵然后解除讀保護如果RDP不是A5那閃存就是讀保護狀態無法通過調試器讀取程序避免程序被別人竊取。第二個字節USER可以配置硬件看門狗和進入停機待機模式是否產生復位。第三個和第四個字節Data0/1這個在芯片中沒有定義功能用戶可自定義使用。最后四個字節WRP(WriteProtect)0、1、2、3這四個字節配置的是寫保護在中容量產品里是每一個位對應保護四個存儲頁四個字節總共32位1bit對應保護4頁總共保護32×4等于128頁正好對應中容量量的最大128頁。小容量產品手冊2.5選項字節說明對于小容量產品也是每一位對應保護四個存儲頁但小容量產品最大只有32K所以只需要一個字節WRP0就行4×832其他三個字節沒用到。大容量產品然而對于大容量產品每一個位只能保護兩個存儲頁這樣的話四個字節就不夠用了所以這里規定WRP3的最高位這一位直接把剩下的所有頁一起都保護了這是寫保護的定義。選項字節擦除選項字節擦除第一步其實也是解鎖閃存這里文字并沒有寫。第二步這里文字版的流程多了一步檢查FLASH_SR寄存器的BSY位以確認沒有其他正在進行的閃存操作這個實際上就是事前等待如果當前已經在忙了我先等一下。第三步解鎖FLASH_CR寄存器的OPTWRE(Option Write Enable)位這一步是選項字節的解鎖選項字節里面還有一個單獨的鎖在解鎖閃存后還需要再解鎖選項字節的鎖之后才能操作選項字節。解鎖選項字節看(前面閃存模塊組織圖)整個閃存的鎖是KEYR里面選項字節的小鎖是下面的OPTKEYR(Option Key Register)。解鎖這個小鎖也是類似的流程我們需要在OPTKEYR里先寫入KEY1再寫入KEY2這樣就能解鎖選項字節的小鎖了。第四步繼續解除小鎖之后設置FLASH_CR寄存器的OPTER(Option Erase)位為1表示即將擦除選項字節。第五步設置FLASH_CR寄存器的STRT位為1觸發芯片開始干活這樣芯片就會啟動擦除選項字節的工作。第六步之后等待BUSY位變為0擦除選項字節就完成了。選項字節編程先檢測FLASH_SR寄存器的BSY然后解除小鎖之后設置FLASH_CR寄存器的OPTPG(Option Programming)位為1表示即將寫入選項字節再之后寫入要編程的半字到指定的地址這個是指針寫入操作最后等待忙這樣寫入選項字節就完成了。器件電子簽名電子簽名其實就是STM32的ID號它的存放區域是系統存儲器不僅有BOOTLOADER程序還有幾個字節的ID號系統存儲器起始地址是1FFFF000。第一個是閃存容量存儲器基地址是1FFFF7E0通過地址也可以確定它的位置就是系統存儲器這個存儲器的大小是16位它的值就是閃存的容量單位是KB。第二個是產品唯一身份標識寄存器就是每個芯片的身份證號這個數據存放的基地址是1FFFF7E8大小是96位每一個芯片的這96位數據都是不一樣的。使用這個唯一ID號可以做一些加密的操作比如你想寫入一段程序只能在指定設備運行那也可以在程序的多處加入ID號判斷如果不是指定設備的ID號就不執行程序功能。這樣即使你的程序被盜在別的設備上也難以運行這是STM32的電子簽名。閃存編程手冊在編程過程中任何讀寫閃存的操作都會使CPU暫停直到此閃存編程結束。這是讀寫內部閃存存儲數據的一個弊端忙的時候代碼執行會暫停因為執行代碼需要讀閃存閃存在忙沒法讀所以CPU也就沒法運行了程序就會暫停。這會導致假如你使用內部閃存存儲數據同時你的中斷代碼又在頻繁執行這樣讀寫閃存的時候中斷代碼就無法執行了這可能會導致中斷無法及時響應。選項字節編程閃存控制寄存器FLASH_CR原文鏈接https://blog.csdn.net/m0_62005595/article/details/139897394