由於項目須要使用IAP進行固件更新,因而個人芯片FLASH須要劃分爲四段:安全
- 一段Boot loader 用以判斷上電後進入哪一段APP
- APP1程序
- APP2程序
- 配置文件ID_card
由於程序更新採用的是末尾淘汰,即進入程序後,判斷APP1.2哪個是完整的,在完整的同時判斷那一段APP版本更加高就運行哪一段APP。因此我須要一段保存配置,用來記錄APP1和APP2的數據信息,即程序APP的ID_card。那麼除去APP的擦寫不說,對於配置文件,也須要進行頻繁的FLASH擦寫操做。函數
我使用的單片機是STM32F429ZIT6,因而我去查看了429的FLASH區域介紹。
你們能夠看到, STM32F4系列和F1,F3的FLASH劃分不一樣。咱們都知道F1系列的FLASH劃分是從0x0800 0000地址開始,對於小容量的進行1kb一頁,對於大容量的2kb一頁進行劃分的。而在F4中進行了升級,以我使用的STM32F429ZIT6爲例,2M大小按照容量先進行了塊1和塊2劃分,即程序中常常看到的關鍵字Bank1和Bank2。在每一個Bank中,又以扇區劃分爲16kb的扇區4個,64kb扇區1個,128kb扇區7個,共計大小1M。
測試
理論如上,說幹就幹。因而用STM32CubeMX生成驅動,配置時間樹,調試串口打印……
一系列猛如虎的操做事後。程序寫好了以下圖所示。
指針
以上是main.h中的聲明,以及我對程序位置的一些把控。能夠看到我把ID_card的位置放在了塊1的扇區2位置。由於單片機運行之後都是從0x0800 0000位置開始,因此前兩頁32kb大小用來存放Bootloader。緊跟着扇區2位置即0x0800 8000位置的一個扇區用來存放ID_card配置信息。
這是程序初始化後進入的demo循環讀寫測試程序。流程以下:
調試
- 解鎖FLASH
- 清除一系列標誌位,這一條能夠不要,可是爲了確保成功以及排除一切障礙,手動將他所有清除,加大代碼的安全性。
- 配置擦除FLASH的結構體包括擦除的方式,擦除的地址,擦除的大小,擦除的電壓。
- 執行HAL_FLASHx_Erase函數進行擦除。
- 執行HAL_FLASH_Program對擦除區域寫入新的數值。
- 打印判斷是否成功。
- FLASH上鎖。
這裏說一下,我在以前有對指針變量賦值地址,如圖:
即將ID_card的指針地址指向0x0800 8000的位置。
blog
另外說一下,不建議你們循環擦寫FLASH,由於FLASH是有擦除次數限制的,在循環中擦FLASH會致使FLASH到達上限後沒法擦除,讀沒有限制。擦除結構體中VoltageRange參數是能夠配置擦除電壓,從而影響擦除的大小是多少,這裏採用32bit一擦。不建議採用64bit擦除,雖然速度會快可是影響芯片FLASH壽命。
固然以上都是個人逼逼賴賴,我本身也循環擦了,固然這只是demo測試用法。
圖片
好,一切準備就緒,開始大刀闊斧的跑程序了,看了黃曆今天適合代碼測試,若是我運氣足夠好,我立刻就能夠下班了。然而,,,我裂開了。
什麼狀況???除了上電第一次按照個人邏輯正常寫入之外,第二次就跑飛了。尼瑪!!!STM32你已是一個成熟的芯片了,要學會看懂開發者的意思,本身跑起來。不要讓我加班和掉頭髮。
開發
好,口嗨事後,冷靜思考。
咱們都知道STM32的FLASH數據分佈是沒有數據默認全都是1。即擦除之後,應該全部位都是1。我按照4字節一個數據,那麼擦除後應該是32位1即0xFFFFFFFF纔對。寫入數聽說明有的位置變爲0了。而從第一次擦除咱們能夠看的到全都是1,寫入數據以前是沒有問題。這說明咱們的寫入數據的函數是沒有問題的,並且第一次寫入以前也進行了擦除,而數據沒有改變。是在咱們寫入了數據或者是現有數據的狀況下擦除出現了錯誤,以後的打印數據所有改成了0,正常的擦除應該是1因此能夠判定是擦除函數有問題。
it
因而開始大量掉髮,瘋狂找資料。參考了野火和原子的標準庫例程,發現讀寫沒有問題。參考了ST的HAL庫例程也沒有問題。發現他們都用了一個GetSector獲取地址所在扇區的函數。而這個函數的調用是直接獲取函數擦除的位置。根據一步步goto,goto,goto後。我終於找到了問題所在。class
F4的擦除函數不一樣於F1和F3的擦除函數,雖然名字和結構體在hal庫中仍然同樣。可是F4中的起始地址,已經改成扇區的宏定義了。而個人這些代碼,均是從我以前項目F373的程序中移植過來的。在373和103中,他的擦除頁面起始位置均是地址。而我直接移植後沒有由於名字沒有變化因此我仍然覺得是地址。而實際上應該是扇區的扇區碼,在相關宏定義中能夠找到。
修改事後的程序以下所示:
調用之後發現:
AMAZING!!!成功完成擦讀寫的操做後。我感受本身已經站在人生巔峯而且那是一個舉止從容,行雲流水,一頓操做猛如虎,一路火花帶閃電,狂拽酷炫吊炸天,我就是那個站在宇宙巔峯的男人啊。
又是一段口嗨之後插一段簡短的總結:
- 在STM32中對FLASH的操做能夠分爲三種:擦,讀,寫。其中擦和寫須要解鎖FLASH,同時用完後須要上鎖FLASH。
- 每當要寫數據以前,必定要執行擦除這個頁面。同時,F4中擦除頁面最小也是16kb一擦,因此注意必定要確保扇區沒有任何程序以及數據,實在不行,先所有讀取出來,擦除後再總體寫入。固然這有必定的代碼風險(讀取後,在擦除時斷電,會致使在讀取在ROM裏的數據所有丟失)
- 這裏以429ZI爲例,在讀寫其餘芯片FLASH的時候,也須要對FLASH的存儲空間分佈進行了解,最起碼F1和F4的就有很大不一樣。
最後特別感謝@ tyustli 朋友給個人一些提示和幫助。
而後看了一下表,臥槽25點01分了,趕忙下班。回頭瞟了一眼我桌子上那些黑色的頭髮,我知道那是我逝去的青春。