u-boot核心初始化

摘要:
()softwareinterrupt:软中断()预取中止:预取中止数据中止:提取数据失败----------------------------------------------代码编译:start.Stouchstart.Schmod777start.S.text.global_start_start:bresetldrpc,_ undefined_ instruction//ldrpc,_Fiq//will_Fiq中的值存储在PC_ undefined_指令中:.word undefined_指令_软件_中断:.word软件_中断_数据_中止:.word数据_中止_未使用:.word未使用_ irq:.word irq_ Fiq:.wordfiq//_ Fiq中存储的地址已定义_指令:nopsoftware_中断:nopdata_中止:nopnot_使用:nopirq:nopfiq:nopreset:no---------------------------------------------gboot.ldstouchboot.ldschmod777gboot.ldsOUTPUT _ ARCH@输出格式为armENTRY@,表示程序的交集为:_ StartSECTIONS{.=0x50008000@定义起始地址。=ALIGN;.text:{start.o@代码段中的第一个文件。*}=ALIGN;。数据:{*@all Data}=ALIGN;bss_start=。;。bss:{*}bss_end=.;}----------------------------------------------TouchMakefilechmod777Makefileall:%。oarm linux ld Tgboot。lds-ogboot。elf$^arm linux objcopy Obinarygboot。埃尔夫格布。bin%。o: %。arm-linux-gcc-g-c$^%。o: %。s----------------------------------------------设置SVC模式:p52页,第49页:M[0:4]设置模式要使处理器在SVC模式下工作,需要将程序状态寄存器cpsr的最后五位设置为10011。想法:首先清除所有五个位并将其设置为1:orr(位OR),然后添加mrs、msr指令。数据s3c6410page:1137图34-1显示,我们的引导加载器相对简单,因此我们不需要看门狗:关闭它。

异常向量表:
异常:因为内部或者外部的一些事件,导致处理器停下正在处理的工作,转而去处理这些发生的事件。ARM Architecture Reference Manual p54页。
7种异常的类型:
Reset异常:突然按下重启键。
Undefined Instruction:未定义指令。()
software interrup:软中断()
Prefetch Abort (instruction fetch memory about):预取中止
Data Abort:提取数据失败。
IRQ:中断
FIQ:快速中断 (响应速度更快)
------------------------------------------------------
异常向量:(p54)
当一种异常发生的时候,ARM处理器会跳转到对应该异常的固定地址去执行异常处理程序,这个固定的地址,称之为异常向量。
-------------------------------------------
异常向量表:由七个异常向量及其处理函数跳转关系组成的表
0x0000000:b reset
0x0000004:ldr pc,_undefined_instruction
0x0000008:ldr pc,_software_interrupt
0x000000c:ldr pc,_prefetch_abort
0x0000010:ldr pc,_data_abort
0x0000014:ldr pc,_not_used //使用无用的指令占据这个地址
0x0000018:ldr pc,_irq
0x000001c:ldr pc,_fiq
在start.S中我们是可以看到这张表的。
------------------------------------------------
代码的编写(start.S,makefile,gboot.lds):
start.S
touch start.S
chmod 777 start.S
.text
.global_start
_start:
b reset
ldr pc,_undefined_instruction //
ldr pc,_software_interrupt
ldr pc,_data_abort
ldr pc,_not_used
ldr pc,_irq
ldr pc,_fiq //将_fiq中的值存放到pc中
_undefined_instruction:.word undefined_instruction
_software_interrupt:.word software_interrupt
_data_abort:.word data_abort
_not_used:.word not_used
_irq:.word irq
_fiq:.word fiq //_fiq中存放的地址为fiq

undefined_instruction:
nop
software_interrupt:
nop
data_abort:
nop
not_used:
nop
irq:
nop
fiq:
nop
reset:
nop
-----------------------------------------------------------
gboot.lds
touch gboot.lds
chmod 777 gboot.lds

