本例演示用的软硬件:

  • 片内外设驱动库:STM32CubeF41.24.1的HAL库1.7.6,2019年4月12日
  • IDE:MDK-ARM 5.28.0.0,2019年5月
  • 开发板:片外SRAM挂在FSMC_NORPSRAM3,16bit×219=1MiB

本例的目的是让编程人员使用片外SRAM就像使用片内SRAM一样,即不用把任何变量声明到指定的RAM地址、连接器也能自动地把片外SRAM作为变量的存储空间
如果把所有需要被放到片外SRAM的变量用__attribute__((at()))、指针等声明到片外SRAM,那么完全不用像本例这样


执行main()前执行片内Flash上初始化FSMC及其GPIO的指令:

  • 有些指令由启动文件的汇编代码生成,例如对于本例的STM32F407ZG来说这个启动文件就是startup_stm32f407xx.s(默认版本位于STM32CubeF4\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm)
  • 有些函数在system_stm32f4xx.c(位于STM32CubeF4\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\)

对于本例的STM32F407来说修改上述的2个源文件的方法是:

1.换用官方的使用片外SRAM作运行内存的例程的启动文件
例如STM32CubeF4\Projects\STM324xG_EVAL\Examples\FSMC\FSMC_SRAM_DataMemory\MDK-ARM\startup_stm32f407xx.s
可以看到适用于使用片外SRAM运存的启动文件相较于默认版本的启动文件变化的地方有

  • 第52行、第75行:定义用于初始化片外SRAM的栈
  • 第191行~第192行:在执行main()前、执行完启动文件定义的指令后将栈顶指针恢复为默认值
 __initial_spTop EQU    0x20000400                 ; stack used for SystemInit & SystemInit_ExtMemCtl
 __Vectors       DCD     __initial_spTop            ; Top of Stack
 __Vectors_End

 __Vectors_Size  EQU  __Vectors_End - __Vectors

                 AREA    |.text|, CODE, READONLY

 ; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main LDR R0, =SystemInit
BLX R0
LDR R0, =__initial_sp ; restore original stack pointer
MSR MSP, R0
LDR R0, =__main
BX R0
ENDP

2.取消注释system_stm32f4xx.c的第96行

 /************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
/* #define DATA_IN_ExtSRAM */
#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
STM32F412Zx || STM32F412Vx */

那么system_stm32f4xx.c的

  • 第662行~第716行

    • 开启FSMC模块用到的GPIO的时钟(第662行)
    • 配置相应GPIO口的模式、速度等信息(第667行~第712行)
    • 开启FSMC模块的时钟(第716行))
  • 第737行~第741行
    • 配置FSMC_NORPSRAM的控制、时序(第739行~第741行)

都会被执行

 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) #if defined(DATA_IN_ExtSRAM)
/*-- GPIOs Configuration -----------------------------------------------------*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHB1ENR |= 0x00000078;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); /* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[] = 0x00CCC0CC;
GPIOD->AFR[] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[] = 0xC00CC0CC;
GPIOE->AFR[] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[] = 0x00CCCCCC;
GPIOF->AFR[] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 100 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[] = 0x00CCCCCC;
GPIOG->AFR[] = 0x000000C0;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00085AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x000CAFFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000; /*-- FMC/FSMC Configuration --------------------------------------------------*/
/* Enable the FMC/FSMC interface clock */
RCC->AHB3ENR |= 0x00000001;
 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
|| defined(STM32F412Zx) || defined(STM32F412Vx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
/* Configure and enable Bank1_SRAM2 */
FSMC_Bank1->BTCR[] = 0x00001011;
FSMC_Bank1->BTCR[] = 0x00000201;
FSMC_Bank1E->BWTR[] = 0x0FFFFFFF;

从system_stm32f4xx.c的第738行的注释可知,第739行~第741行分别配置的是FSMC_NORPSRAM2的控制寄存器、读写时序寄存器、写时序寄存器,而我使用的开发板的片外SRAM挂在FSMC_NORPSRAM3,所以需要修改system_stm32f4xx.c上述的写GPIO寄存器、FSMC寄存器的代码,获取正确的寄存器值的方法是核外片内外设只开启FSMC_NORPSRAM3及其GPIO,再在硬件调试过程中复制出相应的寄存器值

3.更正system_stm32f4xx.c的上述代码

(再次提醒没仔细读题的读者:下文的代码只被保证适用于( (STM32F407ZG) && (片外SRAM挂在FSMC_NORPSRAM3) && (片外SRAM是16bit×219=1MiB) )的情况,且应该根据你用的SRAM芯片、STM32的AHB总线时钟频率等信息修改第739行~第741行配置FSMC寄存器用的值。用上一段提到的方法获取适用于你的开发板的寄存器值,用本文初提到的方法获取适用于你的单片机的启动文件):

 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) #if defined(DATA_IN_ExtSRAM)
