4412内核移植


牛逼人配的:


https://github.com/abcamus/Linux-Kernel


博客:

http://blog.csdn.net/xie0812/article/details/10816059 

http://www.cnblogs.com/pengdonglin137/p/5137941.html 

http://www.embedu.org/Column/Column904.htm 

http://blog.sina.com.cn/s/blog_7fdf9aa70102wa0a.html


http://blog.csdn.net/fengyuwuzu0519/article/details/74101380  

http://blog.csdn.net/abcamus/article/details/53424619  



问题:

http://blog.csdn.net/r_Jimy/article/details/54730609  


分析:

http://blog.csdn.net/zqixiao_09/article/details/50820128 


总结部分:

make uImage ---生成内核镜像  /arch/arm/boot/uImag

make dtbs ---生成设备树文件  /arch/arm/boot/dtb/exynos4412-fs4412.dtb

make modules ---把配置值选成M的代码编译生成模块文件。(.ko)  放在对应的源码目录下。


Kconfig 介绍:http://www.cnblogs.com/Daniel-G/archive/2013/08/27/3284791.html 

                         所有配置工具都是读取arch/$(ARCH)/Kconnfig 文件来生成配置界面

CONFIG_LEDS_FS4412=y   # 对应的文件被编进内核

CONFIG_LEDS_FS4412=m   # 对应的文件被编成模块

CONFIG_LEDS_FS4412   # 对应的文件没有被使用

内核目录结构:http://www.cnblogs.com/holens/p/3792136.html  

常用目录:

arch:体系结构相关代码
ipc:进程调度相关代码
mm:内存管理
Documentation:帮助文档
net:网络协议
lib:库
scripts:编译相关脚本工具
tools:编译相关工具
drivers:设备驱动
fs:文件系统实现


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


1. 编译过程分析

决定编译哪些文件

Linux内核的编译过程从顶层Makefile开始,然后递归地进入各级子目录调用他们的makefile,分为3个步骤:

a -- 顶层Makefile 决定内核根目录下哪些子目录将被编进内核;

      顶层Makefile将这14个子目录分为5类:init-y、divers-y、net-y、libs-y和core-y


b -- arch/$(ARCH)/Makefile 决定arch/$(ARCH)目录下哪些文件、哪些目录将被编进内核;

      编译内核时,将依次进入init-y、core-y、libs-y、drivers-y和net-y 所列出的目录中执行它们的Makefile,每个子目录都会生成一个 built-in.o(libs-y所

列目录下,有可能生成lib.a文件)。最后,head-y所表示的文件将和在这些built-in.o、lib.a 一起被连接成内核映像文件 vmlinux


c -- 各级子目录下的Makefile决定所在目录下哪些文件将被编进内核,哪些文件将被编程模块(即驱动程序),进入哪些子目录继续调用它们的Makefile。

       在配置内核时,生成配置文件.config。内核顶层Makefile使用如下语句间接包含.config 文件,以后就根据.config中定义的各个变量决定编译哪些文件。


怎样编译这些文件

即编译选项、连接选项是什么。这些选项分3类:全局的,适用于整个内核代码树;局部的,仅适用于某个Makefile中的所有文件;个体的,仅适用于某个文件。

全局选项在顶层Makefile和arch/$(ARCH)/Makefile 中定义,这些选项的名称为:CFLAGS、AFLAGS、LDFLAGS、ARFLAGS,他们分别是编译C文件的选项、编译汇编问价你的选项、连接文件的选项、制作库文件的选项。


怎样连接这些文件,它们顺序如何

对于ARM体系,连接脚本就是arch/arm/kernel/vmlinux.lds,它由 arch/arm/kernel/vmlinux/lds.S文件生成(文件名可能变化,反正是某个体系下的lds.S生成的)


总结:

a -- 配置文件.config 中定义了一系列的变量,Makefile将结合它们来决定哪些文件被编进内核、哪些文件被编进模块、涉及哪些子目录;

b -- 顶层Makefile和arch/$(ARCH)/Makefile决定根目录下哪些子目录、arch/$(ARCH) 目录下哪些文件和目录将被编进内核;

c -- 最后,各级子目录下的Makefile决定所在目录下哪些文件将被编进内核,哪些文件将被变成模块(即驱动程序),进入哪些子目录继续调用它们的Makefile;

