返回列表 发新帖我要提问本帖赏金: 50.00元(功能说明)

[MM32软件] 基于MM32实现NOR FLASH运行应用程序的过程解析

[复制链接]
4278|10
 楼主| xld0932 发表于 2022-2-9 16:03 | 显示全部楼层 |阅读模式
#申请原创#@21小跑堂
在项目开发之初,我们会根据设计需求来选择符合要求的芯片,其中RAM决定程序运行时的内存大小、ROM决定了应用程序的存储空间大小;但就些应用功能特别大的项目,MCU内部的FLASHROM)存储空间无法满足要求,这个时候就需要外扩程序存储空间,NOR FLASH就是其中一种解决方案;本文结合涉及到的技术点一一做了介绍说明,包含如下的内容:
1、KEIL下载程序配置及说明
2、MM32实现跳转到NOR FLASH运行程序
3、基于MM32NOR FLASH下载算法实现
4、MM32实现NOR FLASH应用程序编程,下载程序并运行

KEIL下载程序配置及说明

通过对项目工程的配置,在KEIL在编译完工程后,会生成相应的HEXBIN格式的程序烧录文件,点击Download下载按键后,会将烧录文件烧录到芯片中:
点击Option for Target魔术棒按键,在弹出的Option for Target窗口中的Output选项卡中设置生成程序烧录文件名,并勾选Create HEX file选项:
43766203719d51ac9.png

如果需要同时再生成BIN格式的程序烧录文件,我们可以在User选项卡中进行如下图的配置:
60684620371b7801a5.png

接着在Debug选项卡中选择相应的调试下载工具:
37718620371ca332d2.png

Utilities选项卡中配置下载设置(使用与Debug相同的工具进行下载程序)如下图所示:
3698620371e7a4c37.png

另外Utilities选项卡中,点击Settings按键,在弹出的窗口中Flash Download选项卡中进行如下配置:
89578620371ff8629c.png

下载功能设置:包括了擦出选择、编程、校验和下载完成后复位芯片并运行应用程序;
编程(下载)算法选择:一般在创建工程选择相应的芯片后,这边的下载算法就默认了,如果没有我们可以点击ADD按键添加相对应的下载算法;下载算法列举了描述、设备存储空间大小、设备类型以及地址区间范围;
编程(下载)算法在RAM中的位置:这个一般是默认的,START表示芯片RAM的起始地址,这个是由芯片决定的;SIZE表示最大支持的编程(下载)算法的程序空间大小,这个可以修改,但不得小于下载算法程序大小;

待这些都配置完成后,我们编译工程代码,无错误警告后,点击Download下载按键,即可下载应用程序到芯片中;

那在点击了Download按键后,那KEIL是如何将烧录程序下载到芯片中去的呢?

简单的说就是KEIL软件根据配置将编程(下载)算法加载到芯片指定的RAM空间去(这个空间就是上述的以START作为起始地址,SIZE大小的RAM空间),并运行下载算法,对下载文件进行解析,将需要写入的数据通过下载算法写到指定的存储地址上,完成上述编程的过程。

MM32实现跳转到NOR FLASH运行程序

MM32F3270系列MCU支持存储控制器FSMC功能,可配置的静态存储器包括SRAMNOR FLASH;另外还支持8080\6800接口,可以应用到LCD显示上;

NOR FLASH之所以可以运行程序,主要是因为其内部地址/数据线是分开的,支持字节访问,符合CPU指令译码执行的要求(NOR FLASH上储存了指令代码,MCUNOR FLASH一个地址,NOR FLASH就向MCU返回相应地址上的数据,让MCU执行,中间不需要额外的处理操作)。

那通过上述的描述,使用MM32实现跳转到NOR FLASH运行程序,我们就只需要在基于MM32内部FLASH运行的基础上实现NOR FLASHMCU之间的FSMC初始化配置,以及程序跳转这两个操作步骤,具体参考代码如下所示:

