正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-12.1 Linux内核启动流程简介

发布于:2025-06-09 ⋅ 阅读:(12) ⋅ 点赞:(0)

 前言:

本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》

正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

正点原子imx6ull-mini-Linux驱动之Linux I2C 驱动实验(21)-CSDN博客

正文:

本文是 “Arm(iMX6U)Linux系统移植和根文件系统构键篇--9 Linux内核编译和体验。本节将参考正点原子的视频教程和配套的正点原子开发指南文档进行学习。

0. 概述

看完 Linux 内核的顶层 Makefile 以后再来看 Linux 内核的大致启动流程, Linux 内核的启动流程要比 uboot 复杂的多,涉及到的内容也更多,因此本章我们就大致的了解一下 Linux 内核的启动流程。

1 链接脚本 vmlinux.lds

要分析 Linux 启动流程,同样需要先编译一下 Linux 源码,因为有很多文件是需要编译才会生成的。首先分析 Linux 内核的连接脚本文件 arch/arm/kernel/vmlinux.lds,通过链接脚本可以找到 Linux 内核的第一行程序是从哪里执行的。 vmlinux.lds 中有如下代码:

arch/arm/kernel/vmlinux.lds

 第 493 行的 ENTRY 指明了了 Linux 内核入口,入口为 stext, stext 定义在文件arch/arm/kernel/head.S 中 , 因 此 要 分 析 Linux 内 核 的 启 动 流 程 , 就 得 先 从 文 件arch/arm/kernel/head.S 的 stext 处开始分析。

arch/arm/kernel/head.S

 2 Linux 内核启动流程分析

2.1 Linux 内核入口 stext

stext 是 Linux 内核的入口地址,在文件 arch/arm/kernel/head.S 中有如下所示提示内容:

根据示例代码 36.2.1.1 中的注释, Linux 内核启动之前要求如下:

①、关闭 MMU。
②、关闭 D-cache。
③、 I-Cache 无所谓。
④、 r0=0。
⑤、 r1=machine nr(也就是机器 ID)。
⑥、 r2=atags 或者设备树(dtb)首地址。

Linux 内核的入口点 stext 其实相当于内核的入口函数, stext 函数内容如下:

 第 92 行,调用函数 safe_svcmode_maskall 确保 CPU 处于 SVC 模式,并且关闭了所有的中断。 safe_svcmode_maskall 定义在文件 arch/arm/include/asm/assembler.h 中。

第 94 行,读处理器 ID, ID 值保存在 r9 寄存器中。

第 95 行,调用函数__lookup_processor_type 检查当前系统是否支持此 CPU,如果支持就获取 procinfo 信 息 。 procinfo 是 proc_info_list 类 型 的 结 构 体 , proc_info_list 在 文 件arch/arm/include/asm/procinfo.h 中的定义如下:

Linux 内核将每种处理器都抽象为一个 proc_info_list 结构体,每种处理器都对应一个procinfo。因此可以通过处理器 ID 来找到对应的 procinfo 结构, __lookup_processor_type 函数找到对应处理器的 procinfo 以后会将其保存到 r5 寄存器中。

继续回到示例代码 36.2.1.2 中,第 121 行,调用函数__vet_atags 验证 atags 或设备树(dtb)的合法性。函数__vet_atags 定义在文件 arch/arm/kernel/head-common.S 中。

第 128 行,调用函数__create_page_tables 创建页表。

第 137 行,将函数__mmap_switched 的地址保存到 r13 寄存器中。 __mmap_switched 定义在文件 arch/arm/kernel/head-common.S__mmap_switched 最终会调用 start_kernel 函数

第 144 行 , 调 用 __enable_mmu 函 数 使 能 MMU , __enable_mmu 定 义 在 文 件arch/arm/kernel/head.S 中。 __enable_mmu 最终会通过调用__turn_mmu_on 来打开 MMU,__turn_mmu_on 最后会执行 r13 里面保存的__mmap_switched 函数。

2.2 __mmap_switched 函数

__mmap_switched 函数定义在文件 arch/arm/kernel/head-common.S 中,函数代码如下:

第 104 行最终调用 start_kernel 来启动 Linux 内核, start_kernel 函数定义在文件 init/main.c中。

init/main.c

 2.3 start_kernel 函数