FlexBus外扩PSRAM 应用实例详解

前段时间项目遇到瓶颈,片内RAM空间不足,想要解决这个问题要么换更大RAM的MCU,要么就外扩PSRAM。可惜所用的K21最大就128Kb,没有更大的了,所以只有选择外扩。方案选择主要有两个问题需要考虑:1.PSRAM的数据位数;2.是否使用锁存器。由于IO口资源有限,同时为保证片外PSRAM的速度。最终的方案选择:16位数据的PSRAM,地址数据复用,两个锁存器切换数据地址方案。由于在网上没有找到先例,所以硬件接法有很多不确定。现在分享给坛子里的小伙伴们,欢迎指教,大牛勿喷喔。

相信看这篇文章的或多或少也知道Flexbus和PSRAM是什么了吧,所以在这儿就不啰嗦讲Flexbus和PSRAM的基本概念。实在有不懂的小伙伴百度一下,你就知道!

硬件部分

下面仔细来看看硬件框图吧,下面框图主要是Flexbus与PSRAM的接法。

根据上面框图做如下说明:

1. PSRAM的16位数据线接FB_AD[15:0],地址线接FB_AD[20:1]。其中地址线的FB_AD[16:1]与数据复用。采用双锁存器锁存地址。可能有的小伙伴就会产生疑惑了,为什么Flexbus的FB_AD[16:1]接PSRAM的A[15:0]呢?稍后解答!

2. 总线的FB_ALE接锁存器的锁存信号LE,用过锁存器的小伙伴都知道锁存器还有一个片选信号(让锁存器工作的开关),这个信号就随便接MCU的IO口即可。

3. Flexbus的FB_CE,FB_OE,FB_WE分别要与PSRAM的CE,OE,WE连接。

4. Flexbus的FB_BE31_24,FB_BE23_16分别与UB,LB连接,为什么呢?

5. PSRAM还有一个ZZ引脚,控制PSRAM是否休眠的,如果需要接MCU的IO口即可

因为不同的MCU的Flexbus所映射的IO不一样,所以就整理了一下用框图来说明。有什么疑问欢迎留言讨论。下面解答刚刚提出的两个为什么。

1. 为什么Flexbus的FB_AD[16:1]接PSRAM的A[15:0]?

关于这个问题,只要理解MCU处理器的寻址和PSRAM芯片的寻址就明白了。

目前最流行的32位嵌入式处理器ARM处理器,当然我所用的Cortex-M4处理器也是RAM家族的。从处理器的角度看,系统中每个地址对应的是一个BYTE的数据单元。这和很多别的处理器是一样的。

对16位的PSRAM芯片或者工作在16-BIT模式的芯片来说,一个地址对应16-BIT的数据。说到这里想必小伙伴们都懂了吧。也就不啰嗦了。

2. 为什么Flexbus的FB_BE31_24,FB_BE23_16分别与UB,LB连接?

其实这个没有什么好说的,看MCU flexbus的datasheet就能找到。在此顺便提一下。

我们这里是右对齐模式,从上图可知,软件CSCRn[BLS]应设为1 ,PSRAM的UB需要接FB_BE31_24,LU需要接FB_BE23_16。

软件部分

硬件就已经讲述完毕,接下来是软件部分。我这里使用的MQX4.0操作系统,MCU为K21。配置函数如下,不同的平台和MCU程序的表现形式不一样,配置的寄存器都是一样的,这里需要小伙伴们举一反三喔。

#define GPIO_PIN_MASK            0x1Fu

#define GPIO_PINX(x)              (((1)<<(x & GPIO_PIN_MASK)))

/*FUNCTION*---------------------------------------------------------------------

* Function Name    : flexbus_setup

* Returned Value   :  none

* Comments         :

*    Setup FlexBus pins before PSRAM operation

*END*-------------------------------------------------------------------------*/

void flexbus_setup (void)

