免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1147 | 回复: 0
打印 上一主题 下一主题

u boot 第一部分 启动代码 汇编 详解 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-26 16:36 |只看该作者 |倒序浏览

一下是个人在学习uboot 是 阅读时的一点笔记
大多数bootloader都分为stage1和stage2两部分,u-boot也不例外。依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
1、Stage1  start.S代码结构
u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:
(1)定义入口。由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
(2)设置异常向量(Exception Vector)。
(3)设置CPU的速度、时钟频率及终端控制寄存器。
(4)初始化内存控制器。
(5)将ROM中的程序复制到RAM中。
(6)初始化堆栈。
(7)转到RAM中执行,该工作可使用指令ldr pc来完成。
2、Stage2  C语言代码部分
lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作:
(1)调用一系列的初始化函数。
(2)初始化Flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有NAND设备,则初始化NAND设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写IP、MAC地址等。
(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
/*
*  armboot - Startup Code for ARM920 CPU-core
*
*  Copyright (c) 2001 Marius Gr鰃er
mag@sysgo.de
>
*  Copyright (c) 2002 Alex Z黳ke
azu@sysgo.de
>
*  Copyright (c) 2002 Gary Jennejohn
gj@denx.de
>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include
#include
/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/
.globl _start        //入口处 _start
_start: b       reset //异常向量表的定义  跳转到reset 处执行
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort:  .word data_abort
_not_used:  .word not_used
_irq:   .word irq
_fiq:   .word fiq
.balignl 16,0xdeadbeef
/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************
*/
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word _start
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
/*
* the actual reset code
*/
reset:
/*
  * set the cpu to SVC32 mode
  */
mrs r0,cpsr                   //读取cpsr 寄存器的值到r0中
bic r0,r0,#0x1f               //将后5为清0
orr r0,r0,#0xd3               //设置为SVC32模式
msr cpsr,r0                   //将设置好的写回cprs
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON  0x15300000
# define INTMSK  0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(CONFIG_S3C2410)
# define pWTCON  0x53000000
# define INTMSK  0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
/************关闭看门狗***************/
ldr     r0, =pWTCON         
mov     r1, #0x0
str     r1, [r0]
/*
  * mask all IRQs by setting all bits in the INTMR - default
  */
/****************禁止所有中断*******************/
mov r1, #0xffffffff         
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
/*************设置系统频率******************/
ldr r0, =CLKDIVN            
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
/*
  * we do sys-critical inits only at reboot,
  * not when booting from ram!
  */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/*****************************************************************************
*_TEXT_BASE 定义于 board\架构\config.mk 中 根据自己的架构需要改动
******************************************************************************/
relocate:                    //拷贝uboot到RAM
adr r0, _start              //将当前的代码赋值给RO
ldr r1, _TEXT_BASE          //将起始地址赋值给r1
cmp     r0, r1              //比较r0 和 r1 的大小
beq     stack_setup   
/****************************************************************************      *_armboot_start 和 _bss_start 段的 board\架构\u-boot.lds中
*****************************************************************************/                           
ldr r2, _armboot_start    //将armboot 赋值给 r2
ldr r3, _bss_start       //将bss起始地址赋值给r3   
sub r2, r3, r2          //因为bss_start 是armboot 的结束地址 故r2为armboot的大小      
add r2, r0, r2          //指向结束地址、
/************************************************************************/
//循环拷贝数据
copy_loop:
ldmia r0!, {r3-r10}  /* copy from source address [r0]    */
stmia r1!, {r3-r10}  /* copy to   target address [r1]    */
cmp r0, r2   /* until source end addreee [r2]    */
ble copy_loop
/********************************************************/
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
/* Set up the stack          */
stack_setup:
ldr r0, _TEXT_BASE  /* upper 128 KiB: relocated uboot   */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area        */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo          */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12  /* leave 3 words for abort-stack    */
clear_bss:
ldr r0, _bss_start  /* find start of bss segment */
ldr r1, _bss_end  /* stop here  */
mov  r2, #0x00000000  /* clear  */
clbss_l:str r2, [r0]  /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
#if 0
/* try doing this stuff after the relocation */
ldr     r0, =pWTCON
mov     r1, #0x0
str     r1, [r0]
/*
  * mask all IRQs by setting all bits in the INTMR - default
  */
mov r1, #0xffffffff
ldr r0, =INTMR
str r1, [r0]
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
/* END stuff after relocation */
#endif
ldr pc, _start_armboot
_start_armboot: .word start_armboot
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/************cpu初始化*****************/
cpu_init_crit:
/*
  * flush v4 I/D caches
  */
/***********关键寄存器初始化**************/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
  * disable MMU stuff and caches
  */
/***************禁止MMU和cache**********************/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
/*
  * before relocating, we have to setup RAM timing
  * because memory timing is board-dependend, you will
  * find a lowlevel_init.S in your board directory.
  */
mov ip, lr
bl lowlevel_init
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR  64
#define S_PC  60
#define S_LR  56
#define S_SP  52
#define S_IP  48
#define S_FP  44
#define S_R10  40
#define S_R9  36
#define S_R8  32
#define S_R7  28
#define S_R6  24
#define S_R5  20
#define S_R4  16
#define S_R3  12
#define S_R2  8
#define S_R1  4
#define S_R0  0
#define MODE_SVC 0x13
#define I_BIT  0x80
/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/
.macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12}   @ Calling r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
ldmia r2, {r2 - r3}   @ get pc, cpsr
add r0, sp, #S_FRAME_SIZE  @ restore sp_SVC
add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3}   @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp
.endm
.macro irq_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12}   @ Calling r0-r12
add     r8, sp, #S_PC
stmdb   r8, {sp, lr}^                   @ Calling SP, LR
str     lr, [r8, #0]                    @ Save calling PC
mrs     r6, spsr
str     r6, [r8, #4]                    @ Save CPSR
str     r0, [r8, #8]                    @ Save OLD_R0
mov r0, sp
.endm
.macro irq_restore_user_regs
ldmia sp, {r0 - lr}^   @ Calling r0 - lr
mov r0, r0
ldr lr, [sp, #S_PC]   @ Get PC
add sp, sp, #S_FRAME_SIZE
subs pc, lr, #4   @ return & move spsr_svc into cpsr
.endm
.macro get_bad_stack
ldr r13, _armboot_start  @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
str lr, [r13]   @ save caller lr / spsr
mrs lr, spsr
str     lr, [r13, #4]
mov r13, #MODE_SVC   @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13
mov lr, pc
movs pc, lr
.endm
.macro get_irq_stack   @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm
.macro get_fiq_stack   @ setup FIQ stack
ldr sp, FIQ_STACK_START
.endm
/*
* exception handlers
*/
.align  5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl  do_undefined_instruction
.align 5
software_interrupt:
get_bad_stack
bad_save_user_regs
bl  do_software_interrupt
.align 5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl  do_prefetch_abort
.align 5
data_abort:
get_bad_stack
bad_save_user_regs
bl  do_data_abort
.align 5
not_used:
get_bad_stack
bad_save_user_regs
bl  do_not_used
#ifdef CONFIG_USE_IRQ
.align 5
irq:
get_irq_stack
irq_save_user_regs
bl  do_irq
irq_restore_user_regs
.align 5
fiq:
get_fiq_stack
/* someone ought to write a more effiction fiq_save_user_regs */
irq_save_user_regs
bl  do_fiq
irq_restore_user_regs
#else
.align 5
irq:
get_bad_stack
bad_save_user_regs
bl  do_irq
.align 5
fiq:
get_bad_stack
bad_save_user_regs
bl  do_fiq
#endif


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/78572/showart_1945448.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP