一、在Linux内核的编译,首先要对booting sequence有一个基本的了解。首先要对比AM335系列的启动顺序。
AM335x 有四个不同的启动阶段:
- ROM
- SPL(Secondary Program Loader)
- U-BOOT
- Linux Kernel
第一阶段:ROM Code
ROM Code 是芯片上电复位之后第一块自动运行的代码。ROM Code 固化在芯片中不能被用户修改。
ROM Code 存储在片上地址 0x40000000-0x40040000 处。
ROM Code 不可能太复杂,ROM大小是一个限制,最重要的还是因为其所能获取的系统信息太少,所以处理器只能使用简单的方法去寻找能完成复杂功能的代码, ROM Code 只能将它加载到处理器内部 RAM 中运行,一般处理器的内部 RAM 都要小于128KB,这里只有64K.
ROM Code 有两个主要的功能:
配置设备并初始化主要的外设:建立堆栈,配置开门狗定时器1(设置到三分钟),配置 PLL 和系统时钟
为下一阶段启动做准备:为下一阶段启动检查启动源(SPL),把下一启动阶段的 bootloader 代码移动到内存中准备运行
第二阶段叫做 SPL,但有些时候也叫 MLO。SPL 是启动 U-Boot 前的一个阶段,并且必须从 启动源(MMC、USB、SD、UART等)加载到内部 RAM 中。SPL 只有极少的功能,SPL 主要的职责就是初始化 DDR,时钟等最小系统,以读取 U-Boot 并加载到 DDR 中。
第三阶段:U-Boot, 主要的工作就是正确加载 Kernel。和 SPL 类似,U-boot 也是要加载下一个阶段的 image,但是 U-Boot 提供了更多外设的支持和更多的调试工具。所以,U-Boot 也要进行各个模块的配置,上述 SPL 配置的部分,除了 DDR 外,U-Boot 也会根据需求重新配置(这里重置主要是U-Boot 是一个开源工程,其要兼容某些特殊的芯片,从而需要做重载)。此外,U-Boot 也会对网口,SD卡等根据需求进行配置。完成配置后,U-Boot 会从相应的存储器或者外设读取 Kernel,并传递参数给 Kernel,运行 Kernel。
第四阶段:启动 Linux 内核。uImage 是与描述内核头信息交换过的内核镜像。这个头信息是一个 64kB的信息块,包含了目标架构、操作系统、内核尺寸、入口等信息。U-boot 启动 uImage的时候,头信息会在命令行输出。
二、在熟悉了AM335之后,可以理解到,AM4378其实和很相似。同样提供了这4个阶段,其中ROM启动部分固化在内存中,是我们不需要接触的。其他的都是可以定制的。
第二阶段编译MLO,第三阶段的u-boot,这是通过上贴的u-boot编译实现的
第四阶段的linux内核,则是对内核编译实现的。
启动了booting,对于程序还有一个linux版本的加载那么是通过roofs的编译来实现的,可以选择桌面版本等等更丰富的功能。但是对于booting来说,其实已经完成了。
三、对应于ROM部分,设计的逻辑很完善,详见下图,不详述了。
对应的开发的ROM只有64k,如下。
四、第二阶段的booting。选择启动设备,见下面流程图。
特别的,选择SD卡启动的逻辑图如下,
这里,启动的img不能超过256k,这是比AM335要大的,地址如下
这个是以FAT格式,存在的MLO。读取MLO的流程如下,
除此以外,还新增了以太网,uart,U盘启动的选项,主要是为了更新firmware。不详述。
五、加载完MLO,就是和硬件的交接基本完成,就该后面的u-boot来完成后续任务了。
从u-boot开始,就具备了访问GPIO端口的功能了。不过,如果充分发挥am4378的性能,一个更完善的操作系统就更有必要。后面的过程和am335以及类似的各种支持linux的开发板过程都相似的,按照基于debian或者feroda,文件组织有所不同。
Jian Zhou:
感谢您的分享,可以和管理员申请加精了。