{

#define ALT5                    0x05

#define OFF_CHIP_ACCESS_ALLOW   3

PORT_MemMapPtr  pctl;

SIM_MemMapPtr   sim = SIM_BASE_PTR;

/* Enable clock to FlexBus module */

sim->SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;

sim->CLKDIV1 |= SIM_CLKDIV1_OUTDIV3(0x0);//flexbus not divided

#ifdef SIM_SOPT2_FBSL

sim->SOPT2 |= SIM_SOPT2_FBSL(OFF_CHIP_ACCESS_ALLOW);

#endif

//把对应的接口配置成总线模式

pctl = (PORT_MemMapPtr)PORTB_BASE_PTR;

pctl->PCR[9] = PORT_PCR_MUX(ALT5); /* FB_AD20 */

pctl->PCR[10] = PORT_PCR_MUX(ALT5); /* FB_AD19 */

pctl->PCR[11] = PORT_PCR_MUX(ALT5); /* FB_AD18 */

pctl->PCR[16] = PORT_PCR_MUX(ALT5); /* FB_AD17 */

pctl->PCR[17] = PORT_PCR_MUX(ALT5); /* FB_AD16 */

pctl->PCR[18] = PORT_PCR_MUX(ALT5); /* FB_AD15 */

pctl->PCR[19] = PORT_PCR_MUX(ALT5); /* FB_OE_B */

// pctl->PCR[20] = PORT_PCR_MUX(ALT5); /* FB_AD31 */

//pctl->PCR[21] = PORT_PCR_MUX(ALT5); /* FB_AD30 */

// pctl->PCR[22] = PORT_PCR_MUX(ALT5); /* FB_AD29 */

// pctl->PCR[23] = PORT_PCR_MUX(ALT5); /* FB_AD28 */

pctl = (PORT_MemMapPtr)PORTC_BASE_PTR;

pctl->PCR[0] = PORT_PCR_MUX(ALT5); /* FB_AD14 */

pctl->PCR[1] = PORT_PCR_MUX(ALT5); /* FB_AD13 */

pctl->PCR[2] = PORT_PCR_MUX(ALT5); /* FB_AD12 */

pctl->PCR[4] = PORT_PCR_MUX(ALT5); /* FB_AD11 */

pctl->PCR[5] = PORT_PCR_MUX(ALT5); /* FB_AD10 */

pctl->PCR[6] = PORT_PCR_MUX(ALT5); /* FB_AD9 */

pctl->PCR[7] = PORT_PCR_MUX(ALT5); /* FB_AD8 */

pctl->PCR[8] = PORT_PCR_MUX(ALT5); /* FB_AD7 */

pctl->PCR[9] = PORT_PCR_MUX(ALT5); /* FB_AD6 */

pctl->PCR[10] = PORT_PCR_MUX(ALT5); /* FB_AD5 */

pctl->PCR[11] = PORT_PCR_MUX(ALT5); /* FB_RW_B */

pctl->PCR[16] = PORT_PCR_MUX(ALT5); /* FB_BE23_16 */

pctl->PCR[17] = PORT_PCR_MUX(ALT5); /* FB_BE31_24 */

pctl->PCR[3] = PORT_PCR_MUX(ALT5); /* FB_CLKOUT */

pctl = (PORT_MemMapPtr)PORTD_BASE_PTR;

pctl->PCR[0] = PORT_PCR_MUX(ALT5); /* FB_ALE */

pctl->PCR[1] = PORT_PCR_MUX(ALT5); /* FB_CS0_b */

pctl->PCR[2] = PORT_PCR_MUX(ALT5); /* FB_AD4 */

pctl->PCR[3] = PORT_PCR_MUX(ALT5); /* FB_AD3 */

pctl->PCR[4] = PORT_PCR_MUX(ALT5); /* FB_AD2 */

pctl->PCR[5] = PORT_PCR_MUX(ALT5); /* FB_AD1 */

pctl->PCR[6] = PORT_PCR_MUX(ALT5); /* FB_AD0 */

//如果FB_AD口被其他功能占用,接口仅做地址线,可用flexbus的专用地址线FB_Ax代替,只需硬件上连接软件把对应IO配成总线模式即可

//pctl->PCR[10] = PORT_PCR_MUX(ALT5); /* FB_A18 */

//pctl->PCR[11] = PORT_PCR_MUX(ALT5); /* FB_A19 */

//pctl->PCR[12] = PORT_PCR_MUX(ALT5); /* FB_A20 */

//Set PIN for GPIO functionality

PORTC_PCR12 = (0|PORT_PCR_MUX(1));//PSRAM_ZZ脚

PORTB_PCR6  = (0|PORT_PCR_MUX(1));//573 OE脚

// GPIOB_PDDR=GPIO_PDDR_PDD(GPIO_PINX(16));

//Change PINto outputs

GPIOC_PDDR=GPIO_PDDR_PDD(GPIO_PINX(12));

GPIOB_PDDR=GPIO_PDDR_PDD(GPIO_PINX(6));

GPIOC_PDOR=GPIO_PDOR_PDO(GPIO_PINX(12));

}

