您的位置:首页 > 其它

s3c2440开发日记,u-boot启动过程,Nand Flash启动分析irq_handler, 中断响应过程,

2010-08-15 00:52 441 查看
3.u-boot启动过程,2010-08-15

(1)0x0开始的地方为 "cpu/arm920t/start.S" 文件,启动进入 reset,此段代码位于前4K里自动

被加载到内部的4K内存里面,在reset里把u-boot从Nand Flash复制到64M的SDRAM里面。

(2)复制完后跳到lib_arm/board.c的start_armboot函数,在这里初始化内存和网络连接,中断后

进入一个 for(;;) {}的无限循环,在此循环里面不断执行位于 common/main.c 里面的main_boot()函数。

(3)执行common/main.c的main_boot()函数,初始化LCD等之后,开始加载启动linux内核,或者wince,

或进入u-boot功能菜单,或进入u-boot的命令行,根据用户具体配置。

2.测试代码从Nand Flash启动,分析,2010-08-14

从Nand Flash启动,先是ARM电路读取NandFlash里面的前4KB数据到内部SRAM中,此4K SRAM被映射到

从0x0开始的地址,CUP就从0x0开始执行代码,此4KB代码必须完成把要执行的数据从NandFlash中全部复制到

SDRAM(64M)中,完在复制后跳到SDRAM中的程序入口,开始执行。

把原来测试代码中的把数据从NandFlash复制到SDRAM中的那一小段代码注析掉后,再把改过的测试程序

编译后通过u-boot写入到NandFlash中,设为从NandFlash启动,再按reset按钮,还是可以正常启动测试代码,

想想觉得挺纳闷,不是要必须得把代码从NandFlash复制到SDRAM中后还可以正常执行吗,怎么现在把复制代码

的那一段去掉后还可以正常执行?纳闷了,后不按reset而是直接关掉电源,再开启(从NandFlash启动),

好了,这会动不了了,屏幕白色的亮着,终端里面什么信息也没有输出,启动不成功了。

但是原来为什么是可以的呢,写入到NandFlash里面后再按reset是可以启动的,原来通过u-boot把测试

程序写入NandFlash时是这样的,先把要写入的测试程序全部加载到SDRAM中,从0x30000000开始,

一直向后填充要下载的测试程序,再把数据从SDRAM全部写入到NandFlash里面去后,这样测试程序是存在于SDRAM里

面的,且从0x30000000开始,这时按reset那SDRAM还是带电里面内容还是存在没变的,那么reset后,即使前4K没

有执行把数据从NandFlash复制到SDRAM中去的动作,但要执行的测试数据还是存在于SDRAM中的,前4K代码执行一

会后直接跳过去到SDRAM中去,刚好就跳过去,执行了。

用axd等调试的话就会很容易发现问题了,但也不一定,跳过去有内容还不晓得是从哪里来的。

==============================================================================================

1.irq_handler, 中断响应过程, 2010-08-13

当来了一个中断后,

(1).pc被设置到 "b HandlerIRQ" 这里

(2).从这里跳转到 HandlerIRQ, HandlerIRQ是由宏$HandlerLabel HANDLER $HandleLabel扩展得来。

进入HandlerIRQ后再跳转到$HandleLabel,$HandleLabel原先由Setup IRQ handler的一小段代码设置到指向IsrIRQ这里了

(3).所以会从HandlerIRQ跳转到IsrIRQ执行,IsrIRQ根据中断的类别得到中断偏移量INTOFFSET,用这个偏移量加

上中断向量表的开始地址,计算得到中断服务程序的地址。

(4).再跳到这个中断服务程序来开始执行相应中断的服务程序。

如下:

(1)

b HandlerIRQ ;handler for IRQ interrupt

(2)

-----------------------------------------------------

HandlerIRQ HANDLER HandleIRQ

-------------------------

MACRO

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

sub sp,sp,#4 ;decrement sp(to store jump address)

stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)

ldr r0,=$HandleLabel;load the address of HandleXXX to r0

ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX

str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack

ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)

MEND

-------------------------

HandlerIRQ

sub sp,sp,#4 ;decrement sp(to store jump address)

stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)

ldr r0,=HandleIRQ ;load the address of HandleIRQto r0

ldr r0,[r0] ;load the contents(service routine start address) of HandleIRQ

str r0,[sp,#4] ;store the contents(ISR) of HandleIRQ to stack

ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)

MEND

(3)

-----------------------------------------------------

; Setup IRQ handler

ldr r0,=HandleIRQ ;This routine is needed

ldr r1,=IsrIRQ ;if there is not 'subs pc,lr,#4' at 0x18, 0x1c

str r1,[r0] ;now HandleIRQ point to IsrIRQ

-------------------------

IsrIRQ

sub sp,sp,#4 ; reserved for PC

stmfd sp!,{r8-r9}

ldr r9,=INTOFFSET

ldr r9,[r9]

ldr r8,=HandleEINT0

add r8,r8,r9,lsl #2

ldr r8,[r8] ; pointer to int server prg address

str r8,[sp,#8]

ldmfd sp!,{r8-r9,pc} ; jump to such as: pISR_ADC -> (int)AdcTsAuto;

-----------------------------------------------------

(4)

上面IsrIRQ的 "ldmfd sp!,{r8-r9,pc}"会把相应的中断服务程序地址存到pc里面,这样

就跳到相应的中断服务地址了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: