arm环境u-boot功能和linux启动过程
1. U-BOOT概况总结
一、 启动代码为start.S
二、 由于u-boot为裸板上第一个程序,所以要初始化各个外设,由于u-boot已经初始化了,
包括:中断禁用、分配动态内存、初始化BBS区域、初始化页目录、打开缓存等任务。
所以linux内核不需要全部再次初始化,所以可以理解bootloader和kernel其实是两兄弟。
例:
1 |
|
三、 U-boot引导内核第一步要做的的是把内核下到ram中,然后跳到内核的start函数。
四、bootloader必须提供5种功能:RAM初始化、串行端口初始化、查找机器类别、构建tagged list内核、将控制移交到内核镜像。
2. linux内核初始化流程
u-boot跳到linux内核的arch/arm/boot/compressed/head.S中start后
内核大致可以理解为三部曲:
第一步 解压内核并跳到start_kernel()。
1.arch/arm/boot/compressed/head.S(start)
准备解压内核
2.arch/arm/boot/compressed/head.S
通过decompress_kernel 解压zImage
通过call_kernel调用已解压后内核vmlinux
3.arch/arm/kernel/head.S
通过ENTRY(stext)->
处理器信息搜寻——__look_processor_type
搜寻我的机型——__lookup_machine_type
通过__mmap_switched调用start_kernel
第二步 跳到真正第一个内核代码init/main.c(start_kernel())。 注:在linux 0.11中为init/main.c main()。
其中明星函数(排名不分先后):
1.初始化console(此处为平台相关需要hack的地方<1>)
start_kernel->console_init->serial_pxa_console_init
2.注册SOC初始化函数machine_desc
start_kernel->setup_arch()->setup_machine(machine_arch_type)[/arch/arm/kernel/setup.c]
[/arch/arm/mach-s3c2440/mach-mini244.c]
MACHINE_START(MINI2440, “FriendlyARM Mini2440 development board”)
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = mini2440_map_io,
.init_machine = mini2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
1)init_machine 在start_kernel()->setup_arch()->do_initcalls()->customize_machine()->mini6410_machine_init()
2)init_irq在start_kernel() -> init_IRQ() -> init_arch_irq()中被调用
3)map_io 在 setup_arch() -> paging_init() -> devicemaps_init()中被调用
4)timer是定义系统时钟,定义TIMER4为系统时钟,在arch/arm/plat-s3c/time.c中体现。
在start_kernel() -> time_init()中被调用。
5)boot_params是bootloader向内核传递的参数的位置,这要和bootloader中参数的定义要一致。
http://blog.csdn.net/boyemachao/article/details/45394363
3.初始化虚拟驱动平台platform
start_kernel->kernel_init()->do_basic_setup()->driver_init()->platform_bus_init()→bus_register(&platform_bus_type)
4.初始化SOC(initcall参考下面的init.h)
start_kernel->kernel_init()->do_basic_setup()->do_initcalls()->do_one_initcall()
第三步 就为愉快的init的代码了也就是第一个进程,在linux 0.11中集成在内核中。在之后版本由用户态提供。
当然我已经升级为systemd啦,哈哈。
3. linux初始化代码框架
哪部分是只和CPU相关的部分,
哪部分是SOC平台相关的部分,
也再次标明LINUX下大致逻辑。
第一部分代码arch/arm/boot/
简介:也就是自我解压部分,可以理解为和cpu相关但和SOC无关。
移植:移植时选择对应的cpu。
功能:arch/arm/boot/compressed/head.S自我解压前准备、解压缩。跳到start_kernel。
第二部分代码init/main.c
简介:也就是start_kernel()或0.11中的main() 可以理解内核真正的第一代码。为平台无关代码。
移植:移植时不用管。
功能:此代码虽说简单的大几十行,但功能太多,我还是给个linux 0.11中main()的靓照吧_!
第三部分代码 arch/arm/PLAT- arch/arm/MACH-
简介:为了完成start_kernel()中初始化的SOC相关部分。
移植:移植时需要考虑对应的SOC。没有对应soc支持时,才是各路玩家大显身手的时候。
功能:看下面的介绍吧。
4. Mini2440的plat和mach
plat-s3c24xx
mach-s3c2440
mach-s3c2410
======================
\1. 三星这样分层的理由是s3c系列的soc具有一定的共通性, plat-实现了一些较通用的封装, 这些封装的具体参数一般是宏, 这些宏如寄存器地址可能是在mach-里面被定义;
linux/arch/arm/plat-s3c24xx/common-smdk.c
static struct s3c24xx_led_platdata smdk_pdata_led5 = {
.gpio = S3C2410_GPF5,
.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
.name = “led5”,
.def_trigger = “nand-disk”,
};
linux/include/asm-arm/arch-s3c2410/regs-gpio.h
#define S3C2410_GPF5 S3C2410_GPIONO(S3C2410_GPIO_BANKF, 5)
\2. 原则上是把所有s3c系列共同的东西放在 plat-里面去, 具体的io或者比较有mach-特色的部分放到mach-里面;
改板时, 实际上大多是直接在mach-里面增删自己的功能. (不按三星预设方案的改动除外)
plat里面需要动的相对更少, 不过在linux/arch/arm/plat-s3c24xx/common-smdk.c里面,
我们可以根据实际情形来分配nand的分区(修改static struct mtd_partition smdk_default_nand_part[] );
\3. 编译时,一般只会选中一个特定的mach-, mach-会调用plat-的功能具体实现平台的资源和设备初始化.
5.内核移植
在一般普通的产品公司,大部分都是在soc上添加自己需要的外设做成产品。
并且常见的soc都已经有了成熟的soc代码支持。
现在讨论内核移植重点在板级支持,这属于BSP工程师的范围。并非属于芯片工程。
BSP工程师的能力就是要在各种板子上移植我们万众期待的linux内核。
总的来说,我们所做的就是要找到外设的区别,熟悉内核的框架,
修改外设的驱动,使内核完美的运行起来就好了。
所涉及到的驱动:GPIO、协处理器、中断、时钟、MMU、存储控制器、NAND、UART、IIC等。
我们可以找出最基本的,启动linux所依赖的。并根据依赖的顺序一一攻破。
我暂时认为,学习此部分好的方法是先在一个成熟板子上写一个裸板程序。
这样可以熟悉板子硬件,也可熟悉一个小的系统是如何跑起来的。
有了这个基础我们就能把我哪些是最为基础的驱动。和依赖的顺序等。
通过本文可以体会到,对于内核,移植它改造它有难度呀。
会裸板驱动、会写bootloader只是基础。
还要熟悉内核代码,真是上知系统、应用,下知硬件、驱动。
参考资料:
[console] early printk实现流程
http://blog.csdn.net/ooonebook/article/details/52654120
linux2.6中的console_init初始化的研究
http://blog.csdn.net/breeze_vickie/article/details/5563375
linux下tty,控制台,虚拟终端,串口,console(控制台终端)详解
http://blog.csdn.net/liaoxinmeng/article/details/5004743
【原创】s3c2440内核启动时如何注册串口为终端设备