FSMC初始化配置:
  1. /*******************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]    NOR.c
  3. * [url=home.php?mod=space&uid=187600]@author[/url]  King
  4. * [url=home.php?mod=space&uid=895143]@version[/url] V1.00
  5. * [url=home.php?mod=space&uid=212281]@date[/url]    25-Jan-2021
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]   ......
  7. *******************************************************************************/


  8. /* Define to prevent recursive inclusion -------------------------------------*/
  9. #define __NOR_C__


  10. /* Includes ------------------------------------------------------------------*/
  11. #include "NOR.h"


  12. /* Private typedef -----------------------------------------------------------*/
  13. /* Private define ------------------------------------------------------------*/
  14. /* Private macro -------------------------------------------------------------*/
  15. /* Private variables ---------------------------------------------------------*/
  16. /* Private function prototypes -----------------------------------------------*/
  17. /* Private functions ---------------------------------------------------------*/


  18. /* Exported variables --------------------------------------------------------*/
  19. /* Exported function prototypes ----------------------------------------------*/


  20. /*******************************************************************************
  21. * @brief      
  22. * @param      
  23. * @retval      
  24. * [url=home.php?mod=space&uid=93590]@Attention[/url]   
  25. *******************************************************************************/
  26. void NOR_InitGPIO(void)
  27. {
  28.     GPIO_InitTypeDef GPIO_InitStructure;

  29.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE |
  30.                           RCC_AHBPeriph_GPIOF | RCC_AHBPeriph_GPIOG , ENABLE);

  31.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_12);  /* FSMC_D0  */
  32.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_12);  /* FSMC_D1  */
  33.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource0,  GPIO_AF_12);  /* FSMC_D2  */
  34.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource1,  GPIO_AF_12);  /* FSMC_D3  */
  35.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource7,  GPIO_AF_12);  /* FSMC_D4  */
  36.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource8,  GPIO_AF_12);  /* FSMC_D5  */
  37.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource9,  GPIO_AF_12);  /* FSMC_D6  */
  38.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_12);  /* FSMC_D7  */
  39.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_12);  /* FSMC_D8  */
  40.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_12);  /* FSMC_D9  */
  41.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_12);  /* FSMC_D10 */
  42.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_12);  /* FSMC_D11 */
  43.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_12);  /* FSMC_D12 */
  44.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource8,  GPIO_AF_12);  /* FSMC_D13 */
  45.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource9,  GPIO_AF_12);  /* FSMC_D14 */
  46.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_12);  /* FSMC_D15 */

  47.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource0,  GPIO_AF_12);  /* FSMC_A0  */
  48.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource1,  GPIO_AF_12);  /* FSMC_A1  */
  49.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource2,  GPIO_AF_12);  /* FSMC_A2  */
  50.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource3,  GPIO_AF_12);  /* FSMC_A3  */
  51.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource4,  GPIO_AF_12);  /* FSMC_A4  */
  52.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource5,  GPIO_AF_12);  /* FSMC_A5  */

  53.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_12);  /* FSMC_A6  */
  54.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_12);  /* FSMC_A7  */
  55.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_12);  /* FSMC_A8  */
  56.     GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_12);  /* FSMC_A9  */

  57.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource0,  GPIO_AF_12);  /* FSMC_A10 */
  58.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource1,  GPIO_AF_12);  /* FSMC_A11 */
  59.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource2,  GPIO_AF_12);  /* FSMC_A12 */
  60.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource3,  GPIO_AF_12);  /* FSMC_A13 */
  61.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource4,  GPIO_AF_12);  /* FSMC_A14 */
  62.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource5,  GPIO_AF_12);  /* FSMC_A15 */

  63.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_12);  /* FSMC_A16 */
  64.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_12);  /* FSMC_A17 */
  65.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_12);  /* FSMC_A18 */

  66.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource3,  GPIO_AF_12);  /* FSMC_A19 */
  67.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource4,  GPIO_AF_12);  /* FSMC_A20 */
  68.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource5,  GPIO_AF_12);  /* FSMC_A21 */
  69.     GPIO_PinAFConfig(GPIOE, GPIO_PinSource6,  GPIO_AF_12);  /* FSMC_A22 */

  70.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource4,  GPIO_AF_12);  /* FSMC_NOE  */
  71.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource5,  GPIO_AF_12);  /* FSMC_NWE  */
  72.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource6,  GPIO_AF_12);  /* FSMC_NWAIT*/
  73.     GPIO_PinAFConfig(GPIOG, GPIO_PinSource9,  GPIO_AF_12);  /* FSMC_NE2  */

  74.     /* D00 - D01 */
  75.     GPIO_StructInit(&GPIO_InitStructure);
  76.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_14 | GPIO_Pin_15;
  77.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  78.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  79.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  80.     /* D02 - D03 */
  81.     GPIO_StructInit(&GPIO_InitStructure);
  82.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1;
  83.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  84.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  85.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  86.     /* D04 - D12 */
  87.     GPIO_StructInit(&GPIO_InitStructure);
  88.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7  | GPIO_Pin_8  | GPIO_Pin_9  |
  89.                                     GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 |
  90.                                     GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  91.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  92.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  93.     GPIO_Init(GPIOE, &GPIO_InitStructure);

  94.     /* D13 - D15 */
  95.     GPIO_StructInit(&GPIO_InitStructure);
  96.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
  97.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  98.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  99.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  100.     /* A00 - A05 */
  101.     GPIO_StructInit(&GPIO_InitStructure);
  102.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
  103.                                     GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
  104.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  105.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  106.     GPIO_Init(GPIOF, &GPIO_InitStructure);

  107.     /* A06 - A09 */
  108.     GPIO_StructInit(&GPIO_InitStructure);
  109.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12 | GPIO_Pin_13 |
  110.                                     GPIO_Pin_14 | GPIO_Pin_15;
  111.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  112.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  113.     GPIO_Init(GPIOF, &GPIO_InitStructure);

  114.     /* A10 - A15 */
  115.     GPIO_StructInit(&GPIO_InitStructure);
  116.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
  117.                                     GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
  118.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  119.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  120.     GPIO_Init(GPIOG, &GPIO_InitStructure);

  121.     /* A16 - A18 */
  122.     GPIO_StructInit(&GPIO_InitStructure);
  123.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
  124.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  125.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  126.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  127.     /* A19 - A22 */
  128.     GPIO_StructInit(&GPIO_InitStructure);
  129.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_4 |
  130.                                     GPIO_Pin_5 | GPIO_Pin_6;
  131.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  132.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  133.     GPIO_Init(GPIOE, &GPIO_InitStructure);

  134.     /* NOE(PD4) NWE(PD5) configuration */  
  135.     GPIO_StructInit(&GPIO_InitStructure);
  136.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5;
  137.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  138.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  139.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  140.     /* NWAIT(PD6) configuration */
  141.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
  142.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  143.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
  144.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  145.     /* NE2(PG9) configuration */
  146.     GPIO_StructInit(&GPIO_InitStructure);
  147.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
  148.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  149.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  150.     GPIO_Init(GPIOG, &GPIO_InitStructure);
  151. }


  152. /*******************************************************************************
  153. * @brief      
  154. * @param      
  155. * @retval      
  156. * @attention   
  157. *******************************************************************************/
  158. void NOR_InitFSMC(void)
  159. {
  160.     FSMC_InitTypeDef              FSMC_InitStructure;
  161.     FSMC_NORSRAM_Bank_InitTypeDef FSMC_BankInitStructure;

  162.     RCC_AHB3PeriphClockCmd(RCC_AHB3ENR_FSMC, ENABLE);

  163.     FSMC_NORSRAM_BankStructInit(&FSMC_BankInitStructure);
  164.     FSMC_BankInitStructure.FSMC_SMReadPipe      = 0;
  165.     FSMC_BankInitStructure.FSMC_ReadyMode       = 0;
  166.     FSMC_BankInitStructure.FSMC_WritePeriod     = 5;    /* W:WE Pulse Width         : [0, 63] */
  167.     FSMC_BankInitStructure.FSMC_WriteHoldTime   = 3;    /* W:Address/Data Hold Time : [0,  3] */
  168.     FSMC_BankInitStructure.FSMC_AddrSetTime     = 3;    /* W:Address Setup Time     : [0,  3] */
  169.     FSMC_BankInitStructure.FSMC_ReadPeriod      = 8;    /* R:Read Cycle Time        : [0, 63] */
  170.     FSMC_BankInitStructure.FSMC_DataWidth       = FSMC_DataWidth_16bits;
  171.     FSMC_NORSRAM_Bank_Init(&FSMC_BankInitStructure, FSMC_NORSRAM_BANK1);

  172.     FSMC_NORSRAMStructInit(&FSMC_InitStructure);
  173.     FSMC_InitStructure.FSMC_Mode                = FSMC_Mode_NorFlash;
  174.     FSMC_InitStructure.FSMC_TimingRegSelect     = FSMC_TimingRegSelect_1;
  175.     FSMC_InitStructure.FSMC_MemSize             = FSMC_MemSize_64MB;
  176.     FSMC_InitStructure.FSMC_MemType             = FSMC_MemType_FLASH;
  177.     FSMC_InitStructure.FSMC_AddrDataMode        = FSMC_AddrDataDeMUX;
  178.     FSMC_NORSRAMInit(&FSMC_InitStructure);
  179. }


  180. /*******************************************************************************
  181. * @brief      
  182. * @param      
  183. * @retval      
  184. * @attention   
  185. *******************************************************************************/
  186. void NOR_Init(void)
  187. {
  188.     NOR_InitGPIO();

  189.     NOR_InitFSMC();
  190. }


  191. /******************* (C) COPYRIGHT 2022 *************************END OF FILE***/


