微控制器的FSMC到底是咋回事?(上)

控制/MCU

1878人已加入

描述

摘要:玩单片机的难免要和内存和屏幕打交道,那就不得不说一下FSMC,掌握了他基本你就知道单片机是如何与他们进行通讯的了。本文较长因此分了两篇文章来说明,如有不同意见请在评论区留言。

一、概述

STM32控制器芯片内部有一定大小的SRAM及FLASH作为内存和程序存储空间,但当程序较大,内存和程序空间不足时,就需要在 STM32芯片的外部扩展存储器了。

扩展内存时一般使用SRAM和SDRAM存储器,但STM32F407系列的芯片不支持扩展 SDRAM(STM32F429系列支持),它仅支持使用FSMC外设扩展 SRAM,我们以SRAM为例讲解如何为STM32扩展内存。

给STM32芯片扩展内存与给PC扩展内存的原理是一样的,只是PC上一般以内存条的形式扩展,内存条实质是由多个内存颗粒(即SRAM芯片)组成的通用标准模块,而STM32直接与SRAM 芯片连接。

二、SRAM的简介

大家都知道,当电脑运行比较卡的时候,我们可以通过给电脑加装内存条来改善电脑的性能。那么号称微型计算机的单片机能不能像电脑一样加装内存条呢?装内存条倒是不行,但是我们可以给单片机外加和内存条效果一样的SRAM来提升单片机的性能。下面以STM32F407ZGT6单片机来讲解一下来扩展外部SRAM。

原理:给STM32芯片扩展内存与给PC扩展内存的原理是一样的,只是PC上一般以内存条的形式扩展,内存条实质是由多个内存颗粒(即SRAM芯片)组成的通用标准模块,而STM32直接与SRAM芯片连接。

SRAM,型号IS62WV51216,管脚图如下:

STM32

STM32

一种 SRAM 芯片的内部结构框图

IS62WV51216的管脚总的来说大致分为:电源线、地线、地址线、数据线、片选线、写使能端、读使能端和数据掩码信号线。

STM32

数据手册截图,原汁原味

STM32

什么是数据掩码信号呢UB#和LB#?

用UB#或LB#线控制数据宽度,例如,当要访问宽度为16位的数据时,使用行地址线指出地址,然后把UB#和LB#线都设置为低电平,那么 I/O0-I/O15线都有效,它们一起输出该地址的16位数据(或者接收16位数据到该地址);当要访问宽度为 8位的数据时,使用行地址线指出地址,然后把UB#或LB#其中一个设置为低电平,I/O会对应输出该地址的高8位和低8位数据,因此它们被称为数据掩码信号。如果不太明白接着往下看。

因为IS62WV51216是有LB和UB引脚的,可以控制字节的有效性,所以编程操作的时候我们是可以进行任意字节位宽的数据操作的。如果换作其他不支持字节通道访问的芯片的话,那就需要对齐芯片的数据位宽进行数据操作了。在网上查资料时看到有人问“在操作不同的数据位宽时,FSMC_NBL1,FSMC_NBL0是受什么控制输出高低电平给UB,LB的?”,这个应该是属于硬件自动实现的,是FSMC的硬件机制。

从这个图中我们可以看出IS62WV51216有19根地址线和16根数据线,从这些数据中我们可以分析出IS62WV51216的存储大小为1M,那么这个1M是怎么分析出来的呢?我们得来说说IS62WV51216的存储原理。首先,我们来谈一谈一般的RAM的存储原理。

CPU编址以字节(8bit)为单位。存储器编址:以其位宽为单位,也就是说每个存储器地址下的数据位数为位宽。芯片有19根数据线,那么它的芯片的可寻址空间大小就是2^19=254288=512K,又因为它的数据位宽位16(16根数据线),所以这个芯片的容量位512KB*16bit=8192Kbit=1024KByte=1MByte。

2.1 RAM的存储原理

RAM是“Random Access Memory”的缩写,被译为随机存储器。所谓随机存取,指的是当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关。根据 RAM的存储机制,又分为动态随机存储器 DRAM(Dynamic RAM)以及静态随机存储器 SRAM(Static RAM)两种。不管是DRAM还是SRAM他们都是在RAM前面加了一个头而已。

2.2 静态随机存储器SRAM

