12.1.FMC 基礎知識
閃存控制器(FMC),提供了片上閃存需要的所有功能。FMC 也提供了頁擦除,整片擦除,以及32 位整字或 16 位半字編程閃存等操作。 GD32 MCU 支持不同類型編程的具體說明如下表 GD32 MCU 不同系列編程區別所示。

12.2.FMC 功能
支持 32 位整字或 16 位半字編程,頁擦除和整片擦除操作;
支持 CPU 執行指令零等待區域(code area)和非零等待區域(data area); 大小為 16 字節的可選字節塊可根據用戶需求配置;
具有安全保護狀態,可阻止對代碼或數據的非法讀訪問;
相關術語說明
GD32F10x 和 F30x 分別有 MD(中容量) 、HD(大容量)、XD(超大容量) 、CL(互聯型)系列,不同的系列外設資源有差異,使用固件庫(Firmware)也要作相應的選擇和定義。 中容量產品指Flash 容量為小于 256K 字節的系列;
大容量產品指 Flash 容量為 256K 至 512K 字節之間的 系列; 超大容量產品指 Flash 容量為 768K 至 3072K 字節之間的系列。
GD32F10X/F30X 系列容量匯總

不同容量工程選擇說明,固件庫是通過宏定義來區分的。

不同的系列 MCU flash 架構不一樣,其中 GD32F 系列的 MCU flash 分 code area 和 data area, code area CPU 執行指令是零等待, GD32E 系列 flash 不分 code area 和 data are,但都要插入等待周期。 GD32 系列 Code area&Data area 匯總