OUTPUT_ARCH(arm) @输出格式为arm
ENTRY(_start) @表明程序的路口处为:_start
SECTIONS{
. =0x50008000 @定义起始地址
. =ALIGN(4);
.text :
{start.o(.text) @代码段放的第一个文件。
*(.text)
}
. =ALIGN(4);
.data :
{
*(.data) @所有的数据
}
. =ALIGN(4);
bss_start = .;
.bss :
{
*(.bss)
}
bss_end = .;
}
-----------------------------------------------
touch Makefile
chmod 777 Makefile
all : %.o
arm-linux-ld -Tgboot.lds -o gboot.elf $^
arm-linux-objcopy -O binary gboot.elf gboot.bin
%.o : %.s
arm-linux-gcc -g -c $^
%.o : %.s
-----------------------------------------------
设置SVC模式:p 52页,49页M[0:4]设置模式(cpsr)
要让处理器工作在SVC模式就是要将程序状态寄存器cpsr的后五位设置为10011.
思路:先将这五位全部清理(bic指令)
置1的操作:orr(位或)
然后再加上mrs,msr指令。
首先我们应该是在开发板上电以后,然后来设置处理器的工作模式。所以:reset:
bl set_svc
set_svc:
mrs r0,cpsr //将状态寄存器中的值取出到通用寄存器中
bic r0,r0,#0x1f //将该值置0
orr r0,r0,#0xd3(或0x13) //位或操作,设置模式编号
msr cpsr,r0 //将该编号重新放到状态寄存器中。
------------------------------------------------------
关闭看门狗:
watchdog一般是一个硬件模块,其作用就是在系统死机时,帮助系统实现自动重新启动。
看门狗工作原理:watchdog在硬件上实现了计时功能,启动计时后,启动计时后,软件必须在计时结束前(5分钟或更久)重新开始计时,称为喂狗,如果到超时的时候还没有重新开始计时,那么它就认为系统死机了,就自动重新启动系统。
资料s3c6410page:1137图34-1
应为我们的bootloader比较简单,所以不需要看门狗:关闭。
如何关闭看门狗:通过prescaler(PCLK)这个寄存器来关闭。
控制寄存器:WTCON(watch timer control register):0x7E004000
reset:
bl set_svc
bl disable_watchdog
#define pWTCON 0x7E00400 //保存寄存器的地址
diable_watchdog:
ldr r0,=pWTCON //将立即数pWTCON中的内容装载到r0中
mov r1,#0x0 //r1寄存器中装入0x0
str r1,[r0] //将r1中的内容存储到r0中的有效地址
----------------------------------------------------------
关闭中断:
cpsr中N Z C V I F其中I位是控制中断的,F位是控制快速中断的。
分为两步:先将I,F位设置为1.在之前设置svc时已经设置好了
设置中断屏蔽寄存器ps3c2440 389,378
2440的操作:bl disable_interrupt
disable_interrupt:
mvn r1,#0x0
ldr r0,=0x4a000008
str r1,[r0]
6410一般采用的是向量中断的模式,更多的时候采用的是硬件中断。找到interrupt enable这个寄存器。p419页,需要关闭两个寄存器,VIC0INTENCLEAR(中断使能寄存器),VIC1INTRNCLEAR (关闭中断)。
disable_interrupt:
mvn r1,#0x0 //将0x0取反存放到r1中
ldr r0,=0x71200014 //将寄存器地址装载到r0中,相当与r0为该地址的替身。
str r1,[r0] //把r1中的值存放到r0中。
ldr r0,=0x71300014
str r1,[r0]
210则需关闭四个VICxINTENCLEAR.
----------------------------------------------------
关闭mmu和caches
ARM存储体系:处理器内部寄存器(通用,状态寄存器,速度快,数量少),TMC:紧耦合存储器(Cache,主存储器,容量大,速度稍慢),辅助存储器(Flash,SD等!)
cache:是一种容量小,但存取速度非常快的存储器,它保存最近用到的存储器中数据的拷贝。
按功能分:
I-Cache:指令Cache,用于存放指令.
D-Cache:数据Cache,用于存放数据.
mmu:将虚拟地址映射到物理地址。
虚拟地址:可以解决访问内存冲突,让进程使用更大的空间。
虚拟地址原理:用户指定了一个虚拟地址(4G),然后会通过映射将这些地址映射到不同的物理地址中。
因为使用mmu和cache需要一个正确的配置才能正常的使用。所以在这里我们先不使用,否则会导致意向不到的后果。
cache和mmu都是通过协处理器来控制的co-processor.
2440arm核手册p35 register control(read/write control register)先利用指令MRC p15,r0,c1,c0,0 把Register 1中的内容度到r0中,然后再修改r0中的值,在利用指令MRC p15,0,r0,c1,c0,0
Register1p36,看到第12位控制ICache,Cache disabled,第2位控制DCache,第0位控制mmu.
p41,还有一些数据我们需要设置,在Register7中是cache无效,invalidate cache。instruction:MCR p15,0,Rd,c7,c7,0
----------------------------------------------------
如何关闭cache//在arm11中操作是相同的。
1.使ICache和DCache失效。
2.关闭I/Dcache,关闭mmu
代码: bl disable_mmu
disable_mmu:
mcr p15,0,R0,c7,c7,0 //使I/Dcache失效。
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x00000007
mcr p15,0,r0,c1,c0,0
---------------------------------------------
最后再检查一遍:发现执行完每个bl之后没有返回,所以在每个bl所跳转的程序完成之后,需要加上一个mov pc,lr