d -- 顶层Nakedfile和arch/$(ARCH)/Makefile设置了可以影响所有文件的编译、连接选项:CFLAGS、AFLAGS、LDFLAGS、ARFLAGS;

e -- 顶层Makefile按照一定的顺序组织文件,根据连接脚本 arch/$(ARCH)/kernel/vmlinux.lds生成内核映像文件vmlinux。



!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


2. 启动流程分析

linux 的过程可以分为两部分:架构/开发板相关的引导过程、后续的通用启动过程。对于uImage、zImage ,它们首先进行自解压得到vmlinux ,然后执行 vmlinux 开始“正常的”启动流程。

       引导阶段通常使用汇编语言编写,它首先检查内核是否支持当前架构的处理器,然后检查是否支持当前开发板。通过检查后,就为调用下一阶段的start_kernel函数作准备了。这主要分如下两个步骤:

1)-- 连接内核时使用的虚拟地址,所以要设置页表、使能MMU;

2)调用C 函数 start_kernel 之前的常规工作,包括复制数据段、清除BSS段、调用start_kernel 函数。


以下是对第一部分的分析:

在连接文件中查看函数入口点,内核编译完成后会在arch/arm/kernel/下生成 vmlinux.lds 文件

 stext 在 linux/arch/arm/kernel/head.S 中被定义,做为函数入口点,linux/arch/arm/kernel/head.S是linux内核映像解压后执行的第一个文件

a -- 设定为SVC模式,关闭IRQ、FIQ;

b -- 确定CPU的ID号,判定其是否有效;

c -- 确定machine的ID号,检查合法性;

d -- 检查bootloader传入的参数列表atags的合法性

e -- 创建初始页表

f -- 使能MMU,跳转到start_kernel


a -- 确保处于SVC模式(就是设置CPSR 模式位,并屏蔽中断


b -- 检查CPU ID 是否匹配

获取ID并放到 r9 寄存器中,调用_lookup_processor_type 函数, 函数主要用来判定内核是否和当前的CPU匹配,如果不匹配,r5寄存器的值应为0,此时会调用 _error_p函数,它用来打印错误信息,即内核和当前的CPU不匹配,此时内核时不能启动的;如果两者匹配,会返回一个描述处理器结构的地址(在r5寄存器中),然后调用下面的函数。

_lookup_processor_type 函数,在arch/arm/kernel/head-common.S 中定义:

就是一个地址转换过程,因为在判定CPU架构时未开启系统的MMU功能,所以均使用物理地址,而内核代码在连接时是以虚拟地址来实现的,因此要想用proc_info_list 结构体,就要先找到proc_info_list 结构的物理地址,这样必须使用上面的转换代码。

        proc_info_list 结构体很重要。在Linux 内核映像中定义了很多个proc_info_list 结构,该结构表示的是内核所支持的CPU架构

        proc_info_list 结构体  ,这个结构体在  arch/arm/include/asm/procinfo.h  中定义:

对于 Cortex-A9 来说,其结构体在文件 arch/arm/mm/proc-v7.S 中初始化

 .section ".proc.info.init"表明了该结构在编译后存放的位置。在链接文件arch/arm/kernel/vmlinux.lds中:

 如果CPU ID匹配,在编译内核文件时,会编译 proc-v7.S 这个文件,可以在arch/arm/mm/Makefile 中看到这个文件


c -- 检测 机器ID是否匹配


d -- 检查bootloader传入的参数列表atags的合法性

_vet_atags 函数用于检测参数列表atags的合法性(__vet_atags:  arch/arm/kernel/head-common.S 中定义:

        内核参数链表的格式和说明可以从内核源代码目录树中的 中找到,参数链表必须以ATAG_CORE 开始,以ATAG_NONE结束。这里的 ATAG_CORE,ATAG_NONE是各个参数的标记,本身是一个32位值,例如:ATAG_CORE=0x54410001。其它的参数标记还包括: ATAG_MEM32 , ATAG_INITRD , ATAG_RAMDISK ,ATAG_COMDLINE 等。每个参数标记就代表一个参数结构体,由各个参数结构体构成了参数链表


e -- 创建初始页表


f -- 使能MMU,跳转到start_kernel

mov pc, r13 就是将跳转到__switch_data处。

在文件linux/arch/arm/kernel/head-common.S中:

__mmap_switched_data:

__mmap_switched

最终b   start_kernel


https://github.com/abcamus/Linux-Kernel
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值