讀操作 閃存可以像普通存儲空間一樣直接尋址訪問。對閃存取指令和取數據分別使用 CPU 的 IBUS 或 DBUS總線。
代碼操作如:
uint32_t readflash[3] readflash [0] = *(__IO uint32_t*)(0x8004000); readflash [1] = *(__IO uint32_t*)((0x8004004); readflash [2] = *(__IO uint32_t*)((0x8004008);
頁擦除
FMC 的頁擦除功能使得主存儲閃存的頁內容初始化為高電平。 每一頁都可以被獨立擦除,而不影響其他頁內容。
FMC 擦除頁步驟如下:
? 確保 FMC_CTLx 寄存器不處于鎖定狀態;
? 檢查 FMC_STATx 寄存器的 BUSY 位來判定閃存是否正處于擦寫訪問狀態,若 BUSY 位為 1,則需等待該操作結束, BUSY 位變為 0;
? 置位 FMC_CTLx 寄存器的 PER 位;
? 將待擦除頁的絕對地址( 0x08XX XXXX)寫到 FMC_ADDRx 寄存器;
? 通過將 FMC_CTLx 寄存器的 START 位置 1 來發送頁擦除命令到 FMC;
? 等待擦除指令執行完畢, FMC_STATx 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證該頁是否擦除成功。

整片擦除
FMC 提供了整片擦除功能可以初始化主存儲閃存塊的內容。當設置 MER0 為 1 時,擦除過程僅作用于 Bank0,當設置 MER1 為 1 時,擦除過程僅作用于 Bank1,當設置 MER0 和 MER1 為 1 時,擦除過程作用于整片閃存。
整片擦除操作,寄存器設置具體步驟如下:
? 確保 FMC_CTLx 寄存器不處于鎖定狀態;
? 等待 FMC_STATx 寄存器的 BUSY 位變為 0;
? 如果單獨擦除 Bank0,置位 FMC_CTL0 寄存器的 MER 位。如果單獨擦除 Bank1,置位 FMC_CTL1 寄存器的 MER 位。如果整片擦除閃存,同時置位 FMC_CTL0 和 FMC_CTL1 寄存器的 MER 位;
? 通過將 FMC_CTLx 寄存器的 START 位置 1 來發送整片擦除命令到 FMC;
? 等待擦除指令執行完畢, FMC_STATx 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證是否擦除成功。

字編程操作
FMC 提供了一個 64 位、32 位整字/16 位半字編程功能,用來修改主存儲閃存塊內容。
編程操作使用各寄存器流程如下。
? 確保 FMC_CTLx 寄存器不處于鎖定狀態;
? 等待 FMC_STATx 寄存器的 BUSY 位變為 0;
? 置位 FMC_CTLx 寄存器的 PG 位;
? DBUS 寫一個 32 位整字/16 位半字到目的絕對地址(0x08XXXXXX);
? 等待編程指令執行完畢, FMC_STATx 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證是否編程成功。

可選字節塊擦除
FMC 提供了一個擦除功能用來初始化閃存中的可選字節塊。
可選字節塊擦除過程如下所示。
? 確保 FMC_CTL0 寄存器不處于鎖定狀態;
? 等待 FMC_STAT0 寄存器的 BUSY 位變為 0;
? 解鎖 FMC_CTL0 寄存器的可選字節操作位;
? 等待 FMC_CTL0 寄存器的 OBWEN 位置 1;
? 置位 FMC_CTL0 寄存器的 OBER 位;
? 通過將 FMC_CTL0 寄存器的 START 位置 1 來發送可選字節塊擦除命令到 FMC;
? 等待擦除指令執行完畢, FMC_STAT 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證是否擦除成功。當可選字節塊擦除成功執行, FMC_STAT 寄存器的 ENDF 位置位。若 FMC_CTL0 寄存器的 ENDIE 位被置 1, FMC 將觸發一個中斷。
可選字節塊編程
FMC 提供了一個 32 位整字/16 位半字編程功能,可用來修改可選字節塊內容。可選字節塊共有8 對可選字節。每對可選字節的高字節是低字節的補。當低字節被修改時, FMC 自動生成該選項字節的高字節。
字節塊編程操作過程如下。
? 確保 FMC_CTL0 寄存器不處于鎖定狀態;
? 等待 FMC_STAT0 寄存器的 BUSY 位變為 0;
? 解鎖 FMC_CTL0 寄存器的可選字節操作位;
? 等待 FMC_CTL0 寄存器的 OBWEN 位置 1;
? 置位 FMC_CTL0 寄存器的 OBPG 位;
? DBUS 寫一個 32 位整字/16 位半字到目的地址;
? 等待編程指令執行完畢, FMC_STAT 寄存器的 BUSY 位清 0;
可選字節塊說明
每次系統復位后,閃存的可選字節塊被重加載到 FMC_OBSTAT 和 FMC_WP 寄存器,可選字節生效。可選字節的補字節具體為可選字節取反。當可選字節被重裝載時,如果可選字節的補字節和可選字節不匹配, FMC_OBSTAT 寄存器的 OBERR 位將被置 1,可選字節被強制設置為 0xFF。若可選字節和其補字節同為 0xFF,則 OBERR 位不置位。
頁擦除/編程保護
FMC 的頁擦除/編程保護功能可以阻止對閃存的意外操作。當 FMC 對被保護頁進行頁擦除或編程操作時,操作本身無效且 FMC_STAT 寄存器的 WPERR 位將被置 1。如果 WPERR 位被置 1 且 FMC_CTL 寄存器的 ERRIE 位也被置 1 來使能相應的中斷, FMC 將觸發閃存操作出錯中斷,等待 CPU 處理。配置可選字節塊的 WP [31:0]某位為 0 可以單獨使能某幾頁的保護功能。如果在可選字節塊執行了擦除操作,所有的閃存頁擦除和編程保護功能都將失效。當可選字節的 WP 被改變時,需要系統復位使之生效。
12.3.軟件配置說明
FMC 以 Program 配置為例來說明
Demo 一 (flash 編程)
demo 功能說明: MCU 上電啟動后,對 MCU flash 的 0x8004000~ 0x08004800 的 2K 的區域寫 0x01234567 數據,當編寫錯誤的時候,LED 會亮。
軟件配置步驟如下:
1)配置 led 指示燈;
gd_eval_led_init(LED2); gd_eval_led_init(LED3);
2)進行 page erase
void fmc_erase_pages(void) { uint32_t EraseCounter; fmc_unlock(); //FMC 解鎖 fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR ); //清除標志 for(EraseCounter = 0; EraseCounter < PageNum; EraseCounter++){ fmc_page_erase(FMC_WRITE_START_ADDR + (FMC_PAGE_SIZE * EraseCounter)); //page 擦除 fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR ); //清除標志 } fmc_lock(); //FMC 加鎖 }
- page erase 檢查
void fmc_erase_pages_check(void) { uint32_t i; ptrd = (uint32_t *)FMC_WRITE_START_ADDR;//將寫地址賦值指針 for(i = 0; i < WordNum; i++) { if(0xFFFFFFFF != (*ptrd)) //判斷地址是否擦除成功 { lednum = LED2; gd_eval_led_on(lednum); //不成功的時候 LED2 會亮 break; }else { ptrd++; // 指針地址++ 再進行下一個地址判斷 } } }
- flash 編程
void fmc_program(void) { fmc_unlock(); //FMC 解鎖 address = FMC_WRITE_START_ADDR; while(address < FMC_WRITE_END_ADDR){ fmc_word_program(address, data0); //word 編程 address += 4; fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR );//清除標志 } fmc_lock(); //FMC 加鎖 }
- 字編程檢查
void fmc_program_check(void) { uint32_t i; ptrd = (uint32_t *)FMC_WRITE_START_ADDR; //將寫地址賦值指針 for(i = 0; i < WordNum; i++) { if((*ptrd) != data0) //判斷寫入的數據是否一致 { lednum = LED3; gd_eval_led_on(lednum); //不相等的時候 LED3 會亮 break; }else { ptrd++; // 指針地址++ 再進行下一個地址判斷 } } }
12.4.FMC 使用注意事項
(1)操作 flash 之前需要 fmc_unlock();
(2)flash 編程之前需要 page 擦除;
(3)Page erase 和 program 之前需要先清空標志位;
(4)避免在 erase 或者 program 過程中出現掉電情況,用 flash 作為 eeprom 來用時,需要做好數據備份;
(5)在擦除 code data flash 過程中,擦除的優先級最高,此時任何中斷都不響應。這時需要注意 MCU 與外界通訊時,數據丟失情況。
-
單片機
+關注
關注
6043文章
44621瀏覽量
638487 -
mcu
+關注
關注
146文章
17317瀏覽量
352628 -
嵌入式
+關注
關注
5092文章
19177瀏覽量
307637 -
FMC
+關注
關注
0文章
96瀏覽量
19758 -
開發板
+關注
關注
25文章
5121瀏覽量
98187
發布評論請先 登錄
相關推薦
GD32 MCU移植
《GD32 MCU原理及固件庫開發指南》+讀后感
兆易創新GD32 MCU選型手冊,適用于GD32全系列MCU
GD32 MCU ISP失敗的原因

【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(1)使用Keil開發GD32

【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(2)使用 IAR 開發 GD32

【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(3)使用 Embedded Builder 開發 GD32

【GD32 MCU 入門教程】二、GD32 MCU 燒錄說明(1)ISP 燒錄

【GD32 MCU 入門教程】GD32 MCU 常見外設介紹(14)RTC 模塊介紹

【GD32 MCU入門教程】GD32 MCU GPIO 結構與使用注意事項

評論