现在的位置: 首页 > 综合 > 正文

U-BOOT中SDRAM的初始化分析

2018年01月09日 ⁄ 综合 ⁄ 共 4892字 ⁄ 字号 评论关闭

转帖: ------------------------------------------------------------

 

最近一直在研究嵌入式的东西,如果我对某项东西或是技术着迷,我会想方设法搞明白我感兴趣的部分,我对我的自学能力越来越有信心了,唉,有点儿自恋了。

关于内存时序初始化的部分,我看了很长时间,这处卡着我的学习可能有一个多星期了,很郁闷。现在回想起来,自己卡在这块,主要的原因还是对S3C2440的手册研究得不够透彻,没有仔细看手册,导致好些个关键的地方都忽略过去了。

现在进入正题

首先说一说时钟频率,因为内存对时钟的频率也有要求,时钟频率对内存也有影响。

在对内存进行初始化之前,u-boot-1.1.6在start.S处对时钟频率进行了一个比例上的初始化,相关于语句如下:
 
 /* FCLK:HCLK:PCLK = 1:2:4 */

 /* default FCLK is 120 MHz ! */
 ldr r0, =CLKDIVN
 mov r1, #3

 str r1, [r0]

这个CLKDIVN寄存器就存放了FCLK,HCLK,PCLK三个不同时钟频率之间的关系。这个寄存器被设为了3,那么根据S3C2440手册的第7章的表,可以查到,UCLK=UPLL,HCLK=FCLK/2,PCLK=HCLK/2,即FCLK:HCLK:PCLK = 1:2:4。

那么这里有一个疑问,就是在被设置这个3值之前,这三个时钟的比例是什么呢?那么查一下CLKDIVN这个值的初始值表就知道,初始值是全0的,那么一查表,就是FCLK:HCLK:PCLK = 1:1:1。

还有一个问题,不知道大家注意了没有,就是上面的一个注释,default FCLK is 120 MHz。其实这句注释是有错误的。FCLK是提供给CPU使用的时钟,那么通过什么途径能确定这个FCLK在启动的时候,默认的频率就是120Mhz呢?

经过我对S3C2440手册第7章的仔细研究,发现手册中有这么一句话,翻译成中文大概的意思就是:大家都清楚,在开启电池与重起的过程中,PLL 是不稳定的,所以这个时候,实际上是由Fin这个时钟代替了Mpll,给FCLK提供了时钟频率。一直到有软件重新设置PLLCON寄存器。

那么这里就很明白了,默认的FCLK是频率,是与Fin频率是一致的,直到有软件重新设置了PCCLON寄存器。如果这里Fin的频率是120Mhz,那么上面的这句注释就没有问题,那么这个Fin到底是多少呢?

我手里没有相应的设备来检测这个Fin的频率,但是我在第7章找到了一个名为PLL VALUE SELECTION TABLE的表。实际上,CPU的频率是由MPLL来生成的,那么MPLL又是由Fin、MDIV、PDIV、SDIV由一个公式算出来的。而且这里的值,又都有一个范围,并不是仅满足相应的公式就可以了的,为了减少大家计算的麻烦,所以这个表就给出了一个可供参考的,各个数值的大小的列表,也即推荐使用的值。

根据这个表,可以查到,当输出的时钟频率为405.00MHz的时候,Fin为12Mhz。我想这里的值,应该就是Fin的频率值,也即默认的FCLK的值。

支持我的猜测的就以下几个理由:

1.S3C2440的ARM920T核心,可以运行在200Mhz至533Mhz之间,但是400Mhz是其最稳定,又最快的一个结合点,所以一般就会把CPU的频率定到这个405Mhz的位置。

2.Fin的频率越低,所实现这个Fin的代价就最小,消耗的能量就最少。

根据这两个理由,没有理由不使用这组数值。

所以这里的默认的FCLK的值,应该为12Mhz,并不是120Mhz,可能是作者写错了。

在这里,我还要鄙视卖我开发板的这个公司,这个公司在国内做得也比较大,技术人员老全国各地到处跑,但当我问到他们板子上相关技术问题的时候,从来没有给我满意的答复,这次也是。关于这个Fin的频率,我查过不少资料,终于发现这个频率,应该是在S3C2440板子上的那个钮扣电池及其相应的电路来提供的。当我咨询他们的技术支持QQ关于此电池提供时钟的具体值与作用时,告诉我给他们发邮件询问此事,技术人员出差了。然而,我的邮件,他们一个星期都没有回。然后我又咨询他们的QQ,他们只说这是提供实时时钟的,别无其它用处,但当我问其具体的频率值时,则不回答我仍何问题了,这个态度跟我当时买开发板的时,那简直是一个天上,一个地下。我也活该,谁叫我当时一点儿也不懂呢。

现在想想国内这些个公司啊,很可能这些个硬件都是超葫芦画瓢,直接抄的国外的板子,自己根本就没有相应的技术开发与储备,唉。

这是关于FCLK、HCLK、PCLK的相关的说明,下面说说内存的时序

在u-boot-1.1.6里面,内存的时序设置,是在lowlevel_init.S中来进行的。我的板子提供的内存型号是K4S561632H -UC75,这里再鄙视一下这个公司,给我提供的文档里,告诉我内存的型号是K4S561632E-UC75,搞得我一开始找内存的数据手册都找错了。

根据S3C2440手册中第5章内存控制的说明,可以看出,咱们的内存是被映射在了0x30000000-0x40000000的位置,即 bank6与bank7。那么在内存时序设置的时候,主要关心的,就是bank6与bank7。当然,bank0也是需要关注的,因为它是启动时,启动程序存放的位置。但是bank0是由OM[1:0],即板子上的那几个小开关中的两个来控制的,所以这里程序上是不用管它的。

这里有一点需要说明一下,因为我还没有看到u-boot-1.1.6后面的内容,所以不知道对bank1-bank5的初始化,对板子有什么样的影响,所以这一块暂时不做说明,主要说明一下对bank6与bank7的时序初始化。

在S3C2440手册上,对bank6与bank7的描述,当MT的值为0x3(11bin)的时候,表示使用的是SDRAM,所以B6_MT与B7_MT的值为0x3。

当bank6与bank7为SDRAM的时候,那么就只需要设置Trcd与SCAN的值。

那么Trcd的0x1,即3clk是怎么来的呢?

咱们先看一下S3C2440的手册的第27章,FCLK最大的频率值为400Mhz,HCLK最大为133Mhz,PCLK最大为67Mhz。再查一下关于这些个时钟频率的使用就可以知道,内存方面,是由HCLK来控制的。那么经过简单的计算就可以知道,内存的一个时钟周期,最短为7.519ns。再看一下K4S561632E-UC75的数据手册,关于Trcd的值的描述,K4S561632E-UC75的内存,这个值,最少需要20ns。如果 Trcd为2clk,则时间不够,差一点儿,所以只能填3clk。如果最短的时间都能满足,那么当内存工作在比133Mhz低的情况下,就更能满足了,所以这里的Trcd为3clk。

另外插一句,当FCLK工作在400Mhz的时候,HCLK工作在133Mhz的时候,它们之间的比例,绝对不会是1:2(如果是1:2,我不知道是烧板子呢,还是工作不稳定,没有试过,也不敢试)。所以我想,在u-boot-1.1.6的后面,肯定还有地方对CLKDIVN进行重新设置,如果不设置成合适的比例,很可能会出现问题。

还有一个值,SCAN怎么确定的呢?

我们查一下关于K4S561632E-UC75的手册就知道,这个型号的内存,地址组织形式为16M x 16,再查一下PIN FUNCTION DESCRIPTION这个表就可以知道,这个形式的内存地址的Column Address为(CA0 ~ CA8),即9bit,所以值为0x1。

到此为止,SDRAM的内存就被正确初始化了。

