Flash 中文名字叫閃存,是一種長壽命的非易失性(斷電數據不丟失)的存儲器。可以對稱為塊的存儲器單元塊進行擦寫和再編程,在進行寫入操作之前必須先執行擦除。一個Nand Flash由多個塊(Block)組成,每個塊里面又包含很多頁(page)。每個頁對應一個空閑區域/冗余區域(spare area),這個區域不是用來存儲數據的,用於放置數據的校驗值檢測和糾錯的。塊,是Nand Flash的擦除操作的基本/最小單位。頁,是Nand Flash的寫入操作的基本/最小的單位。
首先簡要寫一下FLASH的讀寫流程:
對FLASH寫入數據
解鎖FLASH
擦除FLASH
寫入數據到FLASH
鎖住FLASH
FLASH讀取數據 (直接讀取相應的FLASH地址即可)
操作MCU里的Flash,還有幾個注意事項:
1、往Flash寫入數據的時候,要先對要寫入的頁進行擦除,如果要寫的頁里有數據,要先讀出來在緩存區,再把頁擦除,再寫入數據;在擦除頁之后,只要這次你寫的數據大小不夠一頁,可以連續寫入。
2、要計算好程序的內存,因為你的程序也是保存在MCU的Flash里的,如果你操作到保存着程序的內存,程序就會死掉,至於程序內存怎么看,你可以生成bin文件,bin文件的大小就是你程序所占內存的大小了,生成bin文件可以參考博客:https://www.cnblogs.com/xingboy/p/10818813.html;程序內存基本都是從Flash內存一開始存起的,這里以STM32Fo72c8t6舉例,如下圖。
看圖可以看出,這個芯片的Flash內存范圍是 0x0800 0000 ~ 0x0802 0000 ,假設我要燒錄進去的bin文件為10K,那我們操作Flash的時候,地址就要從 0x0800 0000 + (0x400*11) 開始,避開程序的存儲位置,Flash地址偏移1位就是1個字節。
3、要注意MCU一頁的大小,一些MCU一頁是1KB,一些MCU一頁是2KB
下面舉個例子寫入數據 0x0001 到Flash中:
uint16_t my_add = 0x0001;
uint32_t Robot_Num_Flash_Add = 0x08005000;
FLASH_EraseInitTypeDef My_Flash; //聲明 FLASH_EraseInitTypeDef 結構體為 My_Flash HAL_FLASH_Unlock(); //解鎖Flash My_Flash.TypeErase = FLASH_TYPEERASE_PAGES; //標明Flash執行頁面只做擦除操作 My_Flash.PageAddress = Robot_Num_Flash_Add; //聲明要擦除的地址 My_Flash.NbPages = 1; //說明要擦除的頁數,此參數必須是Min_Data = 1和Max_Data =(最大頁數-初始頁的值)之間的值 uint32_t PageError = 0; //設置PageError,如果出現錯誤這個變量會被設置為出錯的FLASH地址 HAL_FLASHEx_Erase(&My_Flash, &PageError); //調用擦除函數擦除 uint16_t Write_Flash_Data = my_add; HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Robot_Num_Flash_Add, Write_Flash_Data); //對Flash進行燒寫,FLASH_TYPEPROGRAM_HALFWORD 聲明操作的Flash地址的16位的,此外還有32位跟64位的操作,自行翻查HAL庫的定義即可 HAL_FLASH_Lock(); //鎖住Flash
寫完之后,接着就到讀了,Flash寫有次數限制,寫的次數在1W次還是10W次(忘了)就不可寫入了,而讀是沒有次數限制的,讀多少次都可以,下面就把寫入到Flash里的數據 0x0001 讀出來
uint32_t Robot_Num_Flash_Add = 0x08005000;
ID_Num = *(__IO uint16_t*)( Robot_Num_Flash_Add ); //*(__IO uint16_t *)是讀取該地址的參數值,其值為16位數據,一次讀取兩個字節,*(__IO uint32_t *)就一次讀4個字節
printf("ID_num:0x%x\r\n", ID_Num);
經過上面的程序就可以實現 STM32 中 Flash 數據的讀寫了,具體怎么讀寫,每個案子不同,各位就可以根據需求去修改,只要注意好注意事項即可,代碼已經實測可用。