在項目開發之初,我們會根據設計需求來選擇符合要求的芯片。其中,RAM決定了程序運行時的內存大小,ROM決定了應用程序的存儲空間大小。但對于應用功能特別大的項目,MCU內部的FLASH(ROM)存儲空間就無法滿足要求了。這個時候就需要外擴程序存儲空間,而NOR FLASH就是其中一種解決方案。
文結合涉及到的技術點一一做了詳細介紹和說明,包含如下四大內容:
1. KEIL下載程序配置及說明2. MM32實現跳轉到NOR FLASH運行程序3. 基于MM32的NOR FLASH下載算法實現4. MM32實現NOR FLASH應用程序編程,下載程序并運行
一、KEIL下載程序配置及說明
通過對項目工程的配置,在KEIL在編譯完工程后,會生成相應的HEX或BIN格式的程序燒錄文件,點擊Download下載按鍵后,會將燒錄文件燒錄到芯片中。
點擊Option for Target魔術棒按鍵,在彈出的Option for Target窗口中的Output選項卡中設置生成程序燒錄文件名,并勾選Create HEX file選項,如下圖所示:
如果需要同時再生成BIN格式的程序燒錄文件,我們可以在User選項卡中進行如下圖的配置:
接著,在Debug選項卡中選擇相應的調試下載工具。
在Utilities選項卡中配置下載設置(使用與Debug相同的工具進行下載程序),如下圖所示:
另外Utilities選項卡中,點擊Settings按鍵,在彈出的窗口中Flash Download選項卡中進行如下配置:
下載功能設置:包括擦出選擇、編程、校驗和下載完成后復位芯片并運行應用程序。
編程(下載)算法選擇:一般在創建工程選擇相應的芯片后,這邊的下載算法就默認了,如果沒有我們可以點擊ADD按鍵添加相對應的下載算法;下載算法列舉了描述、設備存儲空間大小、設備類型以及地址區間范圍。
編程(下載)算法在RAM中的位置:這個一般是默認的,START表示芯片RAM的起始地址,這個是由芯片決定的;SIZE表示最大支持的編程(下載)算法的程序空間大小,這個可以修改,但不得小于下載算法程序大小。
待這些都配置完成后,我們編譯工程代碼,無錯誤警告后,點擊Download下載按鍵,即可下載應用程序到芯片中。
那么,在點擊了Download按鍵后,那KEIL是如何將燒錄程序下載到芯片中去的呢?
簡單來說,就是KEIL軟件根據配置將編程(下載)算法加載到芯片指定的RAM空間去(這個空間就是上述的以START作為起始地址,SIZE大小的RAM空間),并運行下載算法,對下載文件進行解析,將需要寫入的數據通過下載算法寫到指定的存儲地址上,完成上述編程的過程。
二、MM32實現跳轉到NOR FLASH運行程序
MM32F3270系列MCU支持存儲控制器FSMC功能,可配置的靜態存儲器包括SRAM、NOR FLASH;另外還支持80806800接口,可以應用到LCD顯示上。
NOR FLASH之所以可以運行程序,主要是因為其內部地址/數據線是分開的,支持字節訪問,符合CPU指令譯碼執行的要求(NOR FLASH上儲存了指令代碼,MCU給NOR FLASH一個地址,NOR FLASH就向MCU返回相應地址上的數據,讓MCU執行,中間不需要額外的處理操作)。
那通過上述的描述,使用MM32實現跳轉到NOR FLASH運行程序,我們就只需要在基于MM32內部FLASH運行的基礎上實現NOR FLASH與MCU之間的FSMC初始化配置,以及程序跳轉這兩個操作步驟,具體參考代碼如下所示:
FSMC初始化配置:
/*******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url] NOR.c
* [url=home.php?mod=space&uid=187600]@author[/url] King
* [url=home.php?mod=space&uid=895143]@version[/url] V1.00
* [url=home.php?mod=space&uid=212281]@date[/url] 25-Jan-2021
* [url=home.php?mod=space&uid=247401]@brief[/url] ......
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#define __NOR_C__
/* Includes ------------------------------------------------------------------*/
#include "NOR.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
/*******************************************************************************
* @brief
* @param
* @retval
* [url=home.php?mod=space&uid=93590]@Attention[/url]
*******************************************************************************/
void NOR_InitGPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE |
RCC_AHBPeriph_GPIOF | RCC_AHBPeriph_GPIOG , ENABLE);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_12); /* FSMC_D0 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_12); /* FSMC_D1 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_12); /* FSMC_D2 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_12); /* FSMC_D3 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_12); /* FSMC_D4 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_12); /* FSMC_D5 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_12); /* FSMC_D6 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_12); /* FSMC_D7 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_12); /* FSMC_D8 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_12); /* FSMC_D9 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_12); /* FSMC_D10 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_12); /* FSMC_D11 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_12); /* FSMC_D12 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_12); /* FSMC_D13 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_12); /* FSMC_D14 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_12); /* FSMC_D15 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_12); /* FSMC_A0 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_12); /* FSMC_A1 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_12); /* FSMC_A2 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_12); /* FSMC_A3 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_12); /* FSMC_A4 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_12); /* FSMC_A5 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_12); /* FSMC_A6 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_12); /* FSMC_A7 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_12); /* FSMC_A8 */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_12); /* FSMC_A9 */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource0, GPIO_AF_12); /* FSMC_A10 */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource1, GPIO_AF_12); /* FSMC_A11 */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource2, GPIO_AF_12); /* FSMC_A12 */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource3, GPIO_AF_12); /* FSMC_A13 */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource4, GPIO_AF_12); /* FSMC_A14 */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource5, GPIO_AF_12); /* FSMC_A15 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_12); /* FSMC_A16 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_12); /* FSMC_A17 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_12); /* FSMC_A18 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource3, GPIO_AF_12); /* FSMC_A19 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_12); /* FSMC_A20 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_12); /* FSMC_A21 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_12); /* FSMC_A22 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_12); /* FSMC_NOE */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_12); /* FSMC_NWE */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_12); /* FSMC_NWAIT*/
GPIO_PinAFConfig(GPIOG, GPIO_PinSource9, GPIO_AF_12); /* FSMC_NE2 */
/* D00 - D01 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* D02 - D03 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* D04 - D12 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 |
GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 |
GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* D13 - D15 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* A00 - A05 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* A06 - A09 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 |
GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* A10 - A15 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/* A16 - A18 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* A19 - A22 */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 |
GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* NOE(PD4) NWE(PD5) configuration */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* NWAIT(PD6) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* NE2(PG9) configuration */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void NOR_InitFSMC(void)
{
FSMC_InitTypeDef FSMC_InitStructure;
FSMC_NORSRAM_Bank_InitTypeDef FSMC_BankInitStructure;
RCC_AHB3PeriphClockCmd(RCC_AHB3ENR_FSMC, ENABLE);
FSMC_NORSRAM_BankStructInit(&FSMC_BankInitStructure);
FSMC_BankInitStructure.FSMC_SMReadPipe = 0;
FSMC_BankInitStructure.FSMC_ReadyMode = 0;
FSMC_BankInitStructure.FSMC_WritePeriod = 5; /* W:WE Pulse Width : [0, 63] */
FSMC_BankInitStructure.FSMC_WriteHoldTime = 3; /* W:Address/Data Hold Time : [0, 3] */
FSMC_BankInitStructure.FSMC_AddrSetTime = 3; /* W:Address Setup Time : [0, 3] */
FSMC_BankInitStructure.FSMC_ReadPeriod = 8; /* R:Read Cycle Time : [0, 63] */
FSMC_BankInitStructure.FSMC_DataWidth = FSMC_DataWidth_16bits;
FSMC_NORSRAM_Bank_Init(&FSMC_BankInitStructure, FSMC_NORSRAM_BANK1);
FSMC_NORSRAMStructInit(&FSMC_InitStructure);
FSMC_InitStructure.FSMC_Mode = FSMC_Mode_NorFlash;
FSMC_InitStructure.FSMC_TimingRegSelect = FSMC_TimingRegSelect_1;
FSMC_InitStructure.FSMC_MemSize = FSMC_MemSize_64MB;
FSMC_InitStructure.FSMC_MemType = FSMC_MemType_FLASH;
FSMC_InitStructure.FSMC_AddrDataMode = FSMC_AddrDataDeMUX;
FSMC_NORSRAMInit(&FSMC_InitStructure);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void NOR_Init(void)
{
NOR_InitGPIO();
NOR_InitFSMC();
}
/******************* (C) COPYRIGHT 2022 *************************END OF FILE***/
程序跳轉代碼:
/*******************************************************************************
* @file main.c
* @author King
* @version V1.00
* @date 25-Jan-2021
* @brief ......
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#define __MAIN_C__
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private typedef -----------------------------------------------------------*/
typedef void (*pFunction)(void);
/* Private define ------------------------------------------------------------*/
#define ApplicationAddress ((uint32_t)0x64000000)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t JumpAddress = 0;
pFunction JumpToApplication;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
int main(void)
{
NOR_Init();
/* Jump to code loaded in NOR memory and execute it ***********************/
JumpAddress = *(volatile uint32_t *)(ApplicationAddress + 4);
JumpToApplication = (pFunction)JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(volatile uint32_t *)ApplicationAddress);
JumpToApplication();
while(1);
}
/******************* (C) COPYRIGHT 2022 *************************END OF FILE***/
KEIL工程的相關配置:
三、基于MM32的NOR FLASH下載算法實現
在能夠成功跳轉到NOR FLASH運行程序后,我們就需要將應用程序下載到NOR FLASH就可以了。
結合第一小結,一般MCU自帶的下載算法只是將程序下載到自身內部的FLASH存儲空間,如果需要將程序下載到外擴的NOR FLASH,我們可以使用燒錄工具,將程序燒錄進NOR FLASH。但在開發調試過程中,這顯然不太方便,所以我們就需要自行編寫下載算法,來實現MM32與NOR FLASH之間的程序編程。
應該怎么去編寫這個下載算法呢?
首先,在KEIL的安裝路徑下:C:Keil_v5ARMFlash有一個_Template的下載算法工程模板,我們將其直接拷貝一份,重命名為MM32F3270_NOR_FLM;打開KEIL工程,里面主要有兩個文件FlashDev.c和FlashPrg.c
FlashDev.c主要是用來描述存儲特性的,包括Device Name、Device Type、Device Start Address、Device Size in Bytes等等,這些特性的值,我們可以根據NOR FLASH的特性值來填寫,編程超時時間和擦出超時時間可以盡量長一些,做些冗余,具體參考如下所示:
FlashPrg.c就是用來實現編程下載算法的接口函數,其中有些函數是必須實現的,有些函數則是可選擇的,如下所示:
我們需要實現的就是通過對這些函數的補充實現,來達到NOR FLASH的讀寫操作,實現將程序下載到NOR FLASH。
在第一小節,我們知道下載算法是需要先加載到RAM中運行,再去進行編程操作的,對于這個加載到RAM空間的下載算法程序空間大小其實是有大小限制有,根據每個芯片的RAM大小而定,但最大也不能超過0x10000。
所以,我們在實現自己定義的下載算法的時候就尤其需要注意,盡量的不去使用庫函數,以使用寄存器或者是直接操作芯片內部地址最佳,這樣可以最大程序的節省程序空間。
不過,這也會使代碼的閱讀理解變得有些困難。因為下載算法運行的程序不能夠實現的在線調試,所以對于NOR FLASH操作的這些函數功能,最好在其它工程上先進行驗證,確認功能正常后,再移植到下載算法的工程當中來。
接下來,就是點擊KEIL工程魔術棒按鍵對工程進行設置。在Target選項卡中選擇芯片型號為MM32F3277G9P,在C/C++選項卡中根據需要進行宏定義(因為這個下載算法,支持多個NOR FLASH,所以我這邊有相應的宏定義),在添加好NOR FLASH的相關函數,并補全接口函數后,進行編譯。
此時工程目錄中就會生成一個FLM文件(因為在User選項卡中有一個命令:cmd.exe /C copy "Objects\%L" ".@L.FLM",它會將編譯后的文件轉換成FLM格式)
我們將這個生成的FLM下載算法文件拷貝到C:Keil_v5ARMFlash目錄下,在后面工程使用到的時候就可以添加進來了。
四、MM32實現NOR FLASH應用程序編程,下載程序并運行
對于運行在NOR FLASH中的MM32程序來說,程序編寫并沒有特殊的要求,唯一不同的就是對于KEIL工程的設置。例程中,我們只實現了LED燈的閃爍功能,功能比較簡單。對于KEIL工程的設置,如下圖所示:
將默認的程序空間和程序啟動空間設置為NOR FLASH的起始地址作為開始:
根據DEBUG調試工具進行對應的選擇:
下載工具與調試工具相同:
將編程(下載)算法選擇為第三小節生成的FLM算法,在添加進來的時候,就會自動顯示相應的描述信息:
這樣配置完成后,編譯后點擊下載按鍵,程序就被下載到NOR FLASH外部存儲空間了。因為勾選了RESET AND RUN,下載完成后會復位MCU,此時MCU FLASH中已經存在了跳轉程序,這個時候就會跳轉到NOR FLASH執行LED閃爍程序。此時LED燈若能夠正常運行,就說明程序功能已經正常運行了。
另外,有些小伙伴可能會問,在Option for Target窗口Utilities選項卡中,有看到Init File會配置一個INI文件,我上述的工程配置中卻沒有,這是怎么回事呢?
這邊的INI文件包含的是對MCU內部地址配置相應參數值的數據,是在下載程序前先對MCU進行設置的操作。一般看到的就是對MCU與NOR FLASH的FSMC相關寄存器進行配置,好讓下載算法能夠正常的去操作NOR FLASH。但我的配置截圖中卻沒有,是因為在實現下載算法時的INIT函數,已經實現了對FSMC的初始化配置,所以在INIT FILE的位置就不需要再重復操作了。
五、后續
有了這個下載算法,我們可以將部分程序或數據指令到外部存儲空間;如果當我們通過LCD顯示圖片數據時,圖片數據是一個很大的數組,我們就可以將這些數據指定到NOR FLASH中,而應用程序還是在MCU內部的FLASH中運行,操作如下圖所示:
芯片有兩個ROM空間,但默認的和啟動的為MCU內部FLASH:
下載算法有兩個,這兩個的地址是不一樣的,一個是MCU內部FLASH,一個是外擴的NOR FLASH:
將程序指定到NOR FLASH的方法,右擊.C文件,選擇Options for File”IMAGE1.c”...
在彈出的窗口中將CODE/CONST指令到ROM1,如下圖所示:
然后在程序中再調用IMAGE1.c文件中的數據,這樣在編譯后下載程序的時候,會先下載程序到MCU的FLASH,再下載圖片數據到MCU擴展的NOR FLASH。
本文中的硬件是基本神舟III開發板實現的,MCU使用的是靈動微電子的MM32F3277G9P,NOR FLASH使用的是M29W128FH。
至此分享就結束了,希望能對各位小伙伴有所幫助!另外,如果有需要查看原圖和代碼的小伙伴,請點擊底部“閱讀原文”進行下載。
審核編輯 :李倩
-
芯片
+關注
關注
456文章
50884瀏覽量
424158 -
應用程序
+關注
關注
37文章
3277瀏覽量
57734 -
存儲空間
+關注
關注
0文章
54瀏覽量
10688 -
MM32
+關注
關注
1文章
106瀏覽量
777
原文標題:實戰!基于MM32實現NOR FLASH運行應用程序的過程解析
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論