因为我在这里,花了非常多的时间,为了后面的人能减少研究的时间,特意把这块提前写出来,将来我把所有的u-boot-1.1.6的源码都分析完了,在详细源码分析里,这些内容,也都会在相应的代码注释里体现出来。现在时间越来越紧,

不知道什么时候能完成这个工作。

fin (frequency in)12M是外部晶振,也有用16.9344m的;你看你板子上是不是有个12m的晶振;那个电池确实是只提供rtc的,和电子表里的电池功能一样,只给那个32.768k提供电源,保证系统时间的准确性,仅此而已。一般demo 板 上有3个晶振,1个20m是cs8900的,一个12m是fin,1个32。768是rtc的
2440最高支持533m,大多数都用400左右,一般是基于发热问题的考虑
只要保证HCLK不超过133 PCLK不超过66,fclk越高cpu性能更好,当然要保证散热不是wt

多谢你的回复,你的回复使我明白了,原来CPU工作在400Mhz左右是因为发热量的考虑,并不是稳定性的考虑。
我的硬件知识不行,不会看板子的电路,所以也看不出来这个Fin是提供的多少频率的晶振,我是根据各个方面的信息来推测这个晶振可能的工作频率的,而且就算我有测试设备,我也不知道如何去测试这个晶振的频率。我也知道晶振可以用16Mhz的那个,但我认为一般情况下,肯定会选择低的那个产品化。
我还没有看到关于CS8900这块的东西,而且我板子提供的网卡芯片,好像是DM9000,所以很可能有些地方不一样,我通过电路板也看不出来给网卡芯片提供时钟的频率是多少,唉,等到时候看到相应的地方再说了

之前在我的博客里,说到了关于u-boot-1.1.6对于内存初始化处的理解,指出了u-boot-1.1.6中一些代码上的错误,还有注释上的错误,具体的文章链接地址为:http://haoyeren.blog.sohu.com/89070824.html

现在根据我的进一步实验与理解,更正我的说法。

实际上,并不是说对方的代码或是注释有错误,而是由于我们是把S3C2410的代码拿过来,改成S3C2440的板子需要的代码,S3C2410与 S3C2440的板子,它们之间是有区别的,所以代码与注释应该是没有错误的,错误的是我们,是我们把S3C2410的代码拿来修改成S3C2440的板子能用的代码。

我现在正在修改我自己的u-boot-1.1.6的代码,我在根目录中的Makefile中加入了我自己的编译目标,为:

haoyeren2440_config :   unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t haoyeren2440 NULL s3c24x0

从上可以看出,我把我板子命名为haoyeren2440。

然后在源码目录路径为:u-boot-1.1.6/include/configs的位置,新加一个名为haoyeren2440.h的文件,这个文件里面有我自己的板子编译的时候需要使用的一些全局变量,例如CONFIG_ARM920T,CONFIG_S3C2440, CONFIG_HAOYEREN2440。这些个全局变量,会在好些个源码里面,起到条件编译的开关作用。

因为我用了我自己的变量,把原先CONFIG_S3C2410的变量改成了CONFIG_S3C2440,在源码里,是没有做这个条件编译的逻辑的,所以编译的时候,肯定会出N多错误,其实不要紧,只要细心,看看是哪个文件出错了,然后顺藤摸瓜,就可以找到相应的源码,然后修改源码,加上 CONFIG_S3C2440的条件编译逻辑就可以了呵呵,如果是与S3C2410一模一样的条件编译内容,那就把CONFIG_S3C2440用||给连在后面,如果不一样,就写上S3C2440应该有的内容就可以了。

我已经把我自己的代码整个都修改通过了,现在已经可以正确的编译出u-boot的烧录文件了,通过仿真器放到开发板内存里也可以执行,但是由于有几个地方代码有BUG,而且自己还在研究某些指令的具体作用,所以在一边改代码,一边做测试,进度就很慢。

我写这篇博文的目的一是纠正自己的错误,还是就是想告诉跟我一样的新手,做自己的u-boot移植,如果想做得完美一些,应该怎么样来做,唉唉,我是一个完美主义者,没办法

 

抱歉!评论已关闭.