STM32(二十五)讀寫內部flash


一、內部flash簡介

  • STM32 芯片內部有一個 FLASH 存儲器,它主要用於存儲代碼 。
  • 我們在電腦上編寫好應用程序后,使用下載器把編譯后的代碼文件燒錄到該內部 FLASH 中 。
  • FLASH 儲器的內容在掉電后不會丟失,芯片重新上電復位后,內核可從內部 FLASH 中加載代碼並運行。  
  • 訪問內部flash的速度比外部的SPI-Flash要快。
  • flash擦除時是按扇區擦除,使用電擦除,設備電壓1.8V ~2.1V按字節(8bit)擦除,2.1V ~2.7V擦除半字(16bit),2.7V ~ 3.6V擦除一個字(32bit)

           2.7V to 3.6V +外部電壓擦除兩個字(64bit),

二、內部flash的構成

  STM32 的內部 FLASH 包含主存儲器系統存儲器以及選項字節區域,它們的地址分布及大小見下表。

 

 1、主存儲器
  • 一般我們說STM32內部FLASH的時候,都是指這個主存儲器區域,它是存儲用戶應用程序的空間,芯片型號說明中的256K FLASH、512K FLASH都是指這個區域的大小。
  • 主存儲器分為256頁,每須大小為2KB,共512KB。這個分頁的概念,實質就是FLASH存儲器的扇區,與其它FLASH - -樣,在寫入數據前,要先按頁(扇區)擦除。

 

 

 

2、系統存儲區

  系統存儲區是用戶不能訪問的區域,它在芯片出廠時已經固化了啟動代碼,它負實現串口、 USB 以及 CAN ISP 燒錄功能。 

3、選項字節

  選項字節用於配置 FLASH 的讀寫保護、待機/停機復位、軟件/硬件看門狗等功能,這部分共 16 字節。可以通過修改 FLASH 的選項控制寄存器修改。 

三、對內部flash的寫入過程

1.解鎖

  由於內部FLASH空間主要存儲的是應用程序,是非常關鍵的數據,為了防止誤操作修改了這些內容,芯片復位后默認會給控制寄存器FLASH _CR上鎖,這個時候不允許設置FLASH的控制寄存器,從而不能修改FLASH中的內容。所以對FLASH寫入數據前,需要先給它解鎖。解鎖的操作步驟如下:

(1) 往FPEC鍵寄存器FLASH_ KEYR中寫入KEY1 = 0x45670123

(2)再往FPEC鍵寄存器FLASH_ KEYR中寫入KEY2 = 0xCDEF89AB

2.頁擦除.

  在寫入新的數據前,需要先擦除存儲區域,STM32提供了頁(扇區)擦除指令和整個FLASH擦除(批量擦除)的指令,批量擦除指令僅針對主存儲區。頁擦除的過程如下:

  (1) 檢查FLASH_ SR寄存器中的“忙碌寄存器位BSY”,以確認當前未執行任何Flash操作;

  (2)在FLASH_ CR寄存器中,將“激活頁擦除寄存器位PER”置1。

  (3)用FLASHAR寄存器選擇要擦除的頁;

  (4) 將FLASH _CR寄存器中的“開始擦除寄存器位STRT"置1,開始擦除;

  (5)等待BSY位被清零時,表示擦除完成。

3.寫入數據

  擦除完畢后即可寫入數據,寫入數據的過程並不是僅僅使用指針向地址賦值,賦值前還還需要配置一-系列的寄存器,步驟如下:

  (1) 檢查FLASH_ SR中的BSY位,以確認當前未執行任何其它的內部Flash操作;

  (2) 將FLASH_ CR寄存器中的“激活編程寄存器位PG”置1;

  (3)向指定的FLASH存儲器地址執行數據寫入操作,每次只能以16位的方式寫入;

  (4)等待 BSY位被清零時,表示寫入完成。

/**
  * @brief  InternalFlash_Test,對內部FLASH進行讀寫測試
  * @param  None
  * @retval None
  */
int InternalFlash_Test(void)
{
	uint32_t EraseCounter = 0x00; 	//記錄要擦除多少頁
	uint32_t Address = 0x00;				//記錄寫入的地址
	uint32_t Data = 0x3210ABCD;			//記錄寫入的數據
	uint32_t NbrOfPage = 0x00;			//記錄寫入多少頁
	
	FLASH_Status FLASHStatus = FLASH_COMPLETE; //記錄每次擦除的結果	
	TestStatus MemoryProgramStatus = PASSED;//記錄整個測試結果
	

  /* 解鎖 */
  FLASH_Unlock();

  /* 計算要擦除多少頁 */
  NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;

  /* 清空所有標志位 */
  FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);	

  /* 按頁擦除*/
  for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
  {
    FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
  
	}
  
  /* 向內部FLASH寫入數據 */
  Address = WRITE_START_ADDR;

  while((Address < WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
  {
    FLASHStatus = FLASH_ProgramWord(Address, Data);
    Address = Address + 4;
  }

  FLASH_Lock();
  
  /* 檢查寫入的數據是否正確 */
  Address = WRITE_START_ADDR;

  while((Address < WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
  {
    if((*(__IO uint32_t*) Address) != Data)
    {
      MemoryProgramStatus = FAILED;
    }
    Address += 4;
  }
	return MemoryProgramStatus;
}

  

思考題1flash擦除完之后,扇區里面所有的數據是什么?

  :所有的數據都是為0xFF,所有bit位都是1。
0

思考題2假如說現在已經擦除完扇區,先寫入了1個字,然后在下一個偏移地址再次寫入新的字是否在需要擦除扇區?

  答案:不需要的。

思考題3:假如說現在已經擦除完扇區,先寫了1個字,然后在同一個地址再次寫入新的字是否需要擦除扇區?

  答案:需要進行擦除!
例子,已經寫入數據為0x12345678,然后再寫入新的數據為0x1111111,最后得到的數據居然是0x101010.
0

總結:

  判斷是否允許寫入字,只需要判斷當前的地址存儲的數據是否為0xFFFFFFFF,若為0xFFFFFFFF,可以寫入數據,不需要進行扇區擦除。

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM