STM32的Flash
生活随笔
收集整理的這篇文章主要介紹了
STM32的Flash
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
STM32中存儲區分為:隨機存取存儲器RAM和只讀存儲器ROM。?
其中:
- RAM為常說的內存,比如手機的2G內存4G內存等,就是程序跑起來的時候所占用的存儲空間,特點是掉電數據丟失。
- ROM為常說的硬盤,比如手機的64G和128G等,可以簡單的理解為硬盤的存儲空間,特點是掉電數據不丟失,所以又叫“非易失性存儲器件”。?
- ROM又包含:EEPROM和flash。
畫個嵌入式產品存儲器件的思維導圖如下(如有什么地方不對,懇請大神們進行指正):?
作為ROM的一份子,flash的特點自然是掉電數據不丟失。但是,flash在STM32中比較重要,程序也是保存在這個地方,所以輕易不讓用戶進行隨意的讀寫,以避免不必要的問題。
而這篇博客就先簡單記錄一下flash的訪問流程和方法(讀和寫),具體原理以后理解深刻了再做補充。
1、STM32 FLASH操作流程
Flash操作已經屬于嵌入式設備中很底層的操作了,直接對地址進行存取,簡單描述,Flash操作大致需要以下流程:
- 1、確定要寫入Flash的首地址(稍后介紹確定地址的方法)
- 2、解鎖Flash
- 3、對Flash進行操作(寫入數據)
- 4、對Flash重新上鎖
1.1 如何查找并選定要寫入Flash十六進制地址值的方法
要想選定安全的Flash地址進行讀寫,可以根據自己的STM32 MCU型號,查找數據手冊,確定FLASH的地址區段,因為起始段會存儲代碼,所以一定要避開起始段,以避免數據錯誤。(我一般是根據Flash大小計算Flash的最末尾地址,往前推一段地址空間,在這里一般不會對代碼中的數據產生覆蓋等影響)
我此次操作Flash使用的MCU是STM32103C8T6,所以以該型號MCU為例進行描述:
- 在數據手冊中,可以看到STM32103C8T6的flash起始地址是0x0800 0000(如下圖所示),而STM32103C8T6的Flash大小為64K,可以計算出STM32103C8T6的Flash地址范圍是:0x0800 0000——0x0800 FFFF(計算方法參考另一篇博客:STM32內存大小與地址的對應關系以及計算方法)。這里選取0x0800 F000作為讀寫操作的起始地址,對于C8T6這款MCU,操作這個起始地址應該算是很安全的范圍了。?
2、Flash基本知識點
2.1 Flash容量
Flash根據容量大小可以分為以下三種:
- 1、小容量產品:Flash大小為1-32KB(STM32F10X_LD)
- 2、中容量產品:Flash大小為64-128KB(STM32F10X_MD)
- 3、大容量產品:Flash大小為256KB以上(STM32F10X_HD)
2.2 ST庫對Flash操作的支持
ST庫中對Flash操作主要提供了以下幾類操作API函數:
- 1、Flash解鎖、鎖定函數?
- void FLASH_Unlock(void);//解鎖函數:在對Flash操作之前必須解鎖
- void FLASH_Lock(void);//鎖定函數:同理,操作完Flash之后必須重新上鎖
- 2、Flash寫操作函數?
- FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);//32位字寫入函數
- FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);//16位半字寫入函數
- FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);//用戶選擇字節寫入函數?
注:這里需要說明,32 位字節寫入實際上是寫入的兩次 16 位數據,寫完第一次后地址+2,這與我們前面講解的 STM32 閃存的編程每次必須寫入 16 位并不矛盾。寫入 8位實際也是占用的兩個地址了,跟寫入 16 位基本上沒啥區別。
- 3、Flash擦除函數?
- FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
- FLASH_Status FLASH_EraseAllPages(void);
- FLASH_Status FLASH_EraseOptionBytes(void);
- 4、獲取Flash狀態?
- FLASH_Status FLASH_GetStatus(void);?
獲取Flash狀態函數,主要是為了獲取Flash的狀態,以便于根據狀態對Flash進行操作。該函數返回值是通過枚舉類型定義的,在代碼中可以看到FLASH_Status類型定義如下(具體含義看注釋即可): - ?????????????????????????????????????????????????typedef enum?
?????????????????????????????????????????????????{?
????????????????????????????????????????????????? FLASH_BUSY = 1, ???????//忙?
????????????????????????????????????????????????? FLASH_ERROR_PG, ?????//編程錯誤?
????????????????????????????????????????????????? FLASH_ERROR_WRP,?? //寫保護錯誤?
????????????????????????????????????????????????? FLASH_COMPLETE, ?????//操作完成?
????????????????????????????????????????????????? FLASH_TIMEOUT ????????//操作超時?
????????????????????????????????????????????????? }FLASH_Status;
- FLASH_Status FLASH_GetStatus(void);?
- 5、等待操作完成函數?
- FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);?
注:在執行閃存寫操作時,任何對閃存的讀操作都會鎖住總線,在寫操作完成后讀操作才能正確地進行;既在進行寫或擦除操作時,不能進行代碼或數據的讀取操作。所以在每次操作之前,我們都要等待上一次操作完成這次操作才能開始。
- FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);?
3、OK,上干貨,上代碼
根據ST庫提供的上述函數,我們可以自己編寫Flash的讀寫操作代碼如下:
3.1 先定義一個Flash操作的起始地址宏定義和Flash狀態指示標志位
#define STARTADDR 0x0800F000 //STM32F103C8T6適用volatile FLASH_Status FLASHStatus = FLASH_BUSY; //Flash操作狀態變量?
3.2 編寫各個讀寫函數
// // Name: WriteFlashOneWord // // Function: 向內部Flash寫入32位數據 // // Input: WriteAddress:數據要寫入的目標地址(偏移地址) // WriteData: 寫入的數據 // void WriteFlashOneWord(uint32_t WriteAddress, uint32_t WriteData) { FLASH_UnlockBank1();FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);FLASHStatus = 1; //清空狀態指示標志位FLASHStatus = FLASH_ErasePage(STARTADDR); if(FLASHStatus == FLASH_COMPLETE) { FLASHStatus = 1; //清空狀態指示標志位FLASHStatus = FLASH_ProgramWord(STARTADDR+WriteAddress, WriteData); //flash.c 中API函數}FLASHStatus = 1; //清空狀態指示標志位FLASH_LockBank1(); }// // Name: WriteFlashData // // Function: 向內部Flash寫入數據 // // Input: WriteAddress:數據要寫入的目標地址(偏移地址) // data[]: 寫入的數據首地址 // num: 寫入數據的個數 // void WriteFlashData(uint32_t WriteAddress, uint8_t data[], uint32_t num) {uint32_t i = 0;uint16_t temp = 0;FLASH_UnlockBank1(); //解鎖flashFLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASHStatus = 1; //清空狀態指示標志位FLASHStatus = FLASH_ErasePage(STARTADDR);//擦除整頁if(FLASHStatus == FLASH_COMPLETE)//flash操作完成{FLASHStatus = 1; //清空狀態指示標志位for(i=0; i<num; i++){temp = (uint16_t)data[i];FLASHStatus = FLASH_ProgramHalfWord(STARTADDR+WriteAddress+i*2, temp);//寫入數據}}FLASHStatus = 1; //清空狀態指示標志位FLASH_LockBank1(); //鎖定flash }// // Name: ReadFlashNBtye // // Function: 從內部Flash讀取N字節數據 // // Input: ReadAddress:數據地址(偏移地址) // ReadBuf:讀取到的數據存放位置指針 // ReadNum:讀取字節個數 // // Output: 讀取的字節數 // int ReadFlashNBtye(uint32_t ReadAddress, uint8_t *ReadBuf, int32_t ReadNum) { int DataNum = 0;ReadAddress = (uint32_t)STARTADDR + ReadAddress; while(DataNum < ReadNum) { *(ReadBuf + DataNum) = *(__IO uint8_t*) ReadAddress++; DataNum++; }return DataNum; }// // Name: ReadFlashData // // Function: 從內部Flash讀取num字節數據 // // Input: ReadAddress:數據地址(偏移地址) // dest_Data: 讀取到的數據存放位置指針 // num: 讀取字節個數 // void ReadFlashData(uint32_t ReadAddress, uint8_t *dest_Data, uint32_t num) {int i = 0;ReadAddress = (uint32_t)STARTADDR + ReadAddress; while(i < num) {*(dest_Data+i) = *(__IO uint16_t*) ReadAddress;ReadAddress += 2;i++;} }來源:https://blog.csdn.net/Ace_Shiyuan/article/details/78196648
總結
以上是生活随笔為你收集整理的STM32的Flash的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity3D 飞碟游戏改进版
- 下一篇: 用什么软件测试mate9的闪存_荣耀v9