U-boot源代码全分析系列(基于PowerPC)-2

来源:互联网 发布:车流量查询软件 编辑:程序博客网 时间:2024/05/05 10:53
3、初始化CPU相关

    下面为初始化CPU的代码,实现的功能依次为屏蔽watchdog、初始化中断控制寄存器、清空Cache、关闭MMU等。

.globlinit_e300_coreinit_e300_core: /* time t 10 *//* Initialize machine status; enable machine check interrupt */lir3, MSR_KERNEL/*设置MSR,允许数据\指令复制以及Machine check*/rlwimir3, r5, 0, 25, 25/* preserve IP bit set by HRCW */#ifdef DEBUGrlwimir3, r5, 0, 21, 22   /* debugger might set SE & BE bits */#endifSYNC/* Some chip revs need this... */mtmsrr3SYNCmtsprSRR1, r3/* Make SRR1 match MSR 中断相关*/lisr3, CFG_IMMR@h#if defined(CONFIG_WATCHDOG)/* Initialise the Wathcdog values and reset it (if req) */lis r4, CFG_WATCHDOG_VALUEori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)stw r4, SWCRR(r3)/* and reset it */lir4, 0x556Csthr4, SWSRR@l(r3)lir4, -0x55C7sthr4, SWSRR@l(r3)#else/* 关闭Wathcdog  */lwz r4, SWCRR(r3)/* Check to see if its enabled for disabling   once disabled by SW you can't re-enable */andi. r4, r4, 0x4beq 1fxor r4, r4, r4stw r4, SWCRR(r3)1:#endif /* CONFIG_WATCHDOG *//* Initialize the Hardware Implementation-dependent Registers *//* HID0 also contains cache control*//*------------------------------------------------------*/lisr3, CFG_HID0_INIT@horir3, r3, CFG_HID0_INIT@lSYNCmtsprHID0, r3lisr3, CFG_HID0_FINAL@horir3, r3, CFG_HID0_FINAL@lSYNCmtsprHID0, r3lisr3, CFG_HID2@horir3, r3, CFG_HID2@lSYNCmtsprHID2, r3/* 关闭MMU功能,先清空所有BAT (块地址转换)*/xorr0, r0, r0mtsprDBAT0U, r0mtsprDBAT0L, r0mtsprDBAT1U, r0mtsprDBAT1L, r0mtsprDBAT2U, r0mtsprDBAT2L, r0mtsprDBAT3U, r0mtsprDBAT3L, r0mtsprIBAT0U, r0mtsprIBAT0L, r0mtsprIBAT1U, r0mtsprIBAT1L, r0mtsprIBAT2U, r0mtsprIBAT2L, r0mtsprIBAT3U, r0mtsprIBAT3L, r0SYNC/* 禁用tlb(快表) */lir3, 32mtctrr3lir3, 01:tlbier3addir3, r3, 0x1000bdnz1bSYNC/* Done! */Blr

    这里需要注意的是,当程序在Flash中运行时,执行程序跳转时使用了跳转指令,但是不是使用绝对地址的跳转(即直接对PC操作)。因为若使用绝对地址,那么程序的取址就是相对于当前PC位置向前或向后的一段空间,而不会跳进SDRAM中。

4、初始化内存控制器

    PowerPC处理器初识化内存控制器就是通过操作BAT以及TLB来实现的,将IBAT0~7以及DBAT0~7初始化,并禁用TLB,代码如下:

/* setup_bats - set them up to some initial state */.globlsetup_batssetup_bats:addisr0, r0, 0x0000/* IBAT 0 */addisr4, r0, CFG_IBAT0L@horir4, r4, CFG_IBAT0L@laddisr3, r0, CFG_IBAT0U@horir3, r3, CFG_IBAT0U@lmtsprIBAT0L, r4mtsprIBAT0U, r3isync/* DBAT 0 */addisr4, r0, CFG_DBAT0L@horir4, r4, CFG_DBAT0L@laddisr3, r0, CFG_DBAT0U@horir3, r3, CFG_DBAT0U@lmtsprDBAT0L, r4mtsprDBAT0U, r3isync#ifdef CONFIG_HIGH_BATS/* IBAT 4 */addis   r4, r0, CFG_IBAT4L@hori     r4, r4, CFG_IBAT4L@laddis   r3, r0, CFG_IBAT4U@hori     r3, r3, CFG_IBAT4U@lmtspr   IBAT4L, r4mtspr   IBAT4U, r3isync/* DBAT 4 */addis   r4, r0, CFG_DBAT4L@hori     r4, r4, CFG_DBAT4L@laddis   r3, r0, CFG_DBAT4U@hori     r3, r3, CFG_DBAT4U@lmtspr   DBAT4L, r4mtspr   DBAT4U, r3isync#endif/* Invalidate TLBs. * -> for (val = 0; val < 0x20000; val+=0x1000) * ->   tlbie(val); */lisr3, 0lisr5, 21:tlbier3addir3, r3, 0x1000cmp0, 0, r3, r5blt1bblr

上面只贴出了高低位各一个BAT的操作代码,其他的类似。

5、复制程序到RAM

    PowerPC中此段程序并不返回,在将程序代码全部复制到ROM中后,将会直接继续在RAM中运行:

/*完成了代码复制,不返回,直接调用in_ram执行*/addir0, r10, in_ram - _start + EXC_OFF_SYS_RESETmtlrr0blr.globlrelocate_coderelocate_code:mrr1,  r3/* 创建一个新的栈指针 */mrr9,  r4/* 备份 */mrr10, r5mrr3,  r5/* r3:拷贝的终点 */lisr4, CFG_MONITOR_BASE@h/* r4:拷贝的起点 */orir4, r4, CFG_MONITOR_BASE@llwzr5, GOT(__init_end)subr5, r5, r4                      /* r5:拷贝的长度 */lir6, CFG_CACHELINE_SIZE/* Cache Line Size *//* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address */subr15, r10, r4/* First our own GOT */addr14, r14, r15/* then the one used by the C code */addr30, r30, r15/* Now relocate code */cmplwcr1,r3,r4addir0,r5,3srwi.r0,r0,2beqcr1,4f/* In place copy is not necessary */beq7f/* Protect against 0 count  */mtctrr0bgecr1,2flar8,-4(r4)lar7,-4(r3)/* copy */1:lwzur0,4(r8)stwur0,4(r7)bdnz1baddir0,r5,3srwi.r0,r0,2mtctrr0lar8,-4(r4)lar7,-4(r3)/* and compare */20:lwzur20,4(r8)lwzur21,4(r7)xor. r22, r20, r21bne  30fbdnz20bb 4f/* compare failed */30:li r3, 0blr2:slwir0,r0,2 /* re copy in reverse order ... y do we needed it? */addr8,r4,r0addr7,r3,r03:lwzur0,-4(r8)stwur0,-4(r7)bdnz3b/* * Now flush the cache: note that we must start from a cache aligned * address. Otherwise we might miss one cache line. */4:cmpwir6,0addr5,r3,r5beq7f/* Always flush prefetch queue in any case */subir0,r6,1andcr3,r3,r0mrr4,r35:dcbst0,r4addr4,r4,r6cmplwr4,r5blt5bsync/* Wait for all dcbst to complete on bus */mrr4,r36:icbi0,r4addr4,r4,r6cmplwr4,r5blt6b7:sync/* Wait for all icbi to complete on bus*/isync

6、初始化堆栈

    对于mpc83xx系列,初始化堆栈代码如下:

/* set up the stack pointer in our newly created cache-ram (r1) */lisr1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@horir1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@llir0, 0/* Make room for stack frame header and*/stwur0, -4(r1)/* clear final stack frame so that*/stwur0, -4(r1)/* stack backtraces terminate cleanly*/

7、跳转到Stage2入口处

    这也是Stage1的最后一步,程序在执行到这一步后,基本的硬件初始化工作也就完成了,下面是跳转的代码:

GET_GOT/* initialize GOT access*//* r3: IMMR */lisr3, CFG_IMMR@h/* run low-level CPU init code (in Flash)*/blcpu_init_f/* r3: BOOTFLAG */mrr3, r21/* run 1st part of board init code (in Flash)*/blboard_init_f

其中board_init_f就是Stage2的函数入口。

    由上可以看出start.S的流程为:异常向量——上电复位后进入复位异常向量——跳到启动代码处——设置处理器进入管理模式——关闭看门狗——关闭中断——设置时钟分频——关闭MMU和CACHE——进入lowlever_init.S——检查当前代码所处的位置,如果在FLASH中就将代码搬移到RAM中。至此,Stage1分析到此结束。

    跳转到board_init_f后,程序开始执行Stage2阶段,代码多为C。