项目使用STM32F407ZET6开发,但自带的RAM空间不够,所以需要外扩SRAM作为默认的RAM来使用,使用的SRAM是IS62WV51216BLL,19条地址线,16条数据线,使用的库为HAL库。
外扩的SRAM使用FSMC的NE3作为硬件接口,所以外扩的重要步骤其实是NE3作为SRAM的初始化。
第一步:勾选魔术棒下面的选项,这样才能使其作为默认的RAM来分配变量
第二步就是FSMC的初始化,由于变量拷贝到RAM中初始化这个过程是在进入main函数之前完成的,所以初始化必须在启动文件LDR R0, =__main 之前完成,这里其实有2个选择,一个是调用自己写的C函数(调用FSMC库函数),一个是通过SystemInit函数中的SystemInit_ExtMemCtl函数配置寄存器来完成,这里我们选择第二种方式。
那么我们需要先将DATA_IN_ExtSRAM添加到魔术棒C/C++选项的Define中,这样SystemInit才会调用SystemInit_ExtMemCtl函数
下一步就是修改寄存器的配置,SystemInit_ExtMemCtl函数407部分FSMC的配置默认是NE2的。找到407部分(有2部分,一部分为引脚配置,一部分为FSMC配置,找到有defined(STM32F407xx)字样的代码部分就是)将寄存器配置修改为以下内容
#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[0] = 0x00CC00CC;
GPIOD->AFR[1] = 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[0] = 0xC00000CC;
GPIOE->AFR[1] = 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[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 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[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0x00000C00;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00200AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x000C03FF;
/* 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;
第二部分FSMC配置:
#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[4] = 0x00001011;
FSMC_Bank1->BTCR[5] = 0x00000201;
FSMC_Bank1E->BWTR[4] = 0x0FFFFFFF;
需要注意的是,我是19条地址线,16条数据线,即地址为19位,数据位为16位,如果不同自己需要修改对应寄存器,包括引脚部分配置,最好能百度下这些寄存器意义,然后对照电路图设置即可。
到这步就成功了,可以写个程序验证往对应RAM地址写数据是否成功或者对应外设运行在该段RAM中是否能初始化成功,能正常使用(我自己的使用体验的话,初始化不成功,连main函数都进入不了就会跑飞)。
--------------------------------------------------------------------------------------------------------------------------------
隔断一下,聊一下1.使用库函数写初始化函数再在启动函数中调用的方式,还有2.在main函数中初始化FSMC 这2种方式。
第一种方式,如果使用官方库而不是HAL库,是可以运行的,我使用正点原子官方库例程修改后可以运行,但是使用HAL库,直接无法进入main程序跑飞,取消勾选第一张图配置,可以正常运行,但各项外设初始化无法成功,实际上无法使用。
第二种方式,只能是不作为默认RAM使用时这样配置。
至于这2种情况是为什么,个人时间和能力有限,没有去深究