12.1.FMC 基礎知識
閃存控制器(FMC),提供了片上閃存需要的所有功能。FMC 也提供了頁擦除,整片擦除,以及32 位整字或 16 位半字編程閃存等操作。 GD32 MCU 支持不同類型編程的具體說明如下表 GD32 MCU 不同系列編程區(qū)別所示。
12.2.FMC 功能
支持 32 位整字或 16 位半字編程,頁擦除和整片擦除操作;
支持 CPU 執(zhí)行指令零等待區(qū)域(code area)和非零等待區(qū)域(data area); 大小為 16 字節(jié)的可選字節(jié)塊可根據(jù)用戶需求配置;
具有安全保護狀態(tài),可阻止對代碼或數(shù)據(jù)的非法讀訪問;
相關術(shù)語說明
GD32F10x 和 F30x 分別有 MD(中容量) 、HD(大容量)、XD(超大容量) 、CL(互聯(lián)型)系列,不同的系列外設資源有差異,使用固件庫(Firmware)也要作相應的選擇和定義。 中容量產(chǎn)品指Flash 容量為小于 256K 字節(jié)的系列;
大容量產(chǎn)品指 Flash 容量為 256K 至 512K 字節(jié)之間的 系列; 超大容量產(chǎn)品指 Flash 容量為 768K 至 3072K 字節(jié)之間的系列。
GD32F10X/F30X 系列容量匯總
不同容量工程選擇說明,固件庫是通過宏定義來區(qū)分的。
不同的系列 MCU flash 架構(gòu)不一樣,其中 GD32F 系列的 MCU flash 分 code area 和 data area, code area CPU 執(zhí)行指令是零等待, GD32E 系列 flash 不分 code area 和 data are,但都要插入等待周期。 GD32 系列 Code area&Data area 匯總
讀操作 閃存可以像普通存儲空間一樣直接尋址訪問。對閃存取指令和取數(shù)據(jù)分別使用 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 的頁擦除功能使得主存儲閃存的頁內(nèi)容初始化為高電平。 每一頁都可以被獨立擦除,而不影響其他頁內(nèi)容。
FMC 擦除頁步驟如下:
? 確保 FMC_CTLx 寄存器不處于鎖定狀態(tài);
? 檢查 FMC_STATx 寄存器的 BUSY 位來判定閃存是否正處于擦寫訪問狀態(tài),若 BUSY 位為 1,則需等待該操作結(jié)束, BUSY 位變?yōu)?0;
? 置位 FMC_CTLx 寄存器的 PER 位;
? 將待擦除頁的絕對地址( 0x08XX XXXX)寫到 FMC_ADDRx 寄存器;
? 通過將 FMC_CTLx 寄存器的 START 位置 1 來發(fā)送頁擦除命令到 FMC;
? 等待擦除指令執(zhí)行完畢, FMC_STATx 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證該頁是否擦除成功。
整片擦除
FMC 提供了整片擦除功能可以初始化主存儲閃存塊的內(nèi)容。當設置 MER0 為 1 時,擦除過程僅作用于 Bank0,當設置 MER1 為 1 時,擦除過程僅作用于 Bank1,當設置 MER0 和 MER1 為 1 時,擦除過程作用于整片閃存。
整片擦除操作,寄存器設置具體步驟如下:
? 確保 FMC_CTLx 寄存器不處于鎖定狀態(tài);
? 等待 FMC_STATx 寄存器的 BUSY 位變?yōu)?0;
? 如果單獨擦除 Bank0,置位 FMC_CTL0 寄存器的 MER 位。如果單獨擦除 Bank1,置位 FMC_CTL1 寄存器的 MER 位。如果整片擦除閃存,同時置位 FMC_CTL0 和 FMC_CTL1 寄存器的 MER 位;
? 通過將 FMC_CTLx 寄存器的 START 位置 1 來發(fā)送整片擦除命令到 FMC;
? 等待擦除指令執(zhí)行完畢, FMC_STATx 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證是否擦除成功。
字編程操作
FMC 提供了一個 64 位、32 位整字/16 位半字編程功能,用來修改主存儲閃存塊內(nèi)容。
編程操作使用各寄存器流程如下。
? 確保 FMC_CTLx 寄存器不處于鎖定狀態(tài);
? 等待 FMC_STATx 寄存器的 BUSY 位變?yōu)?0;
? 置位 FMC_CTLx 寄存器的 PG 位;
? DBUS 寫一個 32 位整字/16 位半字到目的絕對地址(0x08XXXXXX);
? 等待編程指令執(zhí)行完畢, FMC_STATx 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證是否編程成功。
可選字節(jié)塊擦除
FMC 提供了一個擦除功能用來初始化閃存中的可選字節(jié)塊。
可選字節(jié)塊擦除過程如下所示。
? 確保 FMC_CTL0 寄存器不處于鎖定狀態(tài);
? 等待 FMC_STAT0 寄存器的 BUSY 位變?yōu)?0;
? 解鎖 FMC_CTL0 寄存器的可選字節(jié)操作位;
? 等待 FMC_CTL0 寄存器的 OBWEN 位置 1;
? 置位 FMC_CTL0 寄存器的 OBER 位;
? 通過將 FMC_CTL0 寄存器的 START 位置 1 來發(fā)送可選字節(jié)塊擦除命令到 FMC;
? 等待擦除指令執(zhí)行完畢, FMC_STAT 寄存器的 BUSY 位清 0;
? 如果需要,使用 DBUS 讀并驗證是否擦除成功。當可選字節(jié)塊擦除成功執(zhí)行, FMC_STAT 寄存器的 ENDF 位置位。若 FMC_CTL0 寄存器的 ENDIE 位被置 1, FMC 將觸發(fā)一個中斷。
可選字節(jié)塊編程
FMC 提供了一個 32 位整字/16 位半字編程功能,可用來修改可選字節(jié)塊內(nèi)容。可選字節(jié)塊共有8 對可選字節(jié)。每對可選字節(jié)的高字節(jié)是低字節(jié)的補。當?shù)妥止?jié)被修改時, FMC 自動生成該選項字節(jié)的高字節(jié)。
字節(jié)塊編程操作過程如下。
? 確保 FMC_CTL0 寄存器不處于鎖定狀態(tài);
? 等待 FMC_STAT0 寄存器的 BUSY 位變?yōu)?0;
? 解鎖 FMC_CTL0 寄存器的可選字節(jié)操作位;
? 等待 FMC_CTL0 寄存器的 OBWEN 位置 1;
? 置位 FMC_CTL0 寄存器的 OBPG 位;
? DBUS 寫一個 32 位整字/16 位半字到目的地址;
? 等待編程指令執(zhí)行完畢, FMC_STAT 寄存器的 BUSY 位清 0;
可選字節(jié)塊說明
每次系統(tǒng)復位后,閃存的可選字節(jié)塊被重加載到 FMC_OBSTAT 和 FMC_WP 寄存器,可選字節(jié)生效。可選字節(jié)的補字節(jié)具體為可選字節(jié)取反。當可選字節(jié)被重裝載時,如果可選字節(jié)的補字節(jié)和可選字節(jié)不匹配, FMC_OBSTAT 寄存器的 OBERR 位將被置 1,可選字節(jié)被強制設置為 0xFF。若可選字節(jié)和其補字節(jié)同為 0xFF,則 OBERR 位不置位。
頁擦除/編程保護
FMC 的頁擦除/編程保護功能可以阻止對閃存的意外操作。當 FMC 對被保護頁進行頁擦除或編程操作時,操作本身無效且 FMC_STAT 寄存器的 WPERR 位將被置 1。如果 WPERR 位被置 1 且 FMC_CTL 寄存器的 ERRIE 位也被置 1 來使能相應的中斷, FMC 將觸發(fā)閃存操作出錯中斷,等待 CPU 處理。配置可選字節(jié)塊的 WP [31:0]某位為 0 可以單獨使能某幾頁的保護功能。如果在可選字節(jié)塊執(zhí)行了擦除操作,所有的閃存頁擦除和編程保護功能都將失效。當可選字節(jié)的 WP 被改變時,需要系統(tǒng)復位使之生效。
12.3.軟件配置說明
FMC 以 Program 配置為例來說明
Demo 一 (flash 編程)
demo 功能說明: MCU 上電啟動后,對 MCU flash 的 0x8004000~ 0x08004800 的 2K 的區(qū)域?qū)?0x01234567 數(shù)據(jù),當編寫錯誤的時候,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) //判斷寫入的數(shù)據(jù)是否一致 { 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 過程中出現(xiàn)掉電情況,用 flash 作為 eeprom 來用時,需要做好數(shù)據(jù)備份;
(5)在擦除 code data flash 過程中,擦除的優(yōu)先級最高,此時任何中斷都不響應。這時需要注意 MCU 與外界通訊時,數(shù)據(jù)丟失情況。
本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關注聚沃科技官網(wǎng)
-
單片機
+關注
關注
6037文章
44558瀏覽量
635301 -
mcu
+關注
關注
146文章
17148瀏覽量
351197 -
嵌入式
+關注
關注
5082文章
19126瀏覽量
305198 -
FMC
+關注
關注
0文章
93瀏覽量
19687 -
開發(fā)板
+關注
關注
25文章
5050瀏覽量
97471
發(fā)布評論請先 登錄
相關推薦
評論