STM32 Flash詳解

本文將根據ST官方Flashprogramming manual,文檔編號:PM0059,講解STM32F207內部Flash編程。git

0一、概述

這裏的flash是指STM32F207內部集成的Flashgithub

Flash存儲器有如下特色編程

  • 最大1M字節的能力
  • 128位,也就是16字節寬度的數據讀取
  • 字節,半字,字和雙字寫入
  • 扇區擦除和批量擦除

存儲器的構成app

主要存儲區塊包含4個16K字節扇區,1個64K字節扇區和7個128K字節扇區。函數

系統存儲器是用於在系統boot模式啓動設備的。這一塊是預留給ST的。包括bootloader程序,boot程序用於經過如下接口對Flash進行編程。USART一、USART三、CAN二、USB OTG FS設備模式(DFU:設備固件升級)。boot程序由ST製造期間編寫,用於保護防止錯誤寫入和擦除操做。ui

512OTP(一次性編程)字節用於用戶數據。OTP區域包含16個附加的字節,用於鎖定響應的OTP數據。this

選項字節,讀寫保護,BOR水平,軟件/硬件看門狗和復位當設置處於待機和停機狀態。spa

低功耗模式(參考參考手冊的PWR部分)翻譯

對比參考手冊的boot部分debug

當BOOT0爲0是運行主存儲區

當BOOT0爲1,BOOT1爲0時運行系統存儲區

系統存儲區運行的是ST出廠的bootloader代碼,跳過過了用戶的代碼。若是在應用層代碼鎖定了JTAG管腳(將JTAG管腳用於普通GPIO),咱們能夠經過修改boot管腳狀態,進入系統存儲中,再進行debug。

 

0二、Flash操做

2.一、讀取

內置的Flash是處於CortexM3的數據總線上的,因此能夠在通用地址空間之間尋址,任何32位數據的讀操做都能訪問Flash上的數據。

data32 = *(__IO uint32_t*)Address;

將Address強制轉化爲32位整型指針,而後取該指針所指向的地址的值,就獲得了Address地址上的32位數據。

2.二、擦除

Flash 擦除操做可針對扇區或整個Flash(批量擦除)執行。執行批量擦除時,不會影響OTP扇區或配置扇區。

 

扇區擦除步驟

一、檢查FLASH_SR 寄存器中的BSY 位,以確認當前未執行任何Flash 操做

二、在FLASH_CR 寄存器中將SER 位置1 並選擇要擦除的扇區(SNB)(主存儲器塊中的12個扇區之一)

三、將FLASH_CR 寄存器中的STRT 位置1

四、等待BSY 位清零

 

批量擦除步驟

一、檢查FLASH_SR 寄存器中的BSY 位,以確認當前未執行任何Flash 操做

二、將FLASH_CR 寄存器中的MER 位置1

三、將FLASH_CR 寄存器中的STRT 位置1

四、等待BSY 位清零

 

ST提供相應的庫函數接口

FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_tVoltageRange)
FLASH_Status FLASH_EraseAllSectors(uint8_tVoltageRange)

​​​​​​注意到,有個特殊的參數VoltageRange,這是由於

這裏就再也不翻譯了,就是在不一樣電壓下數據訪問的位數不一樣,咱們是3.3V,因此是32位數據,這也就是在讀數據是爲何要讀取32位的緣由。

2.三、寫入

寫入以前必須擦除,這裏和NorFlash操做是相同的

復位後,Flash控制器寄存器(FLASH_CR)不容許寫入的,去保護Flash閃存由於電氣緣由出現的之外操做,如下是解鎖的步驟

一、在Flash 密鑰寄存器(FLASH_KEYR) 中寫入KEY1 = 0x45670123

二、在Flash 密鑰寄存器(FLASH_KEYR) 中寫入KEY2 = 0xCDEF89AB

將FLASH_CR 寄存器中的LOCK 位置爲1 後,可經過軟件再次鎖定FLASH_CR 寄存器

ST提供了庫函數

FLASH_Unlock();//解鎖
FLASH_Lock();//從新上鎖

備註:

當FLASH_SR 寄存器中的BSY 位置爲1 後,將不能在寫模式下訪問FLASH_CR 寄存器。BSY 位置爲1 後,對該寄存器的任何寫操做嘗試都會致使AHB 總線阻塞,直到BSY位清零

這要求咱們在寫入前必須判斷下FLASH_SR寄存器中的BSY位。

ST提供了對用的庫函數

FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR| FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

寫入步驟

一、檢查FLASH_SR 中的BSY 位,以確認當前未執行任何主要Flash 操做

二、將FLASH_CR 寄存器中的PG 位置1。

三、經過不一樣的位寬對指定地址寫入

四、等待BSY 位清零

對於寫入接口,ST提供相應的庫函數,提供了8位,16位,32位的操做,由於咱們是3.3V電壓,因此使用32位寫入接口

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)

2.四、中斷

若是對於寫入要求較高,可使能中斷,對於寫入完成,寫入錯誤都會有響應的中斷響應。我也沒有詳細研究,參看Flash編程手冊的15.5章節

 

0三、Flash保護

3.1概述

Flash具備讀寫保護機制,主要是用過選項地址實現的。還有一次性編程保護

這講述了選項字節的構成

用戶修改選項字節

To run any operation on this sector, the option lock bit (OPTLOCK) inthe Flash option control register (FLASH_OPTCR) must be cleared. Tobe allowed to clear this bit, you have to perform the followingsequence:

1. Write OPTKEY1 = 0x0819 2A3B in the Flash option key register(FLASH_OPTKEYR)

2. Write OPTKEY2 = 0x4C5D 6E7F in the Flash option key register(FLASH_OPTKEYR)

The user option bytes can be protected against unwanted erase/programoperations by setting the OPTLOCK bit by software.

這個上面講述的解鎖Flash相同,就是要寫入不能的數值

ST提供相應的庫函數

void FLASH_OB_Unlock(void)
void FLASH_OB_Lock(void)

修改用戶字節的步驟

一、檢查FLASH_SR 寄存器中的BSY 位,以確認當前未執行任何Flash 操做

二、在FLASH_OPTCR 寄存器中寫入所需的選項值

三、將FLASH_OPTCR 寄存器中的選項啓動位(OPTSTRT) 置1

四、等待BSY 位清零

 

3.2 讀保護

從上面概述中得知,Flash讀保護共分三個等級

 

等級0:沒有保護

將0xAA 寫入讀保護選項字節(RDP) 時,讀保護級別即設爲0。此時,在全部自舉配置(Flash用戶自舉、調試或從RAM 自舉)中,都可執行與Flash 或備份SRAM 相關的全部讀/寫操做(若是未設置寫保護)。

 

等級1:閃存讀保護

這是擦除選項字節後的默認讀保護級別。將任意值(分別用於設置級別0 和級別2 的0xAA和0xCC 除外)寫入RDP 選項字節時,即激活讀保護級別1。設置讀保護級別1 後:

-在鏈接調試功能或從RAM 進行自舉時,將不執行任何Flash 訪問(讀取、擦除和編程)。Flash 讀請求將致使總線錯誤。而在使用Flash 用戶自舉功能或在系統存儲器自舉模式下操做時,則可執行全部操做

-激活級別1 後,若是將保護選項字節(RDP) 編程爲級別0,則將對Flash 和備份SRAM執行批量擦除。所以,在取消讀保護以前,用戶代碼區域會清零。批量擦除操做僅擦除用戶代碼區域。包括寫保護在內的其它選項字節將保持與批量擦除操做前相同。OTP 區域不受批量擦除操做的影響,一樣保持不變。

只有在已激活級別1 並請求級別0 時,纔會執行批量擦除。當提升保護級別(0->1,1->2, 0->2) 時,不會執行批量擦除。

 

等級2:禁止調試/芯片讀保護

注意:

在注意中寫道,若是使能了等級2的讀保護,永久禁止JTAG端口(至關於JTAG熔絲)ST也沒法進行分析,說白了就是沒辦法再debug了,目前我沒有使用到這個水平的讀保護

 

讀保護庫函數

void FLASH_OB_RDPConfig(uint8_t OB_RDP)

查詢讀保護狀態庫函數

FlagStatus FLASH_OB_GetRDP(void)

3.3 寫保護

Flash 中的用戶扇區(0到11)具有寫保護功能,可防止因程序計數器(PC) 跑飛而發生意外的寫操做。當扇區i 中的非寫保護位(nWRPi, 0 ≤ i ≤ 11) 爲低電平時,沒法對扇區i 執行擦除或編程操做。所以,若是某個扇區處於寫保護狀態,則沒法執行批量擦除。

若是嘗試對Flash 中處於寫保護狀態的區域執行擦除/編程操做(由寫保護位保護的扇區、鎖定的OTP 區域或永遠不能執行寫操做的Flash 區域,例如ICP),則FLASH_SR 寄存器中的寫保護錯誤標誌位(WRPERR) 將置1。

寫保護庫函數

void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState)

查詢寫保護狀態庫函數

uint16_t FLASH_OB_GetWRP(void)

0四、一次性可編程字節

沒有使用過,使用了芯片就廢了吧,沒有作過這個等級等保護,能夠參看Flash編程手冊的2.7章節

0五、代碼

關於讀寫保護代碼如何調用的問題,在stm32f2xx_flash.c文件中有調用說明.​​​​​。

/** @defgroup FLASH_Group3 Option Bytes Programming functions
 *  @brief   Option Bytes Programming functions 
 *
@verbatim   
 ===============================================================================
                        Option Bytes Programming functions
 ===============================================================================  
 
   This group includes the following functions:
   - void FLASH_OB_Unlock(void)
   - void FLASH_OB_Lock(void)
   - void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState)
   - void FLASH_OB_RDPConfig(uint8_t OB_RDP)
   - void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY)
   - void FLASH_OB_BORConfig(uint8_t OB_BOR)
   - FLASH_Status FLASH_ProgramOTP(uint32_t Address, uint32_t Data)              
   - FLASH_Status FLASH_OB_Launch(void)
   - uint32_t FLASH_OB_GetUser(void)            
   - uint8_t FLASH_OB_GetWRP(void)            
   - uint8_t FLASH_OB_GetRDP(void)              
   - uint8_t FLASH_OB_GetBOR(void)
   
   Any operation of erase or program should follow these steps:
   1. Call the FLASH_OB_Unlock() function to enable the FLASH option control register access
   2. Call one or several functions to program the desired Option Bytes:
      - void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) => to Enable/Disable 
        the desired sector write protection
      - void FLASH_OB_RDPConfig(uint8_t OB_RDP) => to set the desired read Protection Level
      - void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) => to configure 
        the user Option Bytes.
      - void FLASH_OB_BORConfig(uint8_t OB_BOR) => to set the BOR Level
   3. Once all needed Option Bytes to be programmed are correctly written, call the
      FLASH_OB_Launch() function to launch the Option Bytes programming process.
     
     @note When changing the IWDG mode from HW to SW or from SW to HW, a system 
           reset is needed to make the change effective.
   4. Call the FLASH_OB_Lock() function to disable the FLASH option control register
      access (recommended to protect the Option Bytes against possible unwanted operations)
    
@endverbatim
  * @{
  */

編程Flash,寫保護,讀保護代碼開源

開源地址:

https://github.com/strongercjd/STM32F207VCT6

 

點擊查看本文所在的專輯,STM32F207教程