本例演示用的软硬件:

  • 片内外设驱动库: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. 入门gulp前端构建工具

    1. 全局安装 gulp:(倘若之前电脑安装过,则跳过此步骤) $ cnpm install -g gulp 2. 作为项目的开发依赖(devDependencies)安装: (此步骤会自动在目录下创 ...

  2. 小技巧(2) 查询自己博客的SEO(如果违规,请先提醒)

    今天,教大家查看自己博客的SEO. 首先,上网站http://seo.chinaz.com/ 接着,在网页输入框中输入自己博客地址(带后面路径,不是cnblogs.com这样的,类似https://w ...

  3. YOLOv3 K-means获取anchors大小

    YOLOv1和YOLOv2简单看了一下,详细看了看YOLOv3,刚看的时候是蒙圈的,经过一番研究,分步记录一下几个关键的点: v2和v3中加入了anchors和Faster rcnn有一定区别,这个a ...

  4. CS0656 缺少编译器要求的成员“Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create”

    问题出现原因:在net core使用动态类型dynamic,在编译的时候提示错误信息如上. 解决方案: 1.不用dynamic类型 2.在使用的地方添加一个dll,Microsoft.CSharp,或 ...

  5. python文档字符串(函数使用说明)

    关键字: 函数说明.help()函数 1.效果图: 2.代码: # 文档字符串( doc str) 是 函数使用说明 # 用法: 在函数第一行写一个字符串 def fn(*nums): ''' 函数的 ...

  6. 【UEFI&BIOS】---BIOS开机串口报"ERROR: C2:V1050007 IO 93B80003-9FB3-11D4-9A3A-0090273FC14D 6413FA18"的分析

    intel的X86 CPU对运行错误的处理已经做的非常完善了,一般即使是开机卡死,跑飞等各种问题也会丢给你相关的提示信息,那么掌握这种错误的分析手段就显得至关重要.在实际开发的过程中,我遇到了一个错误 ...

  7. Django自定义状态码

    class BaseResponse: def __init__(self): self.code = 1000 self.data = None self.error = None @propert ...

  8. MNIST数据集

    一.MNIST数据集分类简单版本 import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_data # ...

  9. beta版本发布说明与总结

    1.发布说明: 软件介绍: deta版本的发布最终是一个可安装使用的窗体程序,已经由Alpha版本的应用解决方案完成到一个程序: deta版本解决了Alpha版本遗留的软件技术方面错误问题,以及针对有 ...

  10. selenium,滚到页面底部的方法

    你可以用 execute_script方法来处理这个. 调用原生javascript的API,这样你想滚到哪里就能滚到哪里.   下面的代码演示了如何滚到页面的最下面:   driver.execut ...