免责声明:文章转载自《u-boot核心初始化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇pf4j实例 插件框架c++里面的单冒号和双冒号下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C++ 变量作用域

作用域是程序的一个区域,一般来说有三个地方可以定义变量: 在函数或一个代码块内部声明的变量,称为局部变量。 在函数参数的定义中声明的变量,称为形式参数。 在所有函数外部声明的变量,称为全局变量。 局部变量 在函数或一个代码块内部声明的变量,称为局部变量。它们只能被函数内部或者代码块内部的语句使用。 #include<iostream> us...

Linux设备驱动——内核定时器

内核定时器使用 内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于<Linux/timer.h>和kernel/timer.c文件中。 被调度的函数肯定是异步执行的,它类似于一种“软件中断”,而且是处于非进程的上下文中,所以调度函数必须遵守以下规则: 1)没有current指针、不允许访问用户空...

浅析vue混入(mixin)

  vue中的混入,可以在一定程度上提高代码的复用性。通俗来说,混入类似于“继承”,当前组件对象继承于组件对象,一般情况下遵循“就近原则”。但是与继承不同的是,继承一般都跟随着属性的重写与合并,混入在不同的配置项中,有着不同的混入策略,下面会一一进行介绍vue不同配置项的混入策略。vue混入的基本流程如图所示,混入属性的合并是发生在组件的生命周期钩子调用之...

NGINX----源码阅读一(main函数)

1、ngx_debug_init(); 初始化debug函数,一般为空。 2、ngx_strerror_init(); 将系统错误码+错误信息,以ngx_str_t数组保存。 3、ngx_get_options(int argc, char *const *argv) nginx启动函数选项, 4、ngx_show_version_info(); 如果上一...

Qt中的QGLWidget简介

我对QGLWidget的理解就是,其从QWidget继承,额外实现了一些OpenGl的操作,归纳如下:1、使用QWidget的句柄winID返回的HWND对OpenGl的绘制设备进行初始化,用一个虚函数initializeGL()实现,用户可以重置这个函数。2、使用resizeGL(int width,int height);对GL的视口进行变换。同样是一...

【Vue后台管理二】vue-admin-template 对接后端API JWT认证

初始化对接端台API 上一篇了完成了项目初始化,但是那个只是把 vue-admin-template 模版简单的初始化了一下,新增了tagsview标签快捷导航栏,其他的没什么变化。 这一篇了就完成了和后端的Jwt token认证,登录,退出,基本的table list接口数据请求。首先看看效果。 其实看起来和第一篇的初始化效果差不多,唯一的区别是,第一篇...