自己编写bootloader(一):编写前的介绍及关闭看门狗和时钟的设置

    我们知道,U-Boot最大的作用就是启动内核。然而,启动内核之前,它也要做许多事情。接下来,我们就自己编写一个bootloader,让它执行启动内核的功能。

    对于bootloader,我们知道,它的第一段代码就是Start.S,这是一个汇编文件,在这个文件里面,我们进行一些硬件的初始化,也就是bootloader初始化的第一阶段。在这个初始化里面,我们需要做以下事情:  

    1.关看门狗

    2.设置时钟

    3.初始化SDRAM

    4.重定位代码

对于上面的步骤,我分别解释一下。首先,关看门狗,是防止程序定时重启;设置时钟,可以设置机器的运行频率,如CPU运行频率,与HCLK有关的部件的频率、与PCLK有关的部件的频率。初始化SDRAM,即初始化内存,作用不用多说。对于重定位代码,也是必须的。我们知道,对于S3C2440,一般上电后在NorFlash或者NandFlash运行。对于NorFlash上的代码,我们可以执行,但是写起来效率很低。对于NandFlash,上电后的前4K的复制到SRAM中去执行。然而,4K后的代码就复制不到了,所以如果我们的bootloader超过4K的话,就炸了!因此,我们需要将我们的代码,复制到内存SDRAM里,那里容量又大,又可以读又可以写又可以执行,美滋滋。

    我们一步步来实现:首先,我们先关看门狗。怎么关闭呢?我们要看相关产品的芯片手册才知道。这里我们对S3C2440进行操作,我们看到它的芯片手册中的Whatchdog Timer这一章的WTCON这个寄存器这里:

我们看到Watchdog timer这里,它的描述是使用或者禁止Watchdog Timer,我们的目的是关闭看门狗,所以我们只要另它这里的值为零就好了。为了方便,我们可以直接把零赋值给这个寄存器,因为我们都关闭它了,它的功能我们也用不到,其它位赋值其它值也没有关系。到这里,我们就可以写出关闭看门狗的代码了:

/* 1.关闭看门狗 */
ldr r0,=0x53000000
mov r1,#0
str r1,[r0]

可以看到,这个代码并不难。接下来我们就研究一下怎么去初始化时钟。我们首先看一下芯片手册里关于时钟的部分:

扫描二维码关注公众号,回复: 882385 查看本文章

首先,在产生时钟前,我们需要先选择时钟源,时钟源有两种:外部时钟和晶振。那么开发版是如何选择它的时钟源的呢?我们可以看到这里:

从表格及解释我们可以知道,时钟源的选择,由OM3和OM2的值决定。那么引脚OM3和OM2的值是多少呢?我们可以打开S3C2440的电路图查看一下:

我们看到,这两个引脚都是直接接地的,所以它们恒为低电平,也就是恒为0。对照表我们就可以知道,开发板的Main Clock Source和USB Clock Source的选择都是晶振。我们继续看到上面的图:晶体或外部的时钟首先经过振荡器,产生时钟,然后经过选择器,对于Main Clock,选择器选择的是晶振所产生的时钟。接着,就到达了MPLL根据P、M、S三个参数来产生FCLK,送到时钟控制单元处,时钟控制单元除了将FCLK直接发送到电源控制单元处外,还将其分别发送到HDIVN分频器和PDIVN分频器分别产生HCLK和PCLK,然后分别到达各个外设。以上就是时钟产生的过程。我们可以用一个图来表示一下:

因此,这里我们实际上就设置MPLL,HDIV和PDIV就可以了。这些操作其实都是对寄存器的操作,接下来我们看一下有什么寄存器可以进行设置。在这之前,我们还要看一下相关的时序图:

上面就是上电后的顺序。我们看到上电后,由于系统电压信号等还不稳定,这时复位信号(nRESET)拉低,这时MPLL默认启动,但是如果不向MPLL写入值,那么外部晶振直接就作为系统时钟FCLK,过几毫秒后,复位信号上拉,CPU开始取值运行,这时MPLL就可以按照设定的MPLLCON的值进行工作了。MPLL会产生新的FCLK,但这个过程是需要一定时间的,也就是Lock Time,这时FCLK停止输出,CPU停止工作,过了Lock Time之后,MPLL就稳定了,就可以产生稳定的FCLK了,然后FLCK可以根据FCLK、HCLK、PCLK这三者的比例来产生HCLK和PCLK。所以其实我们要做的有以下步骤:

    l 设置LockTime变频锁定时间

    l 设置FCLK与晶振输入频率(Fin)的倍数

    l 设置FCLK,HCLK,PCLK三者之间的比例

首先看到LockTime,我们怎么去设置呢?只需要设置LOCKTIME寄存器就好了:

但这里,为了方便,我们省略这一步骤,Lock Time使用默认值即可。接下来,就是第二步了,也就是设置MPLL的值:

这里我们设置MPLLCON里的位就好了,UPLLCON是USB的。那么怎么去设置呢?这里是有一条公式的:

我们可以用这条公式推算出我们想要的频率应该怎么去设置,但这里还有一种更简便的办法,它的下面有一个表格,它里面已经有相关频率该怎么去设置了。这里我们希望CPU运行到它最大的正常工作频率,也就是400MHz,那么就要把MDIV设为92,PDIV和SDIV设为1。接着,我们就要做最后一步了,也就是设置FCLK:HCLK:PCLK的比例,这里的话,我们可以通过设置CLKDIVN这个指令来实现:

这里,我们只需设置HDIV和PDIV的相关位就好了,我们令FCLK:HCLK:PCLK=1:2:4,所以HDIVN应该为01,PDIVN应该为1。因此我们在这个寄存器里面写入3就好了。但在此之前,手册里有些东西还需要我们进行注意的:

如果HDIV不为零的话,需要设置CPU的总线模式为异步模式(默认为快速总线模式),如果不设置的话,CPU的频率会受到影响,下降一半甚至更多。这里的我们就直接把它的代码使用上就好了(#R1_nf:OR:R1_iA这个值为#0xc0000000)。到这里,时钟设置的所有步骤就做完了,我们把代码写一下:

#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
//设置CLKDIVN,FCLK:HCLK:PCLK=1:2:4
ldr r0,=0x4c000014
mov r1, #0x03
str r1, [r0]
//设置CPU使其处于异步模式:
mrc p15, 0, r1, c1, c0, 0
orr r1, r1, #0xc0000000 	
mcr p15, 0, r1, c1, c0, 0
//设置MPLLCON
ldr r0,=0x4c000004
ldr r1,=S3C2440_MPLL_400MHZ
str r1,[r0]

猜你喜欢

转载自blog.csdn.net/xiaokangdream/article/details/79621050