1、PC和嵌入式Linux的启动方式:
PC: BIOS ---->引导操作系统 ---->识别分区 ---->应用程序
嵌入式LInux: bootloader ---->引导linux操作系统 ---->挂接文件系统 ---->启动应用
由上述对比我们可以发现,linux的bootloader是类似于PC机的BIOS的。那么什么是bootloader呢?bootloader就是我们的裸机程序。
2、裸板程序的开发
Windows下我们采用:ADS、IAR、KEIL等等集成开发环境(IDE)。不推荐。
Linux下我们采用: GCC,GNU工具链。推荐。
2.1 裸板程序的开发流程:
i 编辑源代码文件
ii 编译/链接
iii 烧写测试
其中在编写程序这一步中,我们要意识到裸板程序开发和应用程序开发的不同之处。
在应用程序开发的过程之中,我们一般只编写main函数。那么我们编写的main函数到底最后是被谁调用以及何时调用的呢?我们的main函数是由启动程序调用的,但是在开发应用程序的时候启动程序是不需要我们自己去编写的。
在开发裸板程序的时候,我们分为两个步骤:第一步就是编写我们的启动代码;第二步再编写我们的C函数。
在启动代码中,我们需要:1、进行硬件设置以及相关初始化 2、调用我们编写的C函数。
在硬件设置中我们主要要做以下两个事情:设置CPU,告诉CPU外设基地址 和 关看门狗
在OK6410中CPU访问地址分为以下两个部分:
内存地址:0~0x6fff ffff
外设地址:0x7000 0000 ~0x7fff ffff 共256MB
下面我们就来分析一段启动代码:
1 /*告诉CPU外设基地址*/ 2 ldr r0,=0x7000 0000 3 4 orr r0,r0,#0x13 5 6 mcr p15,0,r0,c15,c2,4 7 8 /*关闭看门狗*/ 9 10 ldr r0,=0x7e00 4000 11 mov r1,#0 12 str r1,[r0]
很显然,上述代码分为了两个部分,我们首先来看第2行。
ldr r0,=0x7000 0000
//因为在这条代码里面存在'=',所以这是一条伪指令。它的意思是将0x7000 0000传送到r0。0x7000 0000是我们外设的基地址。
第4行
orr r0,r0,#0x13
//这条代码的意思是将r0里面的值与立即数0x13进行或操作,然后将得到的值再传送到寄存器r0中。这里为什么要讲r0里面的值与0x13进行或呢?我们后面马上讲到。
再看第6行
mcr p15,0,r0,c15,c2,4
//参看《arm1176jzfs内核参考》P3-130~P3-132。我们可以看到这几页详细讲述了Peripheral Port Memory Remap Register的每一位的意义,以及如何操作。
//这个寄存器翻译过来就是:外设端口存储重映射寄存器。也就是说我们要把我们外设的基地址写入到这个寄存器里面。那么我们来看看该寄存器的位定义。
//[31:12] Base Address
//[11:5] UNP/SBZ
//[4:0] SIZE。其中b010011表示256MB
//好了现在我们明白为什么要将我们外设的基地址与0x13进行或操作了。就是说在将基地址写入该寄存器的同时还得写入我们的外设所占的大小。我们的6410是256MB,所以或
//上0x13。
//那么这行代码是什么意思大家也就明白了吧?在《arm1176jzfs内核参考》有以下内容:
//MRC p15, 0, <Rd>, c15, c2, 4 ; Read Peripheral Port Memory Remap Register
//MCR p15, 0, <Rd>, c15, c2, 4 ; Write Peripheral Port Memory Remap Register
好的,接下来我们来看如何关闭看门狗。
代码第10行。
ldr r0,=0x7e000400
//这条代码的意思不用赘述。关键是0x7e00 0400是什么意思。参考s3c6410用户手册我们可以发现以下内容:
//WTCON 0x7E004000 读/写 看门狗定时器控制寄存器。
//这样我们就明白了,第10行代码是将我们看门狗控制寄存器的地址传送到我们的r0
接下来我们看下一条代码:
mov r1,#0
这条大家都明白,是将立即数0传送到寄存器r1
接下来我们看下条代码:
str r1 [r0]
这条代码的意思是将r1里面的值放入r0所指向的地址处。str可以理解为store。
也就是说上述三条代码实现了将我们的看门狗控制寄存器所有位清0的操作。参看刚才的手册,控制寄存器的第0位就是控制看门狗定时器enable和disable的位。将该位置0就可以disable看门狗定时器。