外部SRAM
外部 SRAM 的控制一般有:地址线(如 A0~A18)、数据线(如 D0~D15)、写信号(WE)、读信号(OE)、片选信号(CS),如果 SRAM 支持字节控制,那么还有 UB/LB 信号。
XM8A51216介绍
XM8A51216 是深圳星忆存储科技有限公司生产的一颗 16 位宽 512K(512*16,即 1M 字节)容量的 CMOS 静态内存芯片。该芯片具有如下几个特点:
⚫ 高速。具有最高访问速度 10/12ns。
⚫ 低功耗。
⚫ TTL 电平兼容。
⚫ 全静态操作。不需要刷新和时钟电路。
⚫ 三态输出。
⚫ 字节控制功能。支持高/低字节控制。
功能框图
A0~18 为地址线,总共 19 根地址线(即 2^19=512K,1K=1024);
DQ0~15 为数据线,总共 16 根数据线。
CEn 是芯片使能信号,低电平有效;
OEn 是输出使能信号,低电平有效;
WEn 是写使能信号,低电平有效;
BLEn 和 BHEn 分别是高字节控制和低字节控制信号;
硬件连接图
XM8A51216 同 STM32F1 的连接关系:
A[0:18]接 FMSC_A[0:18](不过顺序错乱了)
D[0:15]接 FSMC_D[0:15]
BHEn 接 FSMC_NBL1
BLEn 接 FSMC_NBL0
OEn 接 FSMC_OE
WEn 接 FSMC_WE
CEn 接 FSMC_NE3
上面的连接关系,XM8A51216 的 A[0:18]并不是按顺序连接 STM32F1 的 FMSC_A[0:18],
不过这并不影响我们正常使用外部 SRAM,因为地址具有唯一性。
所以,只要地址线不和数据线混淆,就可以正常使用外部 SRAM。
FSMC接口介绍
大容量,且引脚数在 100 脚以上的 STM32F103 芯片都带有 FSMC 接口
FSMC,即灵活的静态存储控制器flexible static memory controller。
FSMC作用
驱动外部存储器
ü 能够与同步或异步存储器和 16 位 PC 存储器卡连接,从而扩展内存
ü STM32 的 FSMC 接口支持包括 SRAM、NAND FLASH、nor FLASH 和 PSRAM 等存储器。
ü FSMC就是一个MCU与外部存储器(SRAM,FLASH等)读写数据的一个接口,我们可以配置FSMC的寄存器从而实现MCU可以根据特定的时序与外部存储器进行数据的交互(存储/读取)
FSMC内部原理
FSMC 的框图
STM32 的 FSMC 将外部设备分为 3 类:nor/PSRAM 设备、NAND设备、PC 卡设备。
他们共用地址数据总线等信号,他们具有不同的 CS 以区分不同的设备
FSMC内存划分
FSMC的分块
STM32的 FSMC将外部存储器划分为固定大小为 256M 字节的四个存储块(Bank),FSMC 总共管理 1GB 空间.
如下为FSMC在cpu中的地址映射划分。
各模块配置的地址范围
存储块1的介绍
目录FSMC内部原理
存储块1的分区
存储块1的地址
不同数据宽度对存储块1寻址的影响
FSMC中地址与外设地址的对应关系
存储块1的分区
STM32 的 FSMC 存储块 1(Bank1)被分为 4 个区,每个区管理 64M 字节空间,每个区都有独立的寄存器对所连接的存储器进行配置。
存储块1的地址
Bank1 的 256M 字节空间由 28 根地址线(HADDR[27:0])寻址。
HADDR 是需要转换到外部设备的内部 AHB 总线地址,一个地址对应八位数据。
其中 HADDR[25:0]来自外部存储器地址FSMC_A[25:0]。
HADDR[27:26]位用于选择四个存储块之一。
但[0:25]却需要根据不同位宽讨论。
不同区的地址范围
不同数据宽度对存储块1寻址的影响
对于16位宽度的外部存储器,FSMC将在内部使用HADDR[25:1]产生外部存储器的地址FSMC_A[24:0]。
可以区分一下,FSMC即为外部存储器的地址,是FSMC端的,HADDR是AHB总线端的
cpu发出两个地址,去接受一个16位的数据,它不知道自己发出的两个地址会落到同一个位置。因为被右移了两位。
不论外部存储器的宽度是多少(16位或8位),FSMC_A[0]始终应该连到外部存储器的地址线A[0]
FSMC中地址与外设地址的对应关系
FSMC中的1G空间存储的是外设地址,当我们在存储块中的访问单元序号+1,对应的外设存储单元的访问地址就自加8(如果外设数据存储的数据宽度为8b的话)
FSMC相关寄存器
目录
SRAM/nor 闪存片选控制寄存器:FSMC_BCRx
SRAM/nor 闪存片选时序寄存器:FSMC_BTRx
SRAM/nor 闪写时序寄存器:FSMC_BWTRx
SRAM/nor 闪存片选控制寄存器:FSMC_BCRx
该寄存器有1-4。
ü EXTMOD:扩展模式使能位,也就是是否允许读写不同的时序
○ 我们本章需要读写不同的时序,故该位需要设置为 1。
○ 当该位设置为0,读写就公用BTRx寄存器。
ü Wren:写使能位。
○ 我们需要向 TFTLCD 写数据,故该位必须设置为 1。
ü MWID[1:0]:存储器数据总线宽度。
○ 00,表示 8 位数据模式;
○ 01 表示 16 位数据模式;
○ 10和 11 保留。
○ 我们的 TFTLCD 是 16 位数据线,所以设置 WMID[1:0]=01。
ü MTYP[1:0]:存储器类型。
○ 00 表示 SRAM、ROM;
○ 01 表示 PSRAM;
○ 10 表示 nor FLASH;11保留。
ü MBKEN:存储块使能位。
SRAM/nor 闪存片选时序寄存器:FSMC_BTRx
目录
BTRx寄存器介绍
地址建立时间
数据保持时间
BTRx寄存器介绍
该寄存器有1-4。
如果 FSMC_BCRx 寄存器中设置了 EXTMOD 位,则有两个时序寄存器分别对应读(本寄存器)和写操作(FSMC_BWTRx 寄存器)。
ü ACCMOD[1:0]:访问模式。
00 表示访问模式 A;01 表示访问模式 B;
10 表示访问模式 C;11 表示访问模式 D
本章我们用到模式 A,故设置为 00。
ü DATAST[7:0]:数据保持时间。
0 为保留设置,其他设置则代表保持时间为: DATAST 个HCLK 时钟周期,最大为 255 个 HCLK 周期。
对 ILI9341 来说,其实就是 RD 低电平持续时间,一般为 355ns。
而一个 HCLK 时钟周期为 13.8ns 左右(1/72Mhz),为了兼容其他屏,我们这里设置 DATAST 为 15,也就是 16 个 HCLK 周期,时间大约是 234ns。
ü ADDSET[3:0]:地址建立时间。
其建立时间为:ADDSET 个 HCLK 周期,最大为 15 个 HCLK周期,每个周期4ns(1/25M)。
对 ILI9341 来说,这里相当于 RD 高电平持续时间,为 90ns,本来这里我们应该设置和DATAST 一样,但是由于 STM32F103 FSMC 的性能问题,就算设置 ADDSET 为 0,RD 的高电平持续时间也达到了 190ns 以上,所有,我们这里可以设置 ADDSET 为较小的值,本章我们设置 ADDSET 为 1,即 2 个 HCLK 周期,实际 RD 高电平大于 200ns。
地址建立时间
建立时间(Tsu:setuptime)是指在时钟沿到来之前数据从不稳定到稳定所需的时间
用于从外设,如TFTLCD读取到稳定的RS信号。
这段时间内,RDX和WRX均为无效电平。
数据保持时间
保持时间(Th:holdtime)是指数据稳定后保持的时间,如果保持时间不满足要求那么数据同样也不能被稳定的打入触发器。
为了我们识别到稳定可靠的数据,数据保持时间必须大于RDX低电平持续时间,即RDX的上升沿必须出现在地址保持时间之内。
在计算的时候,应该查看驱动外设的读写最小时间,然后除时钟周期即可。ADDSET最小为250ns/HCLK,DATAST最小为150ns/HCLK。
SRAM/nor 闪写时序寄存器:FSMC_BWTRx
ü 该寄存器在本章用作写操作时序控制寄存器
ü ACCMOD 设置同 FSMC_BTRx 一模一样,同样是选择模式 A
ü 另外 DATAST 和ADDSET 则对应低电平和高电平持续时间
○ 对 ILI9341 来说,这两个时间只需要 15ns 就够了,比读操作快得多。
○ 所以我们这里设置 DATAST 为 3,即 4 个 HCLK 周期,时间约为 55ns(因为9320 等控制器,这个时间要求比较长,要 50ns)。
○ ADDSET(也存在性能问题)设置为 0,即 1 个 HCLK 周期,实际 WR 高电平时间大于 100ns。
这里还要给大家做下科普,在 MDK 的寄存器定义里面,并没有定义 FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx 等这个单独的寄存器,而是将他们进行了一些组合。
FSMC_BCRx 和 FSMC_BTRx,组合成 BTCR[8]寄存器组,他们的对应关系如下:
BTCR[0]对应 FSMC_BCR1,BTCR[1]对应 FSMC_BTR1
BTCR[2]对应 FSMC_BCR2,BTCR[3]对应 FSMC_BTR2
BTCR[4]对应 FSMC_BCR3,BTCR[5]对应 FSMC_BTR3
BTCR[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的读写时序
FSMC与外设时序列保持一致
FSMC作为cpu与外部SRAM沟通的桥梁,那就得说他们两个人都认识的话——读写时序
对FSMC管理的变量Var进行读写就会引起FSMC产生读取SRAM中数据的时序,引发对SRAM的读写操作。
FSMC的模式A的读时序
NOE为读,NWE为写。
n低电平有效
o output
e 使能
nex 片选
FSMC的模式A的写时序
FSMC的配置步骤
初始化 FSMC 主要是初始化三个寄存器 FSMC_BCRx,FSMC_BTRx,FSMC_BWTRx
使能 FSMC 时钟,并配置 FSMC 相关的 IO 及其时钟使能
要使用 FSMC,当然首先得开启其时钟。然后需要把 FSMC_D015,FSMCA018 等相关IO 口,全部配置为复用输出,并使能各 IO 组的时钟。使能 FSMC 时钟的方法:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);
初始化FSMC,设置FSMC BANK1区域3
固件库提供了 3 个 FSMC 初始化函数分别为
FSMC_norSRAMInit();
FSMC_NANDInit();
FSMC_PCCARDInit();
这三个函数分别用来初始化 4 种类型存储器。
用来初始化nor 和 SRAM 使用同一个函数 FSMC_norSRAMInit()。
此部分包括设置区域 3 的存储器的工作模式、位宽和读写时序等。
本章我们使用模式 A、16 位宽,读写共用一个时序寄存器。使用的函数是:
void FSMC_norSRAMInit(FSMC_norSRAMInitTypeDef* FSMC_norSRAMInitStruct)
结构体指针:
typedef struct
{
uint32_t FSMC_Bank;
uint32_t FSMC_DataAddressMux;
uint32_t FSMC_MemoryType;
uint32_t FSMC_MemoryDataWidth;
uint32_t FSMC_BurstAccessMode;
uint32_t FSMC_AsynchronousWait;
uint32_t FSMC_WaitSignalPolarity;
uint32_t FSMC_WrapMode;
uint32_t FSMC_WaitSignalActive;
uint32_t FSMC_WriteOperation;
uint32_t FSMC_WaitSignal;
uint32_t FSMC_ExtendedMode;
uint32_t FSMC_WriteBurst;
FSMC_norSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct;
FSMC_norSRAMTimingInitTypeDef* FSMC_WriteTimingStruct;
}FSMC_norSRAMInitTypeDef;
前面13 个基本类型(unit32_t)的成员变量用来配置片选控制寄存器 FSMC_BCRx。
最后两个SMC_norSRAMTimingInitTypeDef 指针类型的成员变量用来配置寄存器 FSMC_BTRx 和 FSMC_BWTRx
下面我们主要来看看模式 A下的相关配置参数:
ü FSMC_Bank
○ 用来设置使用到的存储块标号和区号,前面讲过
○ 存储块 1 区号 4,所以选择值为 FSMC_Bank1_norSRAM4。
ü FSMC_MemoryType
用来设置存储器类型,我们这里是 SRAM,所以选择值为FSMC_MemoryType_SRAM。
ü FSMC_MemoryDataWidth
用来设置数据宽度,可选 8 位还是 16 位,这里我们是 16 位数据宽度,所以选择值为 FSMC_MemoryDataWidth_16b。
ü FSMC_WriteOperation
用来设置写使能,毫无疑问,我们前面讲解过我们要向 TFT 写数据,所以要写使能,这里我们选择 FSMC_WriteOperation_Enable。
ü FSMC_ExtendedMode
是设置扩展模式使能位,也就是是否允许读写不同的时序,这里我们采取的读写不同时序,所以设置值为 FSMC_ExtendedMode_Enable。
上面的这些参数是与模式 A 相关的
下面我们也来稍微了解一下其他几个参数的意义吧:
ü FSMC_DataAddressMux
用来设置地址/数据复用使能,若设置为使能,那么地址的低 16位和数据将共用数据总线,仅对 nor 和 PSRAM 有效,所以我们设置为默认值不复用,值FSMC_DataAddressMux_disable。
FSMC_BurstAccessMode , FSMC_AsynchronousWait , FSMC_WaitSignalPolarity ,FSMC_WaitSignalActive , FSMC_WrapMode , FSMC_WaitSignal FSMC_WriteBurst 和FSMC_WaitSignal 这些参数在成组模式同步模式才需要设置。
设 置 读 写 时 序 参 数 的 两 个 变 量 FSMC_ReadWriteTimingStruct 和FSMC_WriteTimingStruct,他们都是 FSMC_norSRAMTimingInitTypeDef 结构体指针类型,这两个参数在初始化的时候分别用来初始化片选控制寄存器FSMC_BTRx和写操作时序控制寄存器 FSMC_BWTRx。
下面我们看看 FSMC_norSRAMTimingInitTypeDef 类型的定义:
typedef struct
{
uint32_t FSMC_AddressSetupTime;
uint32_t FSMC_AddressHoldTime;
uint32_t FSMC_DataSetupTime;
uint32_t FSMC_BusTurnAroundDuration;
uint32_t FSMC_CLKDivision;
uint32_t FSMC_DataLatency;
uint32_t FSMC_AccessMode;
}FSMC_norSRAMTimingInitTypeDef;
这个结构体有 7 个参数用来设置 FSMC 读写时序。
设计地址建立保持时间,数据建立时间等等配置等。
具体的设置方法请参考我们的 sarm.c 文件中的 FSMC_SRAM_Init()函数。
SRAM/nor 闪存片选时序寄存器:FSMC_BTRx
使能 BANK1 区域 3
FSMC 对不同的存储器类型同样提供了不同的使能函数:
void FSMC_norSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState);
void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState);
void FSMC_PCCARDCmd(FunctionalState NewState);
norSRAM函数是:
void FSMC_norSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState);
FSMC_norSRAMCmd(FSMC_Bank1_norSRAM3, ENABLE);
因为我们使用的是 BANK1 的区域 3,所以 HADDR[27:26]=10,故外部内存的首地址为0X68000000。
存储块1的地址