静态随机存储器SRAM(Static RAM)顾名思义电路结构不需要定时刷新充电,就能保持状态(当然,如果断电了,数据还是会丢失的),因为不需要定时刷心充电,所以SRAM的存储单元以锁存器来存储数据,这种存储器被称为“静态(Static)”RAM。

2.3 动态随机存储器DRAM

而动态随机存储器DRAM(Dynamic RAM)顾名思义电路结构是需要定时刷新充电,因为需要定时刷心充电所以DRAM的存储单元以电容的电荷来表示数据,这种存储器被称为“动态(Dynamic)”RAM。

STM32

SRAM的存储单元  

STM32

DRAM的存储单元

从他们的存储单元的结构图我们就知道DRAM的结构比SRAM的结构简单的多,所以所以生产相同容量的存储器,DRAM 的成本要更低,且集成度更高。而DRAM中的电容结构则决定了它的存取速度不如SRAM。这种结论是不需要死记硬背的,看结构图就知道了。

但是我们可能还听说过SDRAM,我们把它叫做同步动态随机存储器SDRAM(Synchronous DRAM),同步顾名思义就是利用时钟进行同步的通讯时序,它在时钟的上升沿表示有效数据。

STM32

2.4 SRAM的存储模型

STM32

SRAM 存储阵列模型

SRAM的存储模型我们可以用矩阵来说明:

SRAM内部包含的存储阵列,可以把它理解成一张表格,数据就填在这张表格上。和表格查找一样,指定一个行地址和列地址,就可以精确地找到目标单元格,这是SRAM芯片寻址的基本原理。这样的每个单元格被称为存储单元,而这样的表则被称为存储矩阵。地址译码器把N根地址线转换成2的N次方根信号线,每根信号线对应一行或一列存储单元,通过地址线找到具体的存储单元,实现寻址。如果存储阵列比较大,地址线会分成行和列地址,或者行、列分时复用同一地址总线,访问数据寻址时先用地址线传输行地址再传输列地址。

但是呢?你会发现,这个原理好像不太适用于IS62WV51216,为什么呢?

其实不然,因为我们使用的SRAM比较小(IS62WV51216容量是1MB),IS62WV51216没有列地址线。它只有19根行地址线,那么,我们就可以这么来解释:IS62WV51216有16根数据线,也就是说它的数据宽度为16位,一个行地址也就对应16位,即一个行地址对应 2字节空间。

好,那现在来计算一下IS62WV51216有多少个行地址。2的19次方等于512K,在512K的基础之上在乘我们之前计算的2字节,不正好是1024K,也就是1M吗?1M后面的单位是B,即Byte,而不是Bit哦。这样的话你就会发现IS62WV51216这个名字中本身就包含了大量的信息:IS62WV51216共有512K个行地址,数据宽度为16位,再加以计算就可以得到它的存储大小为1M啦,有趣吧!另外,该芯片支持两种不同的高速访问时间,分别为45ns和55ns,该时间表示进行一次数据读写的最短时间要求,本文选择55ns的模式。

2.5 通信方式

异步通讯,无须时钟,无须刷新,与STM32F407单片机通过FSMC接口相连。

SRAM的读写流程

STM32

数据手册上的SRAM 的读时序  

STM32

翻译过来的SRAM 的读时序

STM32

数据手册上的SRAM 的写时序  

STM32

翻译过来的SRAM 的写时序

读写时序的流程很类似,下面我们统一解说:

(1) 主机使用地址信号线发出要访问的存储器目标地址;

(2) 控制片选信号 CS1#及 CS2#使能存储器芯片;

(3) 若是要进行读操作,则控制读使能信号OE#表示要读数据,若进行写操作则控制写使能信号 WE#表示要写数据;

(4) 使用掩码信号LB#与UB#指示要访问目标地址的高、低字节部分;

(5) 若是读取过程,存储器会通过数据线向主机输出目标数据,若是写入过程,主要使用数据线向存储器传输目标数据。

在读写时序中,有几个比较重要的时间参数,在使用 STM32 控制的时候需要参考。

STM32

IS62WV51216BLL-55ns型号SRAM的时间参数

三、FSMC简介

FSMC的本质就是内核想要访问存储器,但是内核不能生成硬件时序,FSMC外设就帮忙做了这个硬件时序这个事情。有了这个外设我们操作外部SRAM就不需要自己在那里写读写时序了,FSMC就帮我们解决了。怎么解决的?它有各种寄存器结构体啊,直接按照要求配置就可以了。

