ARM系统移植

u-boot一旦引导到内核,操作权限就会交给内核,那么所有的事情就和u-boot没有关系了,除了u-boot传递给内核的参数。
基地址+100 u-boot给内核的参数
基地址+4000 映射列表
基地址+8000 内核

内核的执行流程:
整个内核的入口:根据lds文件和编译到内核的源码文件共同决定。
arch/arm/kernel/head.s
safe_svcmode_maskall r9 确保处在SVC模式
mrc p15, 0, r9, c0, c0 读取cpu id cpu id在协处理器内部
bl __lookup_processor_type 判断内核是否支持本cpu


arch/arm/kernel/head-common.S
__lookup_processor_type:
adr r3, __lookup_processor_type_data 基于pc
154 ldmia r3, {r4 - r6}
155 sub r3, r3, r4 @ get offset between virt&phys 判断实际运行地址和规划地址的差值,为了找cpuid在内存上
156 add r5, r5, r3 @ convert virt addresses to
157 add r6, r6, r3 @ physical address space
1: ldmia r5, {r3, r4} @ value, mask
159 and r4, r4, r9 @ mask wanted bits
160 teq r3, r4
161 beq 2f
162 add r5, r5, #PROC_INFO_SZ (8) @ sizeof(proc_info_list)
163 cmp r5, r6
164 blo 1b
165 mov r5, #0 @ unknown processor
166 2: mov pc, lr

__lookup_processor_type_data
174 __lookup_processor_type_data:
175 .long . 利用一条语句,在不同地方(实际运行地址、连接规划地址)的不同,来计算实际运行地址和规划地址的差值
176 .long __proc_info_begin
177 .long __proc_info_end
178 .size __lookup_processor_type_data, . - __lookup_processor_type_data


bl __vet_atags 用来检测参数。
128 bl __create_page_tables 穿件映射列表,映射列表是(虚拟地址和物理地址之间的转换表)

ldr r13, =__mmap_switched 为跳到下一个阶段做准备
adr lr, BSYM(1f)
1: b __enable_mmu 打开mmu
b __turn_mmu_on
ENTRY(__turn_mmu_on)
464 mov r0, r0
465 instr_sync
466 mcr p15, 0, r0, c1, c0, 0 @ write control reg
467 mrc p15, 0, r3, c0, c0, 0 @ read id reg
468 instr_sync
469 mov r3, r3
470 mov r3, r13(=__mmap_switched )
471 mov pc, r3
pc ==__mmap_switched
472 __turn_mmu_on_end:

__mmap_switched :内核的第二阶段


mov fp, #0 @ Clear BSS (and zero fp)
91 1: cmp r6, r7
92 strcc fp, [r6],#4
93 bcc 1b
94
95 ARM( ldmia r3, {r4, r5, r6, r7, sp}) 设置堆栈
473 ENDPROC(__turn_mmu_on)

跳转到c语言:
stmneia r7, {r0, r4} @ Save control register values
104 b start_kernel

init/main.c
start_kernel()

setup_arch(&command_line); 会解析u-boot传递的参数。
mdesc = setup_machine_fdt(__atags_pointer) 解析设备树
mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); 检测本内核是或否支持板子


command_line :制定根文件系统


rest_init();

382 kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

if (execute_command) {判断bootargs里面有init=“?”,如果有则执行,如果没有则去下面的路径上运行
865 ret = run_init_process(execute_command);
866 if (!ret)
867 return 0;
868 pr_err("Failed to execute %s (error %d). Attempting defaults...\n",
869 execute_command, ret);
870 }
871 if (!try_to_run_init_process("/sbin/init") ||
872 !try_to_run_init_process("/etc/init") ||
873 !try_to_run_init_process("/bin/init") ||
874 !try_to_run_init_process("/bin/sh"))

 

init进程的调用流程:
init/main.c
start_kernel()-----》 rest_init();----》kernel_init();---》》》

if (execute_command) {判断bootargs里面有init=“?”,如果有则执行,如果没有则去下面的路径上运行
865 ret = run_init_process(execute_command);
866 if (!ret)
867 return 0;
868 pr_err("Failed to execute %s (error %d). Attempting defaults...\n",
869 execute_command, ret);
870 }
871 if (!try_to_run_init_process("/sbin/init") ||
872 !try_to_run_init_process("/etc/init") ||
873 !try_to_run_init_process("/bin/init") ||
874 !try_to_run_init_process("/bin/sh"))

 

printk内核打印函数:可以分等级

内核调试:内核的错误有两种
panic错误:内核运行到不能再运行的地方出错,是内核设计者提前规定的一些错误点。现阶段主要造成的原因是,参数错误
oops错误:内核使用非法指针,会将错误的pc报出,可以根据addr2line来查找错误点。

 

根文件系统:第一个被挂载的文件系统。
sys(文件系统) 用来显示所有的设备文件
proc(文件系统) 又来显示所有的内核信息
tmp 基于内存的文件夹,主要用来进行记录日志
dev 基于内存的文件夹,用来管理所有的设备节点

转载于:https://www.cnblogs.com/ChuckYin/p/5361305.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值