找回密码
 立即注册
首页 业界区 业界 Linux 内核启动过程中的日志输出阶段分析 ...

Linux 内核启动过程中的日志输出阶段分析

啦迩 2025-9-28 12:21:46
问题描述

在对比原理图后,发现打印日志的串口是UART2(GPIO3_A2 & GPIO3_A3),但设备树中只开启了UART0(GPIO1_C2&GPIO1_C3)
/* 以下设备树内容来自多个设备树描述文件*/
  1. &uart0 {
  2.         pinctrl-names = "default";
  3.         pinctrl-0 = <&uart0_xfer &uart0_ctsn>;
  4.         status = "okay";
  5. };
  6. uart0: serial@ff560000 {
  7.         compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
  8.         reg = <0xff560000 0x100>;
  9.         interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
  10.         reg-shift = <2>;
  11.         reg-io-width = <4>;
  12.         dmas = <&dmac 5>, <&dmac 4>;
  13.         clock-frequency = <24000000>;
  14.         clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
  15.         clock-names = "baudclk", "apb_pclk";
  16.         pinctrl-names = "default";
  17.         pinctrl-0 = <&uart0_xfer &uart0_ctsn &uart0_rtsn>;
  18.         status = "disabled";
  19. };
  20. uart0_xfer: uart0-xfer {
  21.         rockchip,pins =
  22.                 /* uart0_rx */
  23.                 <1 RK_PC2 1 &pcfg_pull_up>,
  24.                 /* uart0_tx */
  25.                 <1 RK_PC3 1 &pcfg_pull_up>;
  26. };
  27. uart2: serial@ff570000 {
  28.         compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
  29.         reg = <0xff570000 0x100>;
  30.         interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
  31.         reg-shift = <2>;
  32.         reg-io-width = <4>;
  33.         dmas = <&dmac 9>, <&dmac 8>;
  34.         clock-frequency = <24000000>;
  35.         clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
  36.         clock-names = "baudclk", "apb_pclk";
  37.         pinctrl-names = "default";
  38.         pinctrl-0 = <&uart2m1_xfer>;
  39.         status = "disabled";
  40. };
  41. uart2m1_xfer: uart2m1-xfer {
  42.         rockchip,pins =
  43.                 /* uart2_rx_m1 */
  44.                 <3 RK_PA3 1 &pcfg_pull_up>,
  45.                 /* uart2_tx_m1 */
  46.                 <3 RK_PA2 1 &pcfg_pull_up>;
  47. };
复制代码
问题分析

无论是硬件原理图还是实际结果都表示启动日志是从UART2打印出来的,所以我们就要尽量往UART2去拓展。
由设备树可以得到内核启动参数 bootargs:
  1. chosen {
  2.   bootargs = "earlycon=uart8250,mmio32,0xff570000 console=ttyFIQ0 root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait snd_aloop.index=7";
  3. };
复制代码
earlycon阶段(内核初始化早期)

首先可以看到earlycon=uart8250,mmio32,0xff570000,earlycon直接在设备树解析前初始化硬件,不依赖设备树中的status属性。在内核初始化早期,直接向地址0xff570000 输出日志,对比之前提到的设备树配置,我们可以看到这个地址就是UART2串口。
标准console阶段(内核初始化后期)

在bootargs中设置了console=ttyFIQ0

  • 由于UART2在设备树中被标记为disabled,内核不会注册标准UART驱动(如ttyS2)
  • 后续日志会通过ttyFIQ0输出(通常是 Rockchip 的 FIQ 调试串口)
    就像一个知道结果的解谜游戏,我们现在大可以猜测是不是ttyFIQ0配置了UART2,接过了日志输出的任务并继续向UART2输出(通过FIQ驱动,绕过标准UART状态),接下来我们继续分析设备树:
  1. &fiq_debugger {
  2.         status = "okay";
  3. };
复制代码
fiq_debugger是启用的,我们继续向上层设备树文件找,目前来到了rv1126.dtsi
  1. fiq_debugger: fiq-debugger {
  2.         compatible = "rockchip,fiq-debugger";
  3.         rockchip,serial-id = <2>;  // 绑定到 UART2
  4.         rockchip,wake-irq = <0>;
  5.         rockchip,irq-mode-enable = <0>;
  6.         rockchip,baudrate = <1500000>;  /* Only 115200 and 1500000 */
  7.         interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
  8.         status = "disabled";
  9. };
复制代码
出现了!rockchip,serial-id = ,我们可以看到fiq_debugger节点绑定到了UART2,由此完成了内核启动早期与后期的日志输出的衔接。
总结

本篇文章是由一个status为disable但却被作为日志输出的UART2引出,核心是围绕着bootargs中的earlycon与console参数展开。earlycon直接通过UART2的地址,在设备树解析前输出早期日志;console通过FIQ调试串口,复用了UART2的端口,实际上是使用了FIQ的驱动输出后续日志。完成了整个内核初始化及后续过程中的日志输出不同阶段的衔接。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

2025-10-31 03:00:57

举报

您需要登录后才可以回帖 登录 | 立即注册