嵌入式系统应用--TFTLCD 显示实验 3 之内存拓展
文章目录
- 问题提出
- 1 SRAM的拓展
- 2 配置流程
- 2.1 硬件电路图
- 2.2 配置流程
- 2.3 地址范围
- 3 编译时候的内存拓展
- 3.1 配置初始化外部内存
- 3.2 配置外设内存地址起始地址
- 3.2 配置缓存地址
- 4 测试代码
- 4.1 测试代码
- 4.2 效果图
问题提出
移植图形库需要消耗能多内存用于系统内部的缓存。然而芯片内置的内存不够,需要拓展的内存。 如何拓展内存,笔者将从下面开始介绍。
1 SRAM的拓展
STM32F407ZGT6 本身就有 192K 字节的 SRAM,对一般应用来说,已经足够使用,不过在一些对内存要求高的场合,STM32F4 自带的这些内存就不够用了,比如跑算法或者 GUI 等。STM32F4 开发板上集成了一颗 1M 字节容量的 SRAM 芯片:IS62WV51216,来满足大内存使用的需求。
FSMC 控制外扩 1MB 的 SRAM(IS62WV51216),实现对 IS62WV51216 的访问控制,并测试其容量.
S62WV51216 是 ISSI(Integrated Silicon Solution, Inc)公司生产的一颗 16 位宽 512K(512*16,即 1M 字节)容量的 CMOS 静态内存芯片.
A0-A18为地址线,总共19根地址线(可访问2^19=512K空间(1K=1024));IO0~15为数据线,总共16根数据线。CS2和CS1都是片选信号,不过CS2是高电平有效CS1是低电平有效;OE是输出使能信号(读信号);WE为输入使能信号(写信号);UB和LB分别是高字节控制和低字节控制信号;
IS62WV51216芯片连接在STM32F4的FSMC上,所以可以直接通过FSMC控制。FSMC的Bank1区域3来控制.
2 配置流程
2.1 硬件电路图
A0-A18 连接在 FSMC_A0-FSMC_A18 上
IO0-IO15 连接在 FSMC_D0-FSMC_D15 上
UB 和 LB 连接在 FSMC_NBL1 和 FSMC_NBL0 上
OE 连接在 FSMC_NOE 上
WE 连接在 FSMC_NWE 上
CE 连接在 FSMC_NE3 上
A0-A18 与 FSMC_A0-FSMC_A18 的连接顺序可以打乱,因为地址是固定的,但是 IO0-IO15 和 FSMC_D0-FSMC_D15 的连接顺序不可打乱,否则读写数据将出错。
2.2 配置流程
(1)使能 FSMC 及端口时钟,并将对应 IO 配置为复用功能。
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef FSMC_ReadWriteNORSRAMTiming; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD,PE,PF,PG时钟
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC时钟 GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12GPIO_PinAFConfig(GPIOE,GPIO_PinSource0,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource1,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);//PE7,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12GPIO_PinAFConfig(GPIOF,GPIO_PinSource0,GPIO_AF_FSMC);//PF0,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource1,GPIO_AF_FSMC);//PF1,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource2,GPIO_AF_FSMC);//PF2,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource3,GPIO_AF_FSMC);//PF3,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource4,GPIO_AF_FSMC);//PF4,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource5,GPIO_AF_FSMC);//PF5,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource12,GPIO_AF_FSMC);//PF12,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource13,GPIO_AF_FSMC);//PF13,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource14,GPIO_AF_FSMC);//PF14,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource15,GPIO_AF_FSMC);//PF15,AF12GPIO_PinAFConfig(GPIOG,GPIO_PinSource0,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource1,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource2,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource3,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource4,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource5,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource10,GPIO_AF_FSMC);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PB15 推挽输出,控制背光
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 //PB15 推挽输出,控制背光GPIO_InitStructure.GPIO_Pin = (3<<0)|(3<<4)|(0XFF<<8);//PD0,1,4,5,8~15 AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化 GPIO_InitStructure.GPIO_Pin = (3<<0)|(0X1FF<<7);//PE0,1,7~15,AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化 GPIO_InitStructure.GPIO_Pin = (0X3F<<0)|(0XF<<12); //PF0~5,12~15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO_InitStructure.GPIO_Pin =(0X3F<<0)| GPIO_Pin_10;//PG0~5,10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
(2) 初始化 FSMC,包括 FSMC 区域的选择、读写时间设定等。
FSMC_ReadWriteNORSRAMTiming.FSMC_AddressSetupTime = 0x0;//0 //地址建立时间(ADDSET)为1个HCLK 1/36M=27ns
FSMC_ReadWriteNORSRAMTiming.FSMC_AddressHoldTime = 0x0;//0 //地址保持时间(ADDHLD)模式A未用到
FSMC_ReadWriteNORSRAMTiming.FSMC_DataSetupTime = 0x18; ////数据保持时间(DATAST)为9个HCLK 6*9=54ns
FSMC_ReadWriteNORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00;
FSMC_ReadWriteNORSRAMTiming.FSMC_CLKDivision = 0x00;
FSMC_ReadWriteNORSRAMTiming.FSMC_DataLatency = 0x00;
FSMC_ReadWriteNORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
(3) 使能 FSMC 的 Bank1 区域 3 。
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;// 这里我们使用NE3 ,也就对应BTCR[4],[5]。
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM; //SRAM
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //存储器写使能
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; // 读写使用相同的时序
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_ReadWriteNORSRAMTiming;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_ReadWriteNORSRAMTiming; //读写同样时序FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE); // 使能BANK1区域3
2.3 地址范围
起始地址:0x68000000,大小 0x100000 . 一共是1MB。
3 编译时候的内存拓展
3.1 配置初始化外部内存
添加内存初始化函数
3.2 配置外设内存地址起始地址
起始地址是0x68000000, 范围是0x20000。
3.2 配置缓存地址
使用__attribute__((at(address))) 来分配内存实现双缓存,提高屏幕刷新效率。
4 测试代码
4.1 测试代码
void lv_color(int argc, char** argv)
{lv_mutex_lock(&lv_mutex);screen_new = lv_obj_create(NULL);lv_obj_set_size(screen_new, LV_HOR_RES, LV_VER_RES);lv_obj_set_style_bg_color(screen_new, lv_color_hex(value&0xffffff), 0);lv_obj_set_style_bg_opa(screen_new, LV_OPA_COVER, 0);switch(value){case 0xff:lv_scr_load_anim(screen_new, LV_SCR_LOAD_ANIM_MOVE_LEFT, 1000, 0, true);break;case 0xff00:lv_scr_load_anim(screen_new, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 1000, 0, true);break;case 0xff0000:lv_scr_load_anim(screen_new, LV_SCR_LOAD_ANIM_MOVE_TOP, 1000, 0, true);break;case 0xff000000:lv_scr_load_anim(screen_new, LV_SCR_LOAD_ANIM_MOVE_BOTTOM, 1000, 0, true);break;}value<<=8;lv_mutex_unlock(&lv_mutex);if(value==0)value=0xff; }MSH_CMD_EXPORT(lv_color,"color_adjust")
4.2 效果图
4-3 拓展内存