第2阶段——编写uboot之硬件初始化和制作链接脚本lds(1)
目标:
第一阶段:
1.关看门狗
2.设置时钟
3.初始化SDRAM (初始化寄存器以及清除bss段)
4.重定位 (将nand/nor中代码COPY到链接地址上,需要初始化nandflash,读flash)
5.执行main
进入第二阶段:
6.写main函数,在main()中设置要传给内核的参数,然后跳转内核基地址处
7.制作uboot.lds链接脚本
编写步骤:
1.创建个名为"my_bootloader"根目录,方便编写uboot
2.新建my_bootloader/si目录,创建source insight工程
2.1 新建my_bootloader/start.S (后缀名必须是大写的S,或者后面编译会报错)
编写start.S (第一阶段初始硬件文件):
start.s任务:
1.关看门狗
2.设置时钟
3.初始化SDRAM
4.重定位(把bootloader本身的代码从flash复制到它的链接地址(c函数编写),然后清空bss段(c函数编写))
5.执行main
/* 看门狗寄存器 */
#define WTCON 0x53000000 /* 2.时钟寄存器 */
#define CLKDIVN 0x4C000014 //设置FCLK,HCLK,PCLK比例
#define MPLLCON 0x4C000004 //设置FCLK频率
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02)) //设置FCLK=200MHZ
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01)) //设置FCLK=400MHZ /* 3.bank寄存器 */
#define BWSCON 0x48000000 .text /*设置代码段*/
.global _start /*定义全局变量,要被连接脚本用到*/
_start: /*_start跳转到这里实现硬件初始化*/ /* 1.关看门狗 */
ldr r0,=WTCON
mov r1,#0
str r1,[r0] /* 2.设置时钟(必须设为异步总线模式) */ ldr r0,=CLKDIVN
mov r1,#3 /*FCLK:HCLK:PCLK=1:2:4*/
str r1,[r0]
mrc p15, 0, r1, c1, c0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
ldr r0,=MPLLCON
ldr r1,=S3C2440_MPLL_200MHZ //使用复杂的数不能用mov,需要用ldr
str r1,[r0] /* 3.初始化SDRAM */
ldr r0,=BWSCON //r0=SDRAM寄存器基地址
adr r1,SDRAM_CONFIG //使用adr相对跳转,因为SDRAM未初始化
add r2,r0,#(13*4) //r2等于 SDRAM尾地址+4 0:
ldr r3,[r1],#4 //r3=r1里的 内容, &r1+=4;
str r3,[r0],#4 //*r0=r3,&r0+=4
cmp r0,r2
bne 0b //(ne:no equal b:bank) 若r0!=r2,跳转到后面的0处 /* 4.重定位 */
ldr sp,=0x34000000 //64Msdram,所以设置栈SP=0x34000000,避免堆栈溢出
mov r0,#0 //r0->src
ldr r1,=_start //r1->dest
ldr r2,=__bss_start //r2->len->__bss_start-_start
sub r2,r2,r1
bl copy_code_to_sdram //复制代码到SDRAM连接地址dest上
bl clear_bss //清除bss段 /* 5.执行main */
ldr lr,=halt //执行一个子程序调用返回时,需要先将返回地址赋给lr链接寄存器
ldr pc,=main //初始化SDRAM后,可以使用pc 绝对跳转到SDRAM地址上
mov pc,lr //若main函数跳出后,使PC等于lr链接寄存器,避免程序跑飞 halt: //死循环,避免跑飞
b halt SDRAM_CONFIG:
.long 0x22011110; //BWSCON
.long 0x00000700; //BANKCON0
.long 0x00000700; //BANKCON1
.long 0x00000700; //BANKCON2
.long 0x00000700; //BANKCON3
.long 0x00000700; //BANKCON4
.long 0x00000700; //BANKCON5
.long 0x00018005; //BANKCON6
.long 0x00018005; //BANKCON7
.long 0x008C04F4; //REFRESH
.long 0x000000B1; //BANKSIZE
.long 0x00000030; //MRSRB6
.long 0x00000030; //MRSRB7
3 新建my_bootloader/init.c,用于重定位,bss段清除,初始化NandFlash等
在重定位函数中的nand驱动在(入口:http://www.cnblogs.com/lifexy/p/7097695.html)里详细介绍了,这里就不描述了.
3.1编写copy_code_tosdram() 重定位函数
void copy_code_to_sdram(unsigned char *src,unsigned char *dest,unsigned int len) //复制代码到SDRAM连接地址dest上
{
unsigned int i;
/*判断nor启动还是nand启动*/
if(is_boot_from_norflash()) //nor启动,直接复制
{
for(i=0;i<len;i++)
{
dest[i]=src[i];
}
}
else
{
nand_init(); nand_read((unsigned int)src,dest,len); }
}
3.2编写isBootFramNorFlash()函数,来判断nand启动还是nor启动
/*判断nor启动还是nand启动*/
unsigned char is_boot_from_norflash(void)
{
volatile unsigned int *p=(volatile unsigned int *)0;
unsigned int i;
i=*p;
*p=0x12345678;
if(*p==0x12345678) //nand
{
*p=i;
return 0;
}
else //nor
{
*p=i;
return 1;
}
3.3编写clear_bss()函数
void clear_bss(void) //清除BSS段
{
extern int __bss_start,__bss_end;
int *p=&__bss_start;
for( ;p<&__bss_end;p++)
{
*p=0;
}
}
4编写连接脚本uboot.lds (参考硬件实验里的uart.lds和u-boot-1.1.6里的u-boot.lds)
SECTIONS {
. = 0x33f80000; //0地址里存放0X33F80000
. = ALIGN(4); .text : { *(.text) }
. = ALIGN(4); .rodata : { *(.rodata) }
. = ALIGN(4); .data : { *(.data) }
. = ALIGN(4); __bss_start = .;
.bss : { *(.bss) *(COMMON) }
__bss_end = .;
}
其中0x33f80000就是链接地址首地址,共512K空间存放bootloader
定义__bss_start和__bss_end符号,是用来程序开始之前将这些未定义的变量清0,节省内存
且bss_start-0x33f80000就等于代码的大小(copy_code_tosdram函数中len值)
第2阶段——编写uboot之硬件初始化和制作链接脚本lds(1)的更多相关文章
- 第2阶段——编写uboot之启动内核和制作Makefile(2)
目标: 1 添加头文件setup.h和serial.h 2 写main函数 2.1 帮内核设置串口0, (内核启动会打印出启动信息) 2.2把内核读入到SDRAM 2.3设置参数(参考u- ...
- 第2阶段——编写uboot之编译测试以及改进(3)
编译测试: 1.将写好的uboot复制到linux下面 2.make编译,然后将错误的地方修改,生成boot.bin (编译出错的解决方案:http://www.cnblogs.com/lifexy/ ...
- 第1阶段——uboot分析之硬件初始化start_armboot函数(5)
start_armboot()分析:在start.S初始化后跳转到start_armboot实现第2阶段硬件相关的初始化(烧写擦除flash,网卡驱动,usb驱动,串口驱动,从FLASH读内核,启动内 ...
- 第1阶段——uboot分析之硬件初始化start.S(4)
分析uboot第一个执行函数_start(cpu/arm920t/start.S) 打开cpu/arm920t/start.S .globl _start // .globl定义一个全局符号" ...
- u-boot中nandflash初始化流程分析(转)
u-boot中nandflash初始化流程分析(转) 原文地址http://zhuairlunjj.blog.163.com/blog/static/80050945201092011249136/ ...
- 硬件初始化,nand flash固化操作,系统启动简单流程
2015.3.27星期五 晴 链接脚本定义代码的排放顺序 硬件系统初始化:一:arm核初始化:(里面有指令)初始化ARM核的时候需要看arm核的手册指令:1.异常向量(最起码有个复位异常,初始化模式- ...
- 15.uboot study 串口初始化
3. 串口初始化 4. 代码实现 关于串口 对于嵌入式设备的开发,刚开始好多设备都无法使用,由于无法获得程序的运行状态,调试程序需要花费好多时间和精力,因此串口对于嵌入式程序的调试的作用显而易见,当串 ...
- 第1阶段——关于u-boot目标文件start.o中.globl 和.balignl理解(3)
汇编程序中以.开头的名称并不是指令的助记符,不会被翻译成机器指令,而是给汇编器一些特殊指示,称为伪操作. .globl _start 作用:声明一个_start全局符号(Symbol), 这个_sta ...
- u-boot的配置、编译及链接
第一次写技术博客,还有些兴奋呢.我是CrazyCatJack,大家可以叫我CCJ或者疯猫.我即将成为一名嵌入式Linux的驱动工程师,现在还是一枚大四狗,呼呼~大学期间做了一些项目和比赛,都是基于32 ...
随机推荐
- LoadRunner性能测试-loadrunner事务
事务(Transaction): 简单来说就是用来模拟用户的一个相对完整的业务过程.添加事务,是用来衡量响应时间的重要方法.我们可以通过事务计时来对不同压力负载下的性能指标进行对比. 插入事务的方法: ...
- Typescript变量声明
let 和 const 是 javascript 里面最新的变量声明方式,let 与 var 很相似,而 const 是 let 的增强,能阻止对一个变量的再次赋值. var 声明 弱类型:var 声 ...
- 移动Web学习笔记(第1天)-bootstrap框架的使用
移动web前言 移动web : 移动端手机浏览器或者微信里面浏览的网页 移动APP : 手机上需要下载安装的应用程序 1. 移动web介绍 1.1 3 天 响应式开发 一套代码运行多个终端 优点:开发 ...
- 原理Lambda表达式
http://www.kingreatwill.com/ (1)源起 .net的设计者发现在使用匿名方法时, 仍旧有一些多余的字母或单词的编码工作 比如delegate关键字 于是进一步简化了匿名方法 ...
- Activity中finish()和onDestroy()的区别
finish()方法用于结束一个Activity的生命周期,而onDestory()方法则是Activity的一个生命周期方法,其作用是在一个Activity对象被销毁之前,Android系统会调用该 ...
- Linux - 简明Shell编程05 - 条件语句(Case)
脚本地址 https://github.com/anliven/L-Shell/tree/master/Shell-Basics 示例脚本及注释 #!/bin/bash var=$1 # 将脚本的第一 ...
- android学习ScrollView的使用
ScrollView 的使用相对来讲比较简单,通过包含更多的布局文件,使得上下滑动可以浏览到更多内容. 关于ScrollView有几个点需要注意的地方 1,ScrollView的滚动方式 Scroll ...
- 设计模式(3)--FactoryMethod( [2] 工厂方法模式)--创建型
1.模式定义: 工厂方法是针对每一种产品提供一个工厂类.通过不同的工厂实例来创建不同的产品实例. 2.模式特点: (1)工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承. (2 ...
- CSS常见英语单词属性一览
这些是css中常会用到的一些英文单词,大家可以多看看,多使用就会容易记得了. color : #999999; /*文字颜色*/ font-family : 宋体,sans-serif; /*文字字体 ...
- DLL基础
Visual C++在创建DLL导出函数时,可能会对原始的函数名做修改.例如: int WINAPI Add(int nLeft, int nRight) 导出后的函数名称是_Add@8. 下面两种方 ...