STM32F407或STM32F417系列芯片都带有FSMC接口,FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,STM32F4的FSMC 接口支持包括SRAM、NAND FLASH、NOR FLASH和 PSRAM 等存储器。

**注意:FSMC不能驱动如SDRAM 这种动态的存储器,而在STM32F429系列的控制器中,它具有FMC外设,支持控制 SDRAM 存储器**。其他我们不用管,从上面我们可以总结的是,STM32雇佣FSMC这个管家来管理我们的IS62WV51216。来来来,我们来看看FSMC的庐山真面目:

FSMC 的框图如图所示:

STM32

FSMC时钟来源

STM32

FSMC—STM32F4XX参考手册

STM32

FSMC—STM32F4XX参考手册

蒙了吧!又是这么多信号线,不要怕,我们还是来总结归纳下。我们FSMC控制SRAM为例来说明:通过查看STM32F407xx参考手册。

STM32

外部存储器接口信号—STM32F4xx参考手册

上图打码的地方是PSRAM伪静态随机存储器的引脚,不需要理会,只需要看SRAM的部分即可。

你会发现居然和SRAM中的线居然高度统一(那是当然喏,我们就是讲的FSMC嘛!)

1、FSMC_NBL[1]、FSMC_NBL[0]分别对应于LBn、UBn,有什么用呢?提供数据掩码信号。貝体是怎么回事昵?还记得前面提到的行地址线吗?

一根行地址线对应16位的数据,我们可以把16位的数据分为高字节和低字节。当要访问宽度为16位的数据时,使用行地址线指出地址,然后把UBn(n表示低电平有效)和LBn线都设置为低电平(FSMC_NBL0和 FSMC_NBL为低电平),那么I/O0-I/O15线(FSMC_D0到 FSMC_D15)都有效,它们一起输出该地址的16位数据(或者接收16位数据到该地址);当要访问宽度为8位的数据时,使用行地址线指出地址,然后把UBn(FSMC_NBL0)设置为低电平,I/O0-I/O15(FSMC_D8到 FSMC_D15)会对应输出该地址的高8位,l/O0-I/O7的信号无效(或者把LBn(FSMC_NBL1)设置为低电平,I/O0-/O7(FSMC_D0到SMCD7)会对应输出该地址的低8位,I/O8-/I/O15的信号无效。这样是不是有部分信号没有用呢?好像被掩盖了。因此它们被称为数据掩码信号。

要注意的是FSMC_NBL[1]、FSMC_NBL[0]分别对应于LBn、UBn,这两个引脚的电平不是我们用程序控制的,如果用程序控制就太麻烦了,这两个引脚应该是FSMC的内部硬件机制完成的,不需要我们人为操作。

2、FSMC_NE[1:4]是个很有趣的东西,它决定了FSMC可以控制多个存储器。这里就要提及FSMC的地址映射啦!

STM32

FSMC存储区域—STM32F4XX参考手册

首先,有一点我们必须明白,对于32位的STM32单片机来说,它能够管理的地址大小为4GB,而STM32将4GB的地址空间中的0X60000到0X9FFFF共1GB的空间分给外部内存,所以这1GB的空间就成了我们的小天地,供我们自由玩耍。

STM32

STM32F407数据手册英文版—MemoryMap

STM32

野火407手册

STM32

STM32F417数据手册—中文版

然后强势的FSMC就接管了这1GB的空间,FSMC将图中的1GB大小的外部RAM存储区域分成了4个Bank区域,每个Bank对应于STM32内部寻址空间的不同地址范围。

那么为什么要分为不同的Bank区域呢?

因为不同的Bank可以来管理不同的外部存储设备,比如NOR_Flash及SRAM存储器只能使用Bank1的地址,NAND_Flash存储器只能使用Bank2和Bank3的地址等。

细心的你肯定还会发现,每个Bank中居然还有4x64MB这种文宇,这是什么意思呢?

STM32

FSMC存储区域—STM32F4XX参考手册

Bank内部的256MB空间又被分成4个小块,每块64M,各自有相应的控制引脚用于连接片选信号。FSMC_NE[4:1]信号线就分别对应图中的 FSMC bank1 NOR/PSRAM4到FSMC bank1 NOR/PSRAM1。当STM32访问0×6800000—0x6BFFF址空间时,会访问到Bank1的第3小块区域:FSMC bank1 NOR/PSRAM3,相应的FSMC_NE3信号线会输出控制信号(即片选信号),如果这个时候FSMC_NE3处刚好接上IS62WV51216的CS端,那么IS62WV51216就可以任由我们摆布啦。因此,对于你使IS62WV51216来说,一定要注意你的CS端是接的FSMC的哪个FSMC_NE端,这决定你在程序访问哪个地址范围。

STM32F4 的 FSMC 存储块 1(Bank1)被分为 4 个区,每个区管理64M 字节空间,每个区都有独立的寄存器对所连接的存储器进行配置。Bank1 的 256M 字节空间由28根地址线(HADDR[27:0])寻址。

为什么是28根地址线?因为2^28=268435456B=262144KB=256MB,正好管理这Bank1的256M 字节空间。

STM32

当Bank1接的是16位宽度存储器的时候:HADDR[25:1]→FSMC_A[24:0]。当Bank1接的是8位宽度存储器的时候:HADDR[25:0]→ FSMC_A[25:0]。不论外部接8位/16位宽设备,FSMC_A0永远接在外部设备地址A[0]。

STM32

这里感觉很不好理解,简单地分析如下:

对于16位SRAM,FSMC地址线要向右移一位(非常重要)。

以0x6800 0000这个地址为例,它分解成二进制是0110 1000 0000 0000 0000 0000 0000 0000,由于一个BANK是64M的地址空间,而2^25=64M,故0x6800 0000的位[25:0]是FSMC向外部SRAM传递的真实地址,对于0x6800 0000,FSMC向外部SRAM发的地址是位[25:0],即00 0000 0000 0000 0000 0000 0000,这很好理解。

同理,对于0x6800 0002,FSMC向外部SRAM发送的地址是00 00000000 0000 0000 0000 0010。若FSMC不自动右移一位,这个地址明显发错了,因为期望读取的SRAM地址为0x0000 0001中的数据。

为了解决这一问题,当在初始化FSMC时,若选择外部SRAM为16位,则FSMC在向外部SRAM发地址时,会自动右移一位,例如刚才的0x6800 0002,FSMC在向外部发SRAM地址时,00 0000 0000 0000 0000 0000 0010会自动右移一位,变成00 0000 00000000 0000 0000 0001,即0x0000 0001,该地址正好是期望的外部SRAM地址。接着,外部SRAM从地址为0x0000 0001中取出16位数据传送给FSMC,由FSMC将这个16位数据保存在以映射地址0x6800 0002起始的两个8位存储单元中。

STM32

地址映射如下:

STM32

这样的话,当16位数据宽度时,地址的问题解决了,还有一个问题,是往高字节写入还是低字节写入呢?

这也就是NBL0和NBL1的作用了,如果你要进行字节操作 :如stm32发送地址0x0001读取一个字节。右移一位对应的是sram地址0x0000处的16位数据, FSMC会根据A0(最后一根地址线)来控制NBL0和NBL1。当A0 = 1时,读取高字节数据(仅NBL1有效);A0 = 0时,读取低字节数据仅NBL0有效),当进行16位读写时,NBL0和NBL1都有效。

经过了上面的分析,再来重新观察数据的写入过程:

当地址为0x6800  0000,会访问到SRAM的第0个16位地址,而此时A0 = 0(低字节有效),实际会访问的是16位 0地址的低字节;当地址为0x6800  0001时,A0 = 1,访问16位 0地址的高字节。依次。

因此,想让地址线的最后一位产生0或1,应该在前一位做出改变(stm32会自动右移):

STM32

我们的SRAM芯片使用的是Bank1 的第三个区,即使用FSMC_NE3来连接外部设备的时候,即对应了HADDR[27:26]=10(这是内部硬件配置,不需要我们管),我们要做的就是配置对应第3区的寄存器组,来适应外部设备即可。

STM32F4的FSMC各Bank配置寄存器如下表

STM32

STM32的FSMC存储块1支持的异步突发访问模式包括:模式1、模式A~D等多种时序模型,驱动SRAM时一般使用模式1或者模式A,这里我们使用模式A来驱动SRAM用,其他模式说明详见:STM32中文参考手册-FSMC章节。

FSMC外设支持输出多种不同的时序以便于控制不同的存储器,它具有 ABCD 四种模式,下面我们仅针对控制 SRAM 使用的模式 A进行讲解。

STM32

模式A读时序

STM32

模式A写时序

对于NOR FLASH/PSRAM(包括SRAM)控制器(存储块1),通过FSMC_BCRX、FSMC_BTRX和FSMCBWTRx寄存器设置(其中x=1~4,对应4个区)。由于我们硬件是把blank的第三个区给外部SRAM使用,所以对于SRAM芯片的片选引脚为FSMC_NE3。所以就要配置FSMC_BCR3、FSMC_BTR3和FSMCBWTR3这3个寄存器。正点原子F407板子的SRAM的片选引脚是FSMC_NE3,LCD显存芯片的片选引脚是FSMC_NE4。

STM32

原子的F407的SRAM是blank NE3 LCD是blank NE3

STM32

野火的F407的SRAM blank NE4  

STM32

野火F407的LCD blank NE3

四、SRAM的FSMC寄存器配置

4.1 SRAM/NOR-Flash片选控制寄存器

STM32

EXTMOD:扩展模式使能位,控制是否允许读写不同的时序,需设置为1。

WREN:写使能位。我们需要向SRAM写数据,故该位必须设置为1。

MWID[1:0]:存储器数据总线宽度。00,表示8位数据模式;01表示16位数据模式;10和11保留。我们的SRAM是16位数据线,所以设置WMID[1:0]=01。

MTYP[1:0]:存储器类型。00表示SRAM、ROM;01表示PSRAM;10表示NOR FLASH;11保留。我们使用SRAM,所以需要设置MTYP[1:0]=00。

MBKEN:存储块使能位。需设置为1。

STM32

STM32F4XX中文参考手册

4.2 SRAM/NOR-Flash片选时序寄存器

STM32

ACCMOD[1:0]:访问模式。00:模式A;01:模式B;10:模式C;11:模式D。

DATAST[7:0]:数据保持时间,等于:DATAST个HCLK时钟周期,DATAST最大为255。对STM32F1,一个HCLK=13.8ns(1/72M),设置为15;对STM32F4,一个HCLK=6ns(1/168M),设置为60。

ADDSET[3:0]:地址建立时间。表示:ADDSET个HCLK周期,ADDSET最大为15。STM32F1的FSMC性能存在问题,即便设置为0,RD也有190ns的高电平,我们这里设置为1。而对STM32F4,则设置为15。

STM32

4.3 SRAM/NOR-Flash写入时序寄存器

STM32

ACCMOD[1:0]:访问模式。00:模式A;01:模式B;10:模式C;11:模式D。

DATASTI7:01:数据保持时间,等于:DATAST个HCLK时钟周期,DATAST最大为255。对ILI9341来说,其实就是WR低电平持续时间,为15ns,不过ILI9320等则需要50ns。考虑兼容性,对STM32F1,一个HCLK=13.8ns(1/72M),设置为3;对STM32F4,一个HCLK=6ns(1/168M),设置为9。

ADDSET[3:0]:地址建立时间。表示:ADDSET个HCLK周期,ADDSET最大为15。对lL19341来说,这里相当于WR高电平持续时间,为15ns。同样考虑兼容IL19320,对STM32F1,这里即便设置为1,WR也有100ns的高电平,我们这里设置为1。而对STM32F4,则设置为8。

STM32

在MDK的寄存器定义里面,并没有定义FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx等这个单独的寄存器,而是将他们进行了一些组合。

FSMC_BCRx和FSMC_BTRx,组合成BTCR[8]寄存器组,他们的对应关系如下:

BTCR[0] 对应 FSMC_BCR1,BTCR[1] 对应 FSMC_BTR1BTCR[2] 对应 FSMC_BCR2,BTCR[3] 对应 FSMC_BTR2BTCR[4] 对应 FSMC_BCR3,BTCR[5] 对应 FSMC_BTR3BTCR[6] 对应 FSMC_BCR4,BTCR[7] 对应 FSMC_BTR4

FSMC_BWTRx则组合成BWTR[7],他们的对应关系如下:

BWTR[0]对应 FSMC_BWTR1,BWTR[2]对应 FSMC_BWTR2,BWTR[4]对应 FSMC_BWTR3,BWTR[6]对应 FSMC_BWTR4,BWTR[1]、BWTR[3]和 BWTR[5]保留,没有用到。

本篇到此结束,下一篇将讲解FSMC的先关代码,并使用STM32CubeMX进行配置。






审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分