用户:
顺铂查看:0 回复:4 评论:0 创建时间:2018-12-15T13:52:15
上次,我们发布了安卓的启动过程,不是很好。希望zhei次能有个全新的开始~
话不多说,开始讲解~
《深入android启动》分为以下几个部分:
1、上电自检及uboot---美好的开端
2、Linux内核---风华正茂
3、init进程与init.rc---纠缠不清的关系
4、deamon守护代理进程
5、zytoge---星星之火
6、System Services
7、从activitymanager到homeactivity---使命完成
先贴张jpg

本次先讲解下uboot吧

当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。
uboot运行有两个阶段,一个阶段是运行在SRAM中的汇编阶段,另一个是运行在DDR中的C语言阶段。
与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段。BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言来实现;BL2阶段主要是对外部设备如网卡、Flash等的初始化以及uboot命令集等的自身实现,通常用C语言来实现。
1、BL1阶段uboot的BL1阶段代码通常放在start.s文件中,用汇编语言实现,其主要代码功能如下:
(1) 指定uboot的入口。在链接脚本uboot.lds中指定uboot的入口为start.S中的_start。
(2)设置异常向量(exception vector)
(3)关闭IRQ、FIQ,设置SVC模式
(4)关闭L1 cache、设置L2 cache、关闭MMU
(5)根据OM引脚确定启动方式
(6)在SoC内部SRAM中设置栈
(7)lowlevel_init(主要初始化系统时钟、SDRAM初始化、串口初始化等)
(8)设置开发板供电锁存
(9)设置SDRAM中的栈
(10)将uboot从SD卡拷贝到SDRAM中
(11)设置并开启MMU
(12)通过对SDRAM整体使用规划,在SDRAM中合适的地方设置栈
(13)清除bss段,远跳转到start_armboot执行,BL1阶段执行完
2、 BL2阶段start_armboot函数位于lib_arm/board.c中,是C语言开始的函数,也是BL2阶段代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,BL2阶段的主要功能如下:
(1)规划uboot的内存使用
(2)遍历调用函数指针数组init_sequence中的初始化函数
(3)初始化uboot的堆管理器mem_malloc_init
(4)初始化SMDKV210开发板的SD/MMC控制器mmc_initialize
(5)环境变量重定位env_relocate
(6)、将环境变量中网卡地址赋值给全局变量的开发板变量
(7)、开发板硬件设备的初始化devices_init
(8)、跳转表jumptable_init
(9)、控制台初始化console_init_r
(10)、网卡芯片初始化eth_initialize
(11)、uboot进入主循环main_loop
二、uboot程序入口分析 1、 link.lds链接脚本文件分析u-boot.lds文件是uboot工程的链接脚本文件,位于board\samsung\喵dkc110目录下,对于工程项目编译后期的链接阶段非常重要,决定了uboot程序的组装。
u-boot.lds链接文件中的ENTRY(_start)指定了uboot程序的入口地址为_start。
2、定位uboot程序入口地址在SourceInsight建立uboot工程,利用索引功能查找_start,在搜索结果中找到与三星喵dkv210开发板相关的代码,最终锁定cpu\s5pc11x\start.S文件,定位到文件中的_start标识符。
第一阶段;
#include @该文件是第二步中mkconfig文件执行时创建的。include/config.h
#include
#include @在include目录下。
/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/
@这是一个异常跳转表,
.globl _start
_start:
b start_code @start_code才是真正的启动代码
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 @在标号_undefined_instruction处存储了一个变量,该变量也是一个标号地址
_software_interrupt: .word software_interrupt @执行上面的ldr pc, _undefined_instruction;指令会将变量undefined_instruction的值装入PC
_prefetch_abort: .word prefetch_abort @pc指向一个地址,喵U从该地址中取指执行
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
.balignl 16,0xdeadbeef
/*
*************************************************************************
*
* Startup Code (called from the ARM reset exception 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 @变量TEXT_BASE由连接脚本指定,
.globl _armboot_start
_armboot_start:
.word _start @_start是在起始代码处定义的标号,当跳到_armboot_start后还是会跳转到_start
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start @这是board/mini2440/u-boot.lds脚本中的变量,
.globl _bss_end
_bss_end:
.word _end @这也是board/mini2440/u-boot.lds脚本中的变量,
#ifdef CONFIG_USE_IRQ @这个宏在include/configs/$(board_name).h中定义。可以取消
/* 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 start code
*/
start_code: @这是真正的启动代码
/* set the cpu to SVC32 mode*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
bl coloured_LED_init @这个函数在status_led.h中被提升了作用域,但是在哪里面实现??status_led.h文件
bl red_LED_on @同上
@下面这些宏开关也是在include/configs/$(board_name).h中定义??
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
/*
* relocate exception table
*/
ldr r0, =_start
ldr r1, =0x0
mov r2, #16
copyex:
subs r2, r2, #1
ldr r3, [r0], #4
str r3, [r1], #4
bne copyex
#endif
@下面这些宏开关是在include/configs/$(board_name).h中定义
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
/* turn off the watchdog */
# if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define IN喵SK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else
# define pWTCON 0x53000000
# define IN喵SK 0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
# endif
#define CLK_CTL_BASE 0x4c000000
#define MDIV_405 0x7f<<12
#define PSDIV_405 0x21
#define UPLL_MDIV_48 0x38<<12
#define UPLL_PSDIV_48 0x22
#define MDIV_200 0xa1<<12
#define PSDIV_200 0x31
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
/*
* mask all IRQs by setting all bits in the IN喵R - default
*/
mov r1, #0xffffffff
ldr r0, =IN喵SK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
/*add by gray*/
#if defined(CONFIG_S3C2440)
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
#endif
/*add by gray,这里是修改后的,其实可以在uboot启动的第二阶段start_armboot()函数里调用board_init()函数时重置喵U钟
对于S3C2440,MPLL(clk)=(2 * m * Fin) / p * 2^s,
m = MDIV + 8, p = PDIV + 2, s = SDIV.
这里MDIV = 0x7f, PDIV = 0x2 ,SDIV = 0x1
*/
#if defined(CONFIG_S3C2440)
/*FCLK:HCLK:PCLK=1:2:4*/
ldr r0, =CLKDIVN
mov r1, #5
str r1,[r0]
mrc p15,0,r1,c1,c0,0 /*read ctrl reg*/
orr r1,r1,#0xc0000000 /*ASYN*/
mcr p15,0,r1,c1,c0,0 /*write ctrl reg*/
mov r1,#CLK_CTL_BASE
mov r2,#UPLL_MDIV_48
add r2, r2,#UPLL_PSDIV_48
str r2,[r1,#0x08] /*write UPLL first,48MHZ*/
mov r2,#MDIV_405
add r2,r2,#PSDIV_405 /*mpll_405MHZ*/
str r2,[r1,#0x04] /*MPLLCON*/
#else
/*F:H:P=1:2:4*/
ldr r0, =CLKDIVN
mov r1, #3
str r1,[r0]
mrc p15,0,r1,c1,c0,0 /*read ctrl reg*/
orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0
mov r1,#CLK_CTL_BASE
mov r2,#MDIV_200
add r2,r2,#PSDIV_200 /*mpll_200MHZ*/
str r2,[r1,#0x04] /*MPLLCON*/
#endif
#endif /*CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440*/
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit @如果没有定义CONFIG_SKIP_LOWLEVEL_INIT,就进行严格的初始化,调用lowlevel_init函数
#endif
#ifndef CONFIG_AT91RM9200 @AT91RM9200评估板,基于ARM920T内核
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/* relocate U-Boot to RAM */
relocate:
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 /*如果_start与_TEXT_BASE相等,就直接跳去stack_setup进行栈的设置, 否则就要进行代码的拷贝,把代码拷贝到内存中*/
ldr r2, _armboot_start
ldr r3, _bss_start @计算代码段大小=_bss_start-_armboot_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
@ r2 = _start的地址+代码段大小
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 */
#endif
/* 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 @如果定义了IRQ,就要为IRQ,FIQ分配中断栈。
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
clear_bss: @清除bss段,_bss_start 和_bss_end就是u-boot.lds脚本传入的变量
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
ldr pc, _start_armboot
_start_armboot: .word start_armboot @跳到start_armboot()函数执行,进入uboot的第二阶段
/*
*************************************************************************
*
* 喵U_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit: @进行严格的初始化,关闭I/D caches,MMU,
/*
* 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
*/
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
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
#else
bl lowlevel_init @这个函数是重点。。在lowlevel_init.S中
#endif
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
lowlevel_init.S的内容:
_TEXT_BASE:
.word TEXT_BASE
.globl lowlevel_init
lowlevel_init: @很明显,是初始化SDRAM
/* memory control configuration */
/* make r0 relative the current location so that it */
/* reads SMRDATA out of FLASH rather than memory ! */
ldr r0, =SMRDATA
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b
/* everything is fine now */
mov pc, lr
.ltorg start.S有四个头文件:
#include <config.h>
config.h头文件在配置开发板时由mkconfig脚本创建的头文件,头文件内容即包含开发板的头文件:#include <configs/喵dkv210single.h>
#include <version.h>
version.h头文件的内容为包含自动生成的版本头文件,头文件内容为:#include "version_autogenerated.h",version_autogenerated.h头文件定义了版本宏,宏定义为:#define U_BOOT_VERSION "U-Boot 1.3.4"。版本宏的值就是Makefile中定义的版本信息。
#include <a喵/proc/domain.h>
domain.h头文件在定义了CONFIG_ENABLE_MMU宏时有效,为链接文件,实际指向的文件为include/a喵-arm/proc-armv/domain.h。
#include <regs.h>
regs.h头文件为链接文件,指向s5pc110.h头文件,s5pc110.h文件内部使用宏定义了有关SoC内部寄存器的大量信息。
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
定义uboot程序开头的16字节校验头信息填充空间,头校验信息块内的值需要在后面写入。
3、异常向量表的构建.globl _start
_start:
b reset
ldrpc, _undefined_instruction
ldrpc, _software_interrupt
ldrpc, _prefetch_abort
ldrpc, _data_abort
ldrpc, _not_used
ldrpc, _irq
ldrpc, _fiq
uboot程序的入口点实际是定义了异常向量表,异常向量表由SoC硬件实现,因此uboot在开机上电复位时需要跳转到reset执行。
4、复位reset分析SoC上电复位后运行的第一段代码就是reset。主要包括以下几部分:
A、关闭IRQ、FIQ,并将处理器模式设置为SVC模式
B、喵U关键寄存器的初始化cpu_init_crit:
关闭L2 cache
初始化L2 cache
开启L2 cache
关闭L1 cache
关闭MMU
读取OM启动引脚信息
确定从启动设备SD卡启动
设置SRAM中的栈为调用lowlevel_init做准备(lowlevel_init内部有嵌套调用)
调用lowlevel_init(主要初始化系统时钟、SDRAM初始化、串口初始化等)
设置开发板供电锁存
设置SDRAM中的栈
判断当前代码是否运行在SDRAM中,如果当前代码运行在SDRAM中,则跳过代码重定位。
判断启动方式,选择SD卡启动设备,跳转到mmcsd_boot
SD卡启动的准备工作,从SD卡拷贝uboot到SDRAM:movi_bl2_copy
C、设置MMU,开启MMU
D、通过对SDRAM整体使用规划,在SDRAM中合适的地方设置栈
E、清除bss段,远跳转到start_armboot执行,BL1阶段执行完
5、lowlevel_init分析lowlevel_init位于\board\samsung\喵dkc110\lowlevel_init.S中,主要功能如下:
A、检查复位状态,判断启动的方式
根据复位状态选择复位启动的方式,处于低功耗状态时复位启动可以跳过后续多个步骤。
B、IO状态恢复
C、关闭看门狗
D、外部SRAM的GPIO初始化、外部SROM初始化
E、开发板供电锁存设置
F、判断当前代码是否运行在SDRAM,如果当前代码运行在SDRAM,说明目前从低功耗状态复位,可以跳过系统时钟初始化、串口初始化、SDRAM初始化等
G、初始化系统时钟:system_clock_init
H、初始化SDRAM内存:mem_ctrl_a喵_init
I、初始化串口,打印出’O’:uart_a喵_init
J、初始化trustzone:tzpc_init
K、初始化nand或onenand
L、检查复位状态
M、关闭ABB
N、串口打印出‘K’
说明:”OK”是打印出的调试信息,如果打印出’O’则说明在串口初始化uart_a喵_init前的所有代码是正确的。如果打印出”OK”则说明在开发板板级初始化lowlevel_init前的所有代码是正常工作的。
system_clock_init、uart_a喵_init、tzpc_init、nand_a喵_init都位于lowlevel_init.S文件内,mem_ctrl_a喵_init位于cpu\s5pc11x\s5pc110\cpu_init.S文件中。
start_armboot()在board.c中,处于lib_arm/下,在进入lib_arm目录下编译LIBS目标时依赖board.o文件
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
#if !defined(CFG_NO_FLASH) || defined (CONFIG_VFD) || defined(CONFIG_LCD)
ulong size;
#endif
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif
//gd是个寄存器变量,ARM平台对应R8寄存器
/* Pointer is writable since we allocated a register for it
*_armboot_start是代码的起始地址,链接脚本指定为0x33f80000,CFG_MALLOC_LEN=192k,
*所以gd的起始地址=0x33F50000
*/
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
/* compiler optimization barrier needed for GCC >= 3.4 */
__a喵__ __volatile__("": : :"memory");
memset ((void*)gd, 0, sizeof (gd_t));//清空gd_t结构体
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));//bd_t结构体
memset (gd->bd, 0, sizeof (bd_t));
gd->flags |= GD_FLG_RELOC;
monitor_flash_len = _bss_start - _armboot_start;//uboot代码的长度
//对结构体init_fnc_t *init_sequence[]数组中的函数指针挨个调用。
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
/* 初始化flash*/
size = flash_init ();
。。。。。。
/* 初始化一个堆空间 */
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
nand_init(); /* go init the NAND */
/* 初始化环境变量,将环境参数读入内存指定位置 */
env_relocate ();
/* must do this after the framebuffer is allocated,串口初始化 */
serial_initialize();
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address,省略 */
devices_init (); /* get the devices list going. */
jumptable_init (); /* 跳转表初始化 */
console_init_r (); /* fully init console as a device */
/* 使能异常中断 */
enable_interrupts ();
/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_CS8900
cs8900_get_enetaddr (gd->bd->bi_enetaddr);
#endif
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
/* NOTREACHED - no way out of command loop except booting */
}
init_fnc_t *init_sequence[] = {
cpu_init, /* 基本的处理器相关配置,初始化IRQ/FIQ模式的栈 -- cpu/arm920t/cpu.c */
board_init, /* 基本的板级相关配置,设置系统时钟等 -- board/喵dk2410/喵dk2410.c */
interrupt_init, /* 初始化定时器处理 -- cpu/arm920t/s3c24x0/interrupt.c */
env_init, /* 初始化环境变量,检查Flash上的环境参数是否有效 -- common/env_flash.c */
init_baudrate, /* 初始化波特率设置 -- lib_arm/board.c */
serial_init, /* 串口通讯设置 -- cpu/arm920t/s3c24x0/serial.c */
console_init_f, /* 控制台初始化阶段1 -- common/console.c */
display_banner, /* 打印u-boot信息 -- lib_arm/board.c */
dram_init, /* 配置可用的RAM,检测系统内存映射 -- board/喵dk2410/喵dk2410.c */
display_dram_config, /* 显示RAM的配置大小 -- lib_arm/board.c */
NULL,
};
下面逐个分析初始化函数:
1.int cpu_init (void)
{
/* setup up stacks if necessary */
#ifdef CONFIG_USE_IRQ
IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif
return 0;
}
2.int board_init (void)//设置系统时钟,配置引脚,使能缓存
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
......
/* configure UPLL */
clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
......
/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* address of boot parameters */
gd->bd->bi_boot_params = 0x30000100;//为什么是这个地址
icache_enable();//下面这两个函数都是设置协处理器的相关寄存器,使能缓存
dcache_enable();
}
3.int interrupt_init (void) //初始化2410的PWM timer 4,使其能自动装载计数值,
//恒定的产生时间中断信号,但是中断被屏蔽了用不上。
{
S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
/* use PWM Timer 4 because it has no output */
/* prescaler for Timer 4 is 16 */
timers->TCFG0 = 0x0f00;
if (timer_load_val == 0)
{
/*
* for 10 ms clock period @ PCLK with 4 bit divider = 1/2
* (default) and prescaler = 16. Should be 10390
* @33.25MHz and 15625 @ 50 MHz
*/
timer_load_val = get_PCLK()/(2 * 16 * 100);
}
/* load value for 10 ms timeout */
lastdec = timers->TCNTB4 = timer_load_val;
/* auto load, manual update of Timer 4 */
timers->TCON = (timers->TCON & ~0x0700000) | 0x600000;
/* auto load, start Timer 4 */
timers->TCON = (timers->TCON & ~0x0700000) | 0x500000;
timestamp = 0;
return (0);
}
4.int env_init(void)
{
int crc1_ok = 0, crc2_ok = 0;
uchar flag1 = flash_addr->flags;
uchar flag2 = flash_addr_new->flags;
ulong addr_default = (ulong)&default_environment[0];
ulong addr1 = (ulong)&(flash_addr->data);
ulong addr2 = (ulong)&(flash_addr_new->data);
crc1_ok = (crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc);
crc2_ok = (crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc);
if (crc1_ok && ! crc2_ok) {
gd->env_addr = addr1;
gd->env_valid = 1;
} else if (! crc1_ok && crc2_ok) {
gd->env_addr = addr2;
gd->env_valid = 1;
} else if (! crc1_ok && ! crc2_ok) {
gd->env_addr = addr_default;
gd->env_valid = 0;
} else if (flag1 == ACTIVE_FLAG && flag2 == OBSOLETE_FLAG) {
gd->env_addr = addr1;
gd->env_valid = 1;
} else if (flag1 == OBSOLETE_FLAG && flag2 == ACTIVE_FLAG) {
gd->env_addr = addr2;
gd->env_valid = 1;
} else if (flag1 == flag2) {
gd->env_addr = addr1;
gd->env_valid = 2;
} else if (flag1 == 0xFF) {
gd->env_addr = addr1;
gd->env_valid = 2;
} else if (flag2 == 0xFF) {
gd->env_addr = addr2;
gd->env_valid = 2;
}
return (0);
}
未完待续~~~
插件实验室新闻工作者 小倩