Chinaunix首页 | 论坛 | 博客
  • 博客访问: 77653
  • 博文数量: 28
  • 博客积分: 1415
  • 博客等级: 上尉
  • 技术积分: 351
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-15 13:18
个人简介

I bet you dont want to know.

文章分类

全部博文(28)

分类: LINUX

2008-08-01 23:34:42

CPU相关的代码部分:
 本系统使用的是PXA处理器,PXA处理器为一个系列,Uboot中使用的是PXA25X的处理器,由于新的开发板使用的是PXA270处理器,与PXA25X处理器不太相同,这里我们就要根据自己的处理器更改相应的start.S文件的代码,给文件位于cpu/pxa目录中。
// _start为当前的地址
.globl _start
_start: b 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 RAM!
 * - relocate armboot to ram
 * - setup stack
 * - jump to second stage
 */
// TEXT_BASE在开发板相关的目录中的config.mk文件中定义, 它定义了
// 代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地址
_TEXT_BASE:
 .word TEXT_BASE
// 见下面_bss_start的说明
.globl _armboot_start
_armboot_start:
 .word _start
/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
// _bss_start保存的是__bss_start这个标号所在的地址, 这里涉及到当前代码所在
// 的地址不是编译时的地址的情况, 这里直接取得该标号对应的地址, 不受编译时
// 地址的影响. _bss_end也是同样的道理.
_bss_start:
 .word __bss_start
.globl _bss_end
_bss_end:
 .word _end
// 系统中不使用IRQ, 故下面的代码不用关心.
#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          */
/*             */
/*********************************************************************/
// 这里是CPU启动后执行的第一条指令.
reset:
 // 设置CPU进入管理模式
 mrs r0,cpsr   /* set the cpu to SVC32 mode     */
 bic r0,r0,#0x1f  /* (superviser mode, M=10011)     */
 orr r0,r0,#0x13
 msr cpsr,r0
 /*
  * we do sys-critical inits only at reboot,
  * not when booting from ram!
  */
// 重新启动时是否进行初始化, 这个宏要定义在用户的目标板配置头文件中
// 一般情况下是需要的, 不过, 在移植到其它开发板时可就要注意了!!
// 在我们的系统中定义了这个宏, 同时我们也是靠这个函数实现了硬件
// 相关的代码的初始化.
#ifdef CONFIG_INIT_CRITICAL
 bl cpu_init_crit  /* we do sys-critical inits     */
#endif
 
// 进行重新定位, 原来在flash中, 现在要拷贝到ram中去运行. .
// _start为当前代码的起始地址
// TEXT_BASE为要拷贝到的ram地址, 定义在board/xxx/config.mk文件中
relocate:     /* relocate U-Boot to RAM     */
 adr r0, _start   /* r0 <- current position of code   */
 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */
 cmp     r0, r1          /* don't reloc during debug         */
 
 // 如果代码就在当前位置, 那么就不用拷贝了, 跳转过去对堆栈进行初始化
 beq     stack_setup  
 
 // 如果说不相等, 就要执行下面的代码进行数据大搬迁.
 ldr r2, _armboot_start // 得到编译时_start的运行时地址, 其实就是TEXT_BASE ldr r3, _bss_start  // 代码中的bss段起始地址,编译时定下来的运行地址!
 // 他们之间的差值就是代码段数据长度.
 sub r2, r3, r2   /* r2 <- size of armboot            */
 add r2, r0, r2   /* r2 <- source end address         */
 
 // 到这里, 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
 
 // 接下来设置堆栈, 这里需要注意的是堆栈在代码段的下方, 不是上方!!
 // 宏CFG_MALLOC_LEN和CFG_GBL_DATA_SIZE在目标板的头文件中定义.
 /* 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                        */
 
 // 这里如果需要使用IRQ, 还有给IRQ保留堆栈空间, 一般不使用.
#ifdef CONFIG_USE_IRQ
 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
 sub sp, r0, #12  /* leave 3 words for abort-stack    */
 
 // 下面用于清除bss段数据, 这个本来就应当为0, 现在没有C库的支持
 // 只好手动清除了.
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
 bne clbss_l
 ldr pc, _start_armboot  // 直接加载绝对地址, 不能使用b指令
// _start_armboot的值就是start_armboot函数运行时对应的地址, 因为代码已经进行了
// 重新定位, 执行自然不会有问题了.
_start_armboot: .word start_armboot
// 下面就是关键的初始化函数的实现.
cpu_init_crit:
 /* mask all IRQs          */
 ldr r0, IC_BASE
 mov r1, #0x00
 str r1, [r0, #ICMR]
// 我们没有在这个函数中实现太多的东西, 这个本身就是CPU相关的代码,
// 这里跳转到board/xxx/memsetup.S中去执行, 在这个文件中实现了所有的
// 开发板相关的代码的初始化.
 mov ip, lr
 bl memsetup
 mov lr, ip
 
(本文章发表于psbec的个人blog,未经本人许可,不得用于商业用途。任何个人、媒体、其他网站不得私自抄袭;网络媒体转载请注明出处,增加原文链接,否则属于侵权行为。如有任何问题,请留言或者发邮件给psbec,地址)
 
阅读(1037) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~