程序跳转代码
  1. /*******************************************************************************
  2. * @file    main.c
  3. * @author  King
  4. * @version V1.00
  5. * @date    25-Jan-2021
  6. * @brief   ......
  7. *******************************************************************************/


  8. /* Define to prevent recursive inclusion -------------------------------------*/
  9. #define __MAIN_C__


  10. /* Includes ------------------------------------------------------------------*/
  11. #include "main.h"


  12. /* Private typedef -----------------------------------------------------------*/
  13. typedef void (*pFunction)(void);


  14. /* Private define ------------------------------------------------------------*/
  15. #define ApplicationAddress      ((uint32_t)0x64000000)


  16. /* Private macro -------------------------------------------------------------*/


  17. /* Private variables ---------------------------------------------------------*/
  18. uint32_t  JumpAddress  =  0;
  19. pFunction JumpToApplication;


  20. /* Private function prototypes -----------------------------------------------*/
  21. /* Private functions ---------------------------------------------------------*/


  22. /* Exported variables --------------------------------------------------------*/
  23. /* Exported function prototypes ----------------------------------------------*/


  24. /*******************************************************************************
  25. * @brief      
  26. * @param      
  27. * @retval      
  28. * @attention   
  29. *******************************************************************************/
  30. int main(void)
  31. {
  32.     NOR_Init();

  33.     /* Jump to code loaded in NOR memory and execute it ***********************/
  34.     JumpAddress = *(volatile uint32_t *)(ApplicationAddress + 4);
  35.     JumpToApplication = (pFunction)JumpAddress;

  36.     /* Initialize user application's Stack Pointer */
  37.     __set_MSP(*(volatile uint32_t *)ApplicationAddress);
  38.     JumpToApplication();

  39.     while(1);
  40. }


  41. /******************* (C) COPYRIGHT 2022 *************************END OF FILE***/


KEIL工程的相关配置:
97400620372e781c1b.png

65872620372f092c63.png

基于MM32NOR FLASH下载算法实现

在能够成功跳转到NOR FLASH运行程序后,我们就需要将应用程序下载到NOR FLASH就可以了;结合第一小结,一般MCU自带的下载算法只是将程序下载到自身内部的FLASH存储空间,如果需要将程序下载到外扩的NOR FLASH,我们可以使用烧录工具,将程序烧录进NOR FLASH,但在开发调试过程中,这显然不太方便,所以我们就需要自行编写下载算法,来实现MM32NOR FLASH之间的程序编程。

怎么去编写这个下载算法呢?

KEIL的安装路径下:C:\Keil_v5\ARM\Flash有一个_Template的下载算法工程模板,我们将其直接拷贝一份,重命名为MM32F3270_NOR_FLM;打开KEIL工程,里面主要有两个文件FlashDev.cFlashPrg.c

FlashDev.c主要是用来描述存储特性的,包括Device NameDevice TypeDevice Start AddressDevice Size in Bytes等等,这些特性的值,我们可以根据NOR FLASH的特性值来填写,编程超时时间和擦出超时时间可以尽量长一些,做些冗余;具体参考如下所示:
861646203730f005e7.png

FlashPrg.c就是用来实现编程下载算法的接口函数,其中有些函数是必须实现的,有些函数则是可选择的,如下所示:
538646203731e5cb89.png

我们需要实现的就是通过对这些函数的补充实现,来达到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格式)
9953662037341d8fd4.png

634666203734d05572.png

60367620373557619a.png

我们将这个生成的FLM下载算法文件拷贝到C:\Keil_v5\ARM\Flash目录下,在后面工程使用到的时候就可以添加进来了。

MM32实现NOR FLASH应用程序编程,下载程序并运行

对于运行在NOR FLASH中的MM32程序来说,程序编写并没有特殊的要求,唯一不同的就是对于KEIL工程的设置;例程中我们只实现了LED灯的闪烁功能,功能比较简单;对于KEIL工程的设置如下图所示:

将默认的程序空间和程序启动空间设置为NOR FLASH的起始地址作为开始:
932386203737e35237.png

根据DEBUG调试工具进行对应的选择:
34546203738e1c28a.png

下载工具与调试工具相同:
104166203739e600e1.png

将编程(下载)算法选择为第三小节生成的FLM算法,在添加进来的时候,就会自动显示相应的描述信息:
3649620373b0d09be.png

这样配置完成后,编译后点击下载按键,程序就被下载到NOR FLASH外部存储空间了,因为勾选了RESET AND RUN,下载完成后会复位MCU,此时MCU FLASH中已经存在了跳转程序,这个时候就会跳转到NOR FLASH执行LED闪烁程序;此时LED灯若能够正常运行,就说明程序功能已经正常运行了。

另外有些小伙伴会问,在Option for Target窗口Utilities选项卡中,有看到Init File会配置一个INI文件,我上述的工程配置中却没有,这是怎么回事呢?

这边的INI文件包含的是对MCU内部地址配置相应参数值的数据,是在下载程序前先对MCU进行设置的操作;一般看到的就是对MCUNOR FLASHFSMC相关寄存器进行配置,好让下载算法能够正常的去操作NOR FLASH;但我的配置截图中却没有,是因为在实现下载算法时的INIT函数,已经实现了对FSMC的初始化配置,所以在INIT FILE的位置就不需要再重复操作了。

后续:

有了这个下载算法,我们可以将部分程序或数据指令到外部存储空间;如果当我们通过LCD显示图片数据时,图片数据是一个很大的数组,我们就可以将这些数据指定到NOR FLASH中,而应用程序还是在MCU内部的FLASH中运行,操作如下所示:

芯片有两个ROM空间,但默认的和启动的为MCU内部FLASH
57445620373e6159ef.png

下载算法有两个,这两个的地址是不一样的,一个是MCU内部FLASH,一个是外扩的NOR FLASH
4630620373f8294ad.png

将程序指定到NOR FLASH的方法,右击.C文件,选择Options for File IMAGE1.c...
62532620374077f7d1.png

在弹出的窗口中将CODE/CONST指令到ROM1,如下图所示:
6597662037418242bc.png

然后在程序中再调用IMAGE1.c文件中的数据,这样在编译后下载程序的时候,会先下载程序到MCUFLASH,再下载图片数据到MCU扩展的NOR FLASH
66675620374272a718.png

附件中是具体的实现例程源工程代码,硬件是基本神舟III开发板实现的,MCU使用灵动微电子的MM32F3277G9PNOR FLASH使用M29W128FH,至此分享就结束了,希望对各位小伙伴有所帮助!
NOR_CodeExecute.zip (1.52 MB, 下载次数: 53)




打赏榜单

21小跑堂 打赏了 50.00 元 2022-02-11
理由:恭喜通过原创文章审核!请多多加油哦!

sf116 发表于 2022-2-9 16:31 | 显示全部楼层
不明觉厉,程序能同时在内部和NOR FLASH运行吗?
 楼主| xld0932 发表于 2022-2-9 16:37 | 显示全部楼层
可以的,最后一节后续中有介绍;
james03 发表于 2022-2-10 10:32 | 显示全部楼层
多谢楼主分享,学习了
海洋无限 发表于 2022-2-10 12:29 | 显示全部楼层
这个厉害
drer 发表于 2022-3-1 10:08 | 显示全部楼层
有木有相关速度的数据啊
nawu 发表于 2022-3-1 10:14 | 显示全部楼层
请问最小的擦除单位是多少呀
zljiu 发表于 2022-3-1 10:28 | 显示全部楼层
下载下来学习借鉴
tfqi 发表于 2022-3-1 10:34 | 显示全部楼层
程序在哪里运行比较快呢
coshi 发表于 2022-3-1 10:53 | 显示全部楼层
默认的就是下载到flash里边吧
 楼主| xld0932 发表于 2022-3-1 12:54 | 显示全部楼层
coshi 发表于 2022-3-1 10:53
默认的就是下载到flash里边吧

默认是下载到芯片内部的FLASH,如果需要下载到外部的NOR FLASH或者是SPI FLASH,就需要有配套的下载算法……
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:King.Xu

77

主题

3023

帖子

38

粉丝
快速回复 在线客服 返回列表 返回顶部