/*-- GPIOs Configuration -----------------------------------------------------*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHB1ENR |= 0x00000078;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); /* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[] = 0x00CC00CC;
GPIOD->AFR[] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A0A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0F0F;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000; /* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[] = 0xC00000CC;
GPIOE->AFR[] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA800A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC00F;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[] = 0x00CCCCCC;
GPIOF->AFR[] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 100 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[] = 0x00CCCCCC;
GPIOG->AFR[] = 0x00000C00;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00200AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x00300FFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000; /*-- FMC/FSMC Configuration --------------------------------------------------*/
/* Enable the FMC/FSMC interface clock */
RCC->AHB3ENR |= 0x00000001;
 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
|| defined(STM32F412Zx) || defined(STM32F412Vx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
/* Configure and enable Bank1_SRAM3 */
FSMC_Bank1->BTCR[4] = 0x00001091;
FSMC_Bank1->BTCR[5] = 0x00100222;

4.在MDK把FSMC_NORPSRAM3映射的地址范围0x68000000~0x6BFFFFFF的首1M设为运行内存

把0x68000000、0x100000分别填入下图窗口右下角的"Read/Write Memory Areas"的”off-chip“的任一行:

5.修改完后Reuild

(注意:如果你用MDK-ARM以外的软件修改了前述的2个源文件,那么MDK-ARM可能不知道你修改了那2个文件,所以如果仅Build,那么IDE可能会拿编译旧版本的源文件得到的目标文件进行连接

或者你手动让MDK-ARM知道你修改过那些文件再仅Build,比如在MDK-ARM打开前述的2个源文件,在里面随便找个地方加个字再删掉那个字了再Build)

从MAP文件可以看到,变量被分配到了片外SRAM映射的地址范围0x68000000~0x68100000中,且单片机程序能正常

Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

0x68000000   0x0800628c   0x00000008   Data   RW               .data               main.o
0x68000008 0x08006294 0x00000008 Data RW .data stm32f4xx_hal_msp.o
0x68000010 0x0800629c 0x0000000c Data RW .data stm32f4xx_hal.o
0x6800001c 0x080062a8 0x00000004 Data RW .data system_stm32f4xx.o
0x68000020 0x080062ac 0x00000004 Data RW .data tftlcd.o
0x68000024 - 0x00000050 Zero RW .bss main.o
0x68000074 - 0x0000000e Zero RW .bss tftlcd.o
0x68000082 0x080062b0 0x00000006 PAD
0x68000088 - 0x00000400 Zero RW STACK startup_stm32f407xx.o

希望CubeMX以后的版本能自动将片外RAM设为运存

STM32片外SRAM作运行内存的更多相关文章

  1. 将STM32F407片外SRAM作运行内存

    本例演示用的软硬件: 片内外设驱动库:STM32CubeF41.24.1的HAL库1.7.6,2019年4月12日 IDE:MDK-ARM 5.28.0.0,2019年5月 开发板:片外SRAM挂在F ...

  2. STM32标准外设库中USE_STDPERIPH_DRIVER, STM32F10X_MD的含义

    在项目中使用stm32标准外设库(STM32F10x Standard Peripherals Library)的时候,我们会在项目的选项中预定义两个宏定义:USE_STDPERIPH_DRIVER, ...

  3. 外部SRAM实验,让STM32的外部SRAM操作跟内部SRAM一样(转)

    源:外部SRAM实验,让STM32的外部SRAM操作跟内部SRAM一样 前几天看到开源电子论坛(openedv.com)有人在问这个问题,我特意去做了这个实验,这样用外部SRAM就跟用内部SRAM一样 ...

  4. STM32标准外设库、 HAL库、LL库

    工作以来一直使用ST的STM32系列芯片,ST为开发者提供了非常方便的开发库.到目前为止,有标准外设库(STD库).HAL库.LL库 三种.前两者都是常用的库,后面的LL库是ST最近才添加,目前支持的 ...

  5. JS画几何图形之六【过直线外一点作垂线】

    样例:http://www.zhaojz.com.cn/demo/draw10.html 依赖:[点].[直线] //过直线外一点画垂线 function drawVerticalLine(point ...

  6. JS画几何图形之五【过圆外一点作切线】

    样例:http://www.zhaojz.com.cn/demo/draw9.html 依赖:[点].[直线].[圆] //画切线 //point 圆外的一点 //dot 圆心 //r 半径 func ...

  7. stm32 flash和sram

    FLASH是用来存储程序的,SRAM是用来存储程序运行中的中间变量

  8. MT【45】抛物线外一点作抛物线的切线(尺规作图题)

    注1:S为抛物线焦点 注2:由切线的唯一性,以及切线时可以利用MT[42]评得到三角形全等从而得到切线平分$\angle MQS$得到

  9. stm32 FSMC-外扩SRAM IS62WV51216

    引脚定义 FSMC配置步骤 1.使能对应引脚GPIO时钟 2.配置GPIO引脚模式 3.使能FSMC时钟 4.FSMC初始化 5.存储器块使能 举例 #define Bank1_SRAM3_ADDR ...

随机推荐

  1. Hexo + Serverless Framework,简单三步搭建你的个人博客

    很多人都想拥有自己的个人博客,还得看起来漂亮.酷酷的.尤其对开发者来说,不仅可以分享技术(装)心得(逼),面试的时候还能成为加分.这里介绍两款好用的神器,不用忙前(前端)忙后(后端),简单3min即可 ...

  2. BFS小记

    题目:求从S走到G点所需步数 #S######.#......#..#.#.##.##.#.#........##.##.####....#....#.#######.#....#......#### ...

  3. Netty快速入门(01)Linux I/O模型介绍

    Netty简述 Netty是一个高性能的网络编程框架. 上面提到了几个关键的字眼,高性能,网络编程,框架.这些概括Netty的本质. Netty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务 ...

  4. [转载] Windows系统批处理延迟方法

    小贴士:方法四 亲测有效,因为当时对于精确度要求不是很高,所以没有具体测试它的精确度.其他方法没有测过,用到的时候再测吧! 批处理延时启动的几个方法 方法一:ping 缺点:时间精度为1秒,不够精确 ...

  5. 【设计模式】 (2)关于UML

    UML -- Unified Modeling Lanaguage(统计建模语言),是一种软件系统分析和设计的语言工具,他用于帮助软件开发人员进行思考和记录思路的结果. UML本身是一套符号的规定,就 ...

  6. Spark集群-Standalone 模式

    Spark 集群相关 table td{ width: 15% } 来源于官方, 可以理解为是官方译文, 外加一点自己的理解. 版本是2.4.4 本篇文章涉及到: 集群概述 master, worke ...

  7. Java小白集合源码的学习系列:Vector

    目录 Vector源码学习 Vector继承体系 Vector核心源码 基本属性 构造器 扩容机制 Enumeration 概述 源码描述 具体操作 Vector总结 Vector源码学习 前文传送门 ...

  8. hadoop各版本hadoop.dll和winutils.exe缺少这两个文件

    1.1 缺少winutils.exeCould not locate executable null \bin\winutils.exe in the hadoop binaries1.2 缺少had ...

  9. lvs+keepalived部署k8s v1.16.4高可用集群

    一.部署环境 1.1 主机列表 主机名 Centos版本 ip docker version flannel version Keepalived version 主机配置 备注 lvs-keepal ...

  10. Docker学习(十一)Docker系列结束-新的开始K8S

    Docker学习(十一)Docker系列结束-新的开始K8S 标签(空格分隔): docke k8s Docker系列结束 上一篇讲到使用docker官方提供的容器编排工具docker-compose ...