本例演示用的软硬件:

  • 片内外设驱动库: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个源文件的方法是:

  • 换用官方的使用片外SRAM作运行内存的例程的启动文件,例如STM32CubeF4\Projects\STM324xG_EVAL\Examples\FSMC\FSMC_SRAM_DataMemory\MDK-ARM\startup_stm32f407xx.s

可以看到适用于使用片外SRAM运存的启动文件相较于默认版本的启动文件变化的地方有

    • 第52行:定义用于初始化片外SRAM的栈
    • 第75行:让栈顶指针指向第52行定义的栈
    • 第191行~第192行:在执行main()前、执行完启动文件定义的指令后将栈顶指针恢复为默认值
 __initial_spTop EQU    0x20000400                 ; stack used for SystemInit & SystemInit_ExtMemCtl
 __Vectors       DCD     __initial_spTop            ; Top of Stack
                  LDR     R0, =__initial_sp          ; restore original stack pointer
                  MSR     MSP, R0  
  • 取消注释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,再在硬件调试过程中复制出相应的寄存器值,于是

  • 更正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[] = 0x00001091;
   FSMC_Bank1->BTCR[] = 0x0FFFFFFF;
  • 在MDK把FSMC_NORPSRAM3映射的地址范围0x68000000~0x6BFFFFFF的首1M设为运行内存

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

修改完后Reuild(注意:MDK-ARM可能不知道用户修改了哪些文件,所以如果仅Build,那么IDE可能会拿编译旧版本的源文件得到的目标文件进行连接)

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


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

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

  1. STM32片外SRAM作运行内存

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

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

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

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

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

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

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

  5. STM32F103片外运行代码分析

    STM32F103片外运行代码分析 STM32F103有三种启动方式: 1.从片内Flash启动: 2.从片内RAM启动: 3.从片内系统存储器启动,内嵌的自举程序,用于串口IAP. 无法直接在片外N ...

  6. DSP28335的XINTF操作SRAM实验

    1. 本次使用三兄弟的XDS28335开发板,研究一下XINTF操作SRAM的代码.哈弗结构,奇怪,DSP28335是哈弗结构,那么数据和程序空间应该独立的,为啥书上说采用统一的寻址方式?估计只是读写 ...

  7. 第51章 设置FLASH的读写保护及解除—零死角玩转STM32-F429系列

    第51章     设置FLASH的读写保护及解除 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...

  8. EasyUI-panel 内嵌页面上的js无法被执行

    声明: http://www.jeasyuicn.com/post-49.html 本文引用自GodSon的杰作 http://www.jeasyuicn.com/post-49.html,除修正了个 ...

  9. Chrome Apps將是Google送給微軟的特洛伊木馬?

    今天,Google 發表了 Chrome Apps,不同於之前 web app,此舉是要把 Chrome 瀏覽器升級為真正的 app 平台,將 Chrome OS 發展成一個成熟的作業系統,可以視為 ...

随机推荐

  1. docker使用阿里云加速器

    1 登录阿里云获得地址 登录https://cr.console.aliyun.com ,点击"镜像加速器",会给我一个地址. 2 写入/etc/docker/daemon.jso ...

  2. javalite 使用druid数据库连接池配置

    在pom文件中引入jar包 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid& ...

  3. numpy基本知识

    """np.arrayobject 数组或嵌套的数列dtype 数组元素的数据类型,可选copy 对象是否需要复制,可选order 创建数组的样式,C为行方向,F为列方向 ...

  4. 线程上下文类加载器ContextClassLoader内存泄漏隐患

    前提 今天(2020-01-18)在编写Netty相关代码的时候,从Netty源码中的ThreadDeathWatcher和GlobalEventExecutor追溯到两个和线程上下文类加载器Cont ...

  5. colab上基于tensorflow2.0的BERT中文多分类

    bert模型在tensorflow1.x版本时,也是先发布的命令行版本,随后又发布了bert-tensorflow包,本质上就是把相关bert实现封装起来了. tensorflow2.0刚刚在2019 ...

  6. sqlserver2008:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。

    在开始菜单中找到: 进入,点击左侧SQL Server服务, 将SQL Server(MSSQL.....)服务开启, 即可成功连接.

  7. TypeScript 源码详细解读(4)语法1-语法树

    在上一节介绍了标记的解析,就相当于识别了一句话里有哪些词语,接下来就是把这些词语组成完整的句子,即拼装标记为语法树. 树(tree) 树是计算机数据结构里的专业术语.就像一个学校有很多年级,每个年级下 ...

  8. BZOJ4559 成绩比较

    题目传送门 分析: 我们可以先试着求一下,对于单个学科,有多少种分配方案可以使B神排名为R 对于第i个学科 \(~~~~g(i)=\sum_{j=1}^{H_i}j^{n-R_i}(H_i-j)^{R ...

  9. Educational Codeforces Round 80 (Rated for Div. 2) E. Messenger Simulator

    可以推出 min[i]要么是i要么是1,当a序列中存在这个数是1 max[i]的话就比较麻烦了 首先对于i来说,如果还没有被提到第一位的话,他的max可由他后面的这部分序列中 j>=i 的不同数 ...

  10. 通过识别页面内容获得返回值判断后续执行(exists指令的用法)

    本案例主要用到airtest 的exists指令 从指令解释可以知道,当判断某图片不存在的时候,会返回false值 脚本思路即为如果返回值==false则执行A,!=fales则执行B 下图脚本思路, ...