• STM32片外SRAM作运行内存


    本例演示用的软硬件:

    • 片内外设驱动库: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(默认版本位于STM32CubeF4DriversCMSISDeviceSTSTM32F4xxSourceTemplatesarm)
    • 有些函数在system_stm32f4xx.c(位于STM32CubeF4DriversCMSISDeviceSTSTM32F4xxSourceTemplates)

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


    1.换用官方的使用片外SRAM作运行内存的例程的启动文件
    例如STM32CubeF4ProjectsSTM324xG_EVALExamplesFSMCFSMC_SRAM_DataMemoryMDK-ARMstartup_stm32f407xx.s
    可以看到适用于使用片外SRAM运存的启动文件相较于默认版本的启动文件变化的地方有

    • 第52行、第75行:定义用于初始化片外SRAM的栈
    • 第191行~第192行:在执行main()前、执行完启动文件定义的指令后将栈顶指针恢复为默认值
    52 __initial_spTop EQU    0x20000400                 ; stack used for SystemInit & SystemInit_ExtMemCtl
    75 __Vectors       DCD     __initial_spTop            ; Top of Stack
    177 __Vectors_End
    178 
    179 __Vectors_Size  EQU  __Vectors_End - __Vectors
    180 
    181                 AREA    |.text|, CODE, READONLY
    182 
    183 ; Reset handler
    184 Reset_Handler    PROC
    185                  EXPORT  Reset_Handler             [WEAK]
    186         IMPORT  SystemInit
    187         IMPORT  __main
    188 
    189                  LDR     R0, =SystemInit
    190                  BLX     R0
    191                  LDR     R0, =__initial_sp          ; restore original stack pointer
    192                  MSR     MSP, R0
    193                  LDR     R0, =__main
    194                  BX      R0
    195                  ENDP

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

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

    那么system_stm32f4xx.c的

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

    都会被执行

    655 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)
    656  || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
    657  || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
    658 
    659 #if defined(DATA_IN_ExtSRAM)
    660 /*-- GPIOs Configuration -----------------------------------------------------*/
    661    /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
    662   RCC->AHB1ENR   |= 0x00000078;
    663   /* Delay after an RCC peripheral clock enabling */
    664   tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
    665   
    666   /* Connect PDx pins to FMC Alternate function */
    667   GPIOD->AFR[0]  = 0x00CCC0CC;
    668   GPIOD->AFR[1]  = 0xCCCCCCCC;
    669   /* Configure PDx pins in Alternate function mode */  
    670   GPIOD->MODER   = 0xAAAA0A8A;
    671   /* Configure PDx pins speed to 100 MHz */  
    672   GPIOD->OSPEEDR = 0xFFFF0FCF;
    673   /* Configure PDx pins Output type to push-pull */  
    674   GPIOD->OTYPER  = 0x00000000;
    675   /* No pull-up, pull-down for PDx pins */ 
    676   GPIOD->PUPDR   = 0x00000000;
    677 
    678   /* Connect PEx pins to FMC Alternate function */
    679   GPIOE->AFR[0]  = 0xC00CC0CC;
    680   GPIOE->AFR[1]  = 0xCCCCCCCC;
    681   /* Configure PEx pins in Alternate function mode */ 
    682   GPIOE->MODER   = 0xAAAA828A;
    683   /* Configure PEx pins speed to 100 MHz */ 
    684   GPIOE->OSPEEDR = 0xFFFFC3CF;
    685   /* Configure PEx pins Output type to push-pull */  
    686   GPIOE->OTYPER  = 0x00000000;
    687   /* No pull-up, pull-down for PEx pins */ 
    688   GPIOE->PUPDR   = 0x00000000;
    689 
    690   /* Connect PFx pins to FMC Alternate function */
    691   GPIOF->AFR[0]  = 0x00CCCCCC;
    692   GPIOF->AFR[1]  = 0xCCCC0000;
    693   /* Configure PFx pins in Alternate function mode */   
    694   GPIOF->MODER   = 0xAA000AAA;
    695   /* Configure PFx pins speed to 100 MHz */ 
    696   GPIOF->OSPEEDR = 0xFF000FFF;
    697   /* Configure PFx pins Output type to push-pull */  
    698   GPIOF->OTYPER  = 0x00000000;
    699   /* No pull-up, pull-down for PFx pins */ 
    700   GPIOF->PUPDR   = 0x00000000;
    701 
    702   /* Connect PGx pins to FMC Alternate function */
    703   GPIOG->AFR[0]  = 0x00CCCCCC;
    704   GPIOG->AFR[1]  = 0x000000C0;
    705   /* Configure PGx pins in Alternate function mode */ 
    706   GPIOG->MODER   = 0x00085AAA;
    707   /* Configure PGx pins speed to 100 MHz */ 
    708   GPIOG->OSPEEDR = 0x000CAFFF;
    709   /* Configure PGx pins Output type to push-pull */  
    710   GPIOG->OTYPER  = 0x00000000;
    711   /* No pull-up, pull-down for PGx pins */ 
    712   GPIOG->PUPDR   = 0x00000000;
    713   
    714 /*-- FMC/FSMC Configuration --------------------------------------------------*/
    715   /* Enable the FMC/FSMC interface clock */
    716   RCC->AHB3ENR         |= 0x00000001;
    734 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)
    735    || defined(STM32F412Zx) || defined(STM32F412Vx)
    736   /* Delay after an RCC peripheral clock enabling */
    737   tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
    738   /* Configure and enable Bank1_SRAM2 */
    739   FSMC_Bank1->BTCR[2]  = 0x00001011;
    740   FSMC_Bank1->BTCR[3]  = 0x00000201;
    741   FSMC_Bank1E->BWTR[2] = 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寄存器用的值。用上一段提到的方法获取适用于你的开发板的寄存器值,用本文初提到的方法获取适用于你的单片机的启动文件):

    655 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)
    656  || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
    657  || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
    658 
    659 #if defined(DATA_IN_ExtSRAM)
    660 /*-- GPIOs Configuration -----------------------------------------------------*/
    661    /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
    662   RCC->AHB1ENR   |= 0x00000078;
    663   /* Delay after an RCC peripheral clock enabling */
    664   tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
    665   
    666   /* Connect PDx pins to FMC Alternate function */
    667   GPIOD->AFR[0]  = 0x00CC00CC;
    668   GPIOD->AFR[1]  = 0xCCCCCCCC;
    669   /* Configure PDx pins in Alternate function mode */  
    670   GPIOD->MODER   = 0xAAAA0A0A;
    671   /* Configure PDx pins speed to 100 MHz */  
    672   GPIOD->OSPEEDR = 0xFFFF0F0F;
    673   /* Configure PDx pins Output type to push-pull */  
    674   GPIOD->OTYPER  = 0x00000000;
    675   /* No pull-up, pull-down for PDx pins */ 
    676   GPIOD->PUPDR   = 0x00000000;
    677 
    678   /* Connect PEx pins to FMC Alternate function */
    679   GPIOE->AFR[0]  = 0xC00000CC;
    680   GPIOE->AFR[1]  = 0xCCCCCCCC;
    681   /* Configure PEx pins in Alternate function mode */ 
    682   GPIOE->MODER   = 0xAAAA800A;
    683   /* Configure PEx pins speed to 100 MHz */ 
    684   GPIOE->OSPEEDR = 0xFFFFC00F;
    685   /* Configure PEx pins Output type to push-pull */  
    686   GPIOE->OTYPER  = 0x00000000;
    687   /* No pull-up, pull-down for PEx pins */ 
    688   GPIOE->PUPDR   = 0x00000000;
    689 
    690   /* Connect PFx pins to FMC Alternate function */
    691   GPIOF->AFR[0]  = 0x00CCCCCC;
    692   GPIOF->AFR[1]  = 0xCCCC0000;
    693   /* Configure PFx pins in Alternate function mode */   
    694   GPIOF->MODER   = 0xAA000AAA;
    695   /* Configure PFx pins speed to 100 MHz */ 
    696   GPIOF->OSPEEDR = 0xFF000FFF;
    697   /* Configure PFx pins Output type to push-pull */  
    698   GPIOF->OTYPER  = 0x00000000;
    699   /* No pull-up, pull-down for PFx pins */ 
    700   GPIOF->PUPDR   = 0x00000000;
    701 
    702   /* Connect PGx pins to FMC Alternate function */
    703   GPIOG->AFR[0]  = 0x00CCCCCC;
    704   GPIOG->AFR[1]  = 0x00000C00;
    705   /* Configure PGx pins in Alternate function mode */ 
    706   GPIOG->MODER   = 0x00200AAA;
    707   /* Configure PGx pins speed to 100 MHz */ 
    708   GPIOG->OSPEEDR = 0x00300FFF;
    709   /* Configure PGx pins Output type to push-pull */  
    710   GPIOG->OTYPER  = 0x00000000;
    711   /* No pull-up, pull-down for PGx pins */ 
    712   GPIOG->PUPDR   = 0x00000000;
    713   
    714 /*-- FMC/FSMC Configuration --------------------------------------------------*/
    715   /* Enable the FMC/FSMC interface clock */
    716   RCC->AHB3ENR         |= 0x00000001;
    734 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)
    735    || defined(STM32F412Zx) || defined(STM32F412Vx)
    736   /* Delay after an RCC peripheral clock enabling */
    737   tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
    738   /* Configure and enable Bank1_SRAM3 */
    739   FSMC_Bank1->BTCR[4] = 0x00001091;
    740   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           19    .data               main.o
    0x68000008   0x08006294   0x00000008   Data   RW          247    .data               stm32f4xx_hal_msp.o
    0x68000010   0x0800629c   0x0000000c   Data   RW         1539    .data               stm32f4xx_hal.o
    0x6800001c   0x080062a8   0x00000004   Data   RW         1772    .data               system_stm32f4xx.o
    0x68000020   0x080062ac   0x00000004   Data   RW         1842    .data               tftlcd.o
    0x68000024        -       0x00000050   Zero   RW           18    .bss                main.o
    0x68000074        -       0x0000000e   Zero   RW         1840    .bss                tftlcd.o
    0x68000082   0x080062b0   0x00000006   PAD
    0x68000088        -       0x00000400   Zero   RW            1    STACK               startup_stm32f407xx.o

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

  • 相关阅读:
    Coin-row problem(1139)
    算法的稳定性
    折半查找的实现(1010)swust-oj
    判断回文(0315)SWUST-OJ
    逆置单链表(0957)swust-oj
    单链表上查找算法的实现(0955) swust-oj
    单链表的插入操作的实现(0952)SUWST-OJ
    单链表的链接(0954)swust-oj
    单链表的删除操作的实现(0953)swust-oj
    ASP.net core 2.0.0 中 asp.net identity 2.0.0 的基本使用(三)—用户账户及cookie配置
  • 原文地址:https://www.cnblogs.com/Humorize/p/stm32-external-sram.html
Copyright © 2020-2023  润新知