/*FUNCTION*---------------------------------------------------------------------

*

* Function Name    : _bsp_flexbus_psram_setup

* Returned Value   :

* Comments         :

*    Setup FlexBus for PSRAM operation

*

*END*-------------------------------------------------------------------------*/

void flexbus_psram_setup ()

{

FB_MemMapPtr fb_ptr = FB_BASE_PTR;

/* Enable external MRAM mapped on CS0 */

/* CS0 base address */

fb_ptr->CS[0].CSAR = 0x60000000;

/* CS0 control (16bit data, 2 wait state) */

fb_ptr->CS[0].CSCR = FB_CSCR_BLS_MASK |//低16位

FB_CSCR_AA_MASK  |

FB_CSCR_WS(0X2)    |

FB_CSCR_ASET(0X1)    |

FB_CSCR_PS(2)    |

FB_CSCR_WRAH(1)   |

FB_CSCR_RDAH(1)   |

FB_CSCR_BEM_MASK;

/* CS0 address mask and enable */

fb_ptr->CS[0].CSMR = FB_CSMR_BAM(0x1F) | FB_CSMR_V_MASK;//2M

fb_ptr->CSPMCR = FB_CSPMCR_GROUP3(2) | FB_CSPMCR_GROUP2(2);

}

关于Flexbus每个寄存器的含义,详参MCU的datasheet。

可靠性测试方案

外扩PSRAM一般用做内存使用,我们的应用程序的数据就是映射到片外的。所以PSRAM的可靠性必须要保证,必须是零容忍。不然就会出现异常死机的情况。这对于产品来说是绝对不允许的。所以虽然硬件软件已经通了,但对PSRAM的压力测试还是很有必要的。

方案:对PSRAM循环遍历读写不同数据并判断所写数据是否正确。源码如下:

void test_psram(void)

{

uint16 wdata16 = 0x5050;

uint16 rdata16=0;

uint32 n,i;

int add;

time++;

wdata16 += time*16;

for(n=0x0000;n<0x1ffff0;n+=2)

{

wdata16 += 1;

add = n;

*(vuint16*)(0x60000000+n) = wdata16;

rdata16 = 0;

rdata16 = (*(vuint16*)(0x60000000+n));

if((wdata16) != (rdata16))

{

error++;                   printf("%d,%d,W=0x%4x,R=0x%4x,add=0x%4x\n",time,error,wdata16,rdata16,add);

}

}

if(time%2 == 0)

{

printf("time = %d\n",time);

}

}

关于PSRAM的稳定性有几点需要分享给大家。

1.关于PSRAM(IS66WVE1M16BLL)供电电压,当初是采用3.3V供电,供应商也说3.3V供电没问题。但是不能通过我们的压力测试,遍历一次会有一些错误出现。芯片手册上是3.0V供电。

2. 压力测试,刚上电第一次遍历会有几个错误,其实比例很小,万分之一的样子。正如前面所说,对PSRAM的要求是零错误。所以这样的问题仍然会影响我们做出来的产品的质量,这个原因很难找,后面我们硬件上在锁存器和PSRAM的片选处加了上拉电阻问题得以解决。可能是上电时片选状态未知,导致PSRAM处于一个未知状态,修改了PSRAM什么配置吧,具体什么原因我实在说不上来,在此分享给大家。如果有不同意见的,欢迎指教!

原创文章,欢迎评论,转载标明出处,谢谢配合!

时间: 2024-11-10 00:15:42

FlexBus外扩PSRAM 应用实例详解的相关文章

实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(一)

在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然QuerySet的文档中已经详细说明了,但本文试图从QuerySet触发的SQL语句来分析工作方式,从而进一步了解Django具体的运作方式. 本来打算写成一篇单独的文章的,但是写完select_related()之后发现长度已经有点长了,所以还是写成系列,大概在两到三篇.整个完成之后将会在这里添加上

SQL存储过程实例详解

