从uboot到linux内核启动完毕的整个流程中主要的函数调用关系一览:
uboot启动:
cpu/arm920t/start.S开始
reset //set svc mode & turn off the watchdog & mask all interrupt
...
cpu_init_crit //禁止Icache,汇编代码
lowlevel_init //初始化SDRAM
stack_setup//设置svc模式栈
clock_init//初始化时钟,c函数
relocate//看看是否要重定向
clear_bss
CopyCode2Ram
_start_armboot//运行命令 or 启动内核
init_sequence数组定义了:
cpu_init
board_init//like set system cloclk
interrupt_init//timer init
env_init//检查Flash上面的环境参数是否有效
init_baudrate
serial_init//这3个函数是初始化串口控制台
console_init_f
dram_init//检测系统内存:起始地址&大小
...
flash_init//初始化nor Flash
...
nand_init//初始化nand
env_relocate//将环境参数读入内存指定位置
...
cs8900_get_enetaddr//初始化网络设备:对应是配置DM9000
...
main_loop
s=getenv ("bootcmd")//获取串口命令
abortboot (bootdelay)//bootdelay时间内是否有串口命令输入?
bBootFrmNORFlash//判断从哪里启动?nor or nand?
Y->run_command("menu", 0)//nor 启动
读取串口命令&执行
N->run_command (s, 0)//启动内核
do_bootm
do_bootm_linux
theKernel (0, bd->bi_arch_number, bd->bi_boot_params)//开始启动内核
||
||
||
\/
arch\arm\boot\compressed\head.S:内核自解压
||
||
||
\/
arch/arm/kernel/head.S:内核启动
__lookup_processor_type //cpu id?
__lookup_machine_type //机器id?
__vet_atags
__create_page_tables //创建页表
__v7_setup //MMU设置的核心内容
__enable_mmu
__turn_mmu_on //使能mmu
__switch_data
__mmap_switched //复制数据段、清BSS、设置栈指针、保存cpu ID、保存机器ID
start_kernel //启动内核工作:/init/main.c
setup_arch //解析uboot启动参数(addr:0x30000100):tag列表在此初步处理
setup_processor
setup_machine//获得开发板的machine_desc数据结构
...
parse_tags //解析每一个tag
parse_cmdline//对命令行进行一些先期的处理:处理一些参数
paging_init //重新初始化页表
devicemaps_init
mdesc->map_io()
s3c24xx_init_io
s3c24xx_init_clocks
s3c24xx_init_uarts
...
console_init //控制台初始化(串口、LCD等)
s3c24xx_serial_initconsole//串口控制台初始化
register_console(&s3c24xx_serial_console)
setup_command_line //命令行后期处理
rest_init //这个函数属于内核的0号线程部分
kernel_thread //开创内核的1号进程
kernel_init//内核的1号进程:init
do_basic_setup(); //初始化内核设备
init_workqueues//初始化工作队列
usermodehelper_init//启动用户态khelper进程
driver_init //设备模型中一些基础结构体初始化和设备的注册
do_initcalls //调用所有的被“initcall”修饰的函数
prepare_namespace
name_to_dev_t //解析uboot传进来的“root=”命令以获得需要挂载的设备号
mount_root //挂接根文件系统
init_post //执行应用程序
free_initmem //将前面调用过被“init”修饰的函数空间释放掉
sys_open & sys_dmp //打开标准终端 0 1 2
run_init_process //从内核态切换到用户态,运行第一个用户进程:1号用户进程,由ubootd的command_line传进“init=/linuxrc”
kernel_execve
do_execve
cpu_idle//若所有进程都执行完毕,退回内核0号线程的进入空闲等待
内核启动这部分代码核心总结:内核创建进程的过程
start_kernel-->rest_init(0号线程)-->kernel_init(1号内核进程)-->init_post(1号用户进程)-->cpu_idle(所有进程退出,进入0号线程空闲)