SQL存储过程实例详解 本文用3个题目,从建立数据库到创建存储过程,详细讲解数据库的功能. 题目1 学校图书馆借书信息管理系统建立三个表: 学生信息表:student 字段名称 数据类型 说明 stuID char(10) 学生编号,主键 stuName Varchar(10) 学生名称 major Varchar(50) 专业 图书表:book 字段名称 数据类型 说明 stuID char(10) 学生编号,主键 stuName Varchar(10) 学生名称 major Varchar(

免费的HTML5连载来了《HTML5网页开发实例详解》连载(三)DOCTYPE和字符集

在2.1.2节中通过新老DOCTYPE的对比,读者可以清晰地看到HTML 5在精简旧有结构上做出的努力.DOCTYPE在出现之初主要用于XML中,用作描述XML允许使用的元素.属性和排列方式.起初HTML借鉴了XML中DOCTYPE的使用方法,并赋予了新用法,如大家熟知的触发浏览器的标准模式.假使在制作一张页面时,没有设定DOCTYPE,则浏览器会以怪异模式状态进行处理(即Quirks模式),该模式与标准模式在盒模型.样式.布局等都存在较大差异.因此,DOCTYPE在制作页面时是不可或缺的部分.

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(五)

这是本系列的最后一篇,主要讲一下FreeMarker模板引擎的基本概念与常用指令的使用方式.     一.FreemMarker基本概念     FreemMarker是一个用Java语言编写的模板引擎,它是一个基于模板来生成文本输出的一个工具.是除了JSP之外被使用得最多的页面模板技术之一,另一个比较有名的模板则是Velocity.     用户可以使用FreeMarker来生成所需要的内容,通常由Java提供数据模型,FreeMarker通过模板引擎渲染数据模型,这样最终得到我们想要的内容.

javascript常用经典算法实例详解

javascript常用经典算法实例详解 这篇文章主要介绍了javascript常用算法,结合实例形式较为详细的分析总结了JavaScript中常见的各种排序算法以及堆.栈.链表等数据结构的相关实现与使用技巧,需要的朋友可以参考下 本文实例讲述了javascript常用算法.分享给大家供大家参考,具体如下: 入门级算法-线性查找-时间复杂度O(n)--相当于算法界中的HelloWorld ? 1 2 3 4 5 6 7 8 9 10 //线性搜索(入门HelloWorld) //A为数组,x为要

TCP/IP协议族——IP工作原理及实例详解(上)

 IP协议详解 本文主要介绍了IP服务特点,头部结构,IP分片知识,并用tcpdump抓取数据包,来观察IP数据报传送过程中IP的格式,以及分片的过程. IP头部信息:IP头部信息出现在每个IP数据报中,用于指定IP通信的源端IP地址.目的端IP地址,知道IP分片和重组. IP数据报的路由和转发:IP数据报的路由和转发发生在出目标机器之外的所有主机和路由器上.他们决定数据报是否应该转发以及如何转发. IP服务的特点 IP协议是TCP/IP协议族的动力,它为上层协议提供无状态.无连接.不可靠的

java网页爬虫简单实例详解——获取天气预报。

[本文介绍] 爬取别人网页上的内容,听上似乎很有趣的样子,只要几步,就可以获取到力所不能及的东西,例如呢?例如天气预报,总不能自己拿着仪器去测吧!当然,要获取天气预报还是用webService好.这里只是举个例子.话不多说了,上看看效果吧. [效果] 我们随便找个天气预报的网站来试试:http://www.weather.com.cn/html/weather/101280101.shtml 从图中可用看出,今天(6日)的天气.我们就以这个为例,获取今天的天气吧! 最终后台打印出: 今天:6日

C#中string用法实例详解

在进行C#程序设计时,用的最多的莫过于string了,但有些时候由于不仔细或者基础的不牢固等因素容易出错,今天本文就来较为详细的总结一下C#中string的用法.具体如下: 1.string是一个引用类型,平时我们比较string对象,比较的是对象的值而不是对象本身 如下面代码所示: string strA="abcde"; string strB="abc"; string strC="de"; Console.WriteLine(strA =

C#泛型Dictionary的用法实例详解

本文以实例形式讲述了C#中的泛型Dictionary的用法.具有很好的实用价值.分享给大家供大家参考.具体如下: 泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱. 很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类: 非泛型集合类 泛型集合类 ArrayList List<T> HashTable D