• uboot启动流程-board_init_r函数执行过程


    一.  uboot启动流程

    本文来了解 board_init_r 函数执行过程。_main函数会调用到 board_init_r 函数。

    二.   board_init_r函数执行过程

    _main 函数会调用到 board_init_r 函数。

    _main 函数在 uboot的  /arch/arm/lib/crt0.S 文件中。_main函数中,执行完 relocate_vectors 函数(即重定位中断向量表)后,然后清 BSS 段,之后就是调用 board_init_r函数。

    前面有文章讲解了 board_init_f 函数,在此函数里面会调用一系列的函数来初始化一些外设和 gd 的成员变量。但是 board_init_f 函数并没有初始化所有的外设,还需要做一些后续工作,这些后续工作就是由 board_init_r 函数来完成的,board_init_r 函数定义在文件 common/board_r.c 中,关键的代码如下:

    1. void board_init_r(gd_t *new_gd, ulong dest_addr)
    2. {
    3. ......
    4. if (initcall_run_list(init_sequence_r))
    5. hang();
    6. ......
    7. }

    initcall_run_list 函数来执行初始化序列 init_sequence_r init_sequence_r 是一个函数集合, init_sequence_r 也定义在文件 common/board_r.c 中,由于 init_sequence_f 的内容 比较长,里面有大量的条件编译代码,这里为了缩小篇幅,将条件编译部分删除掉了,去掉条 件编译以后的 init_sequence_r 定义如下:
    1. init_fnc_t init_sequence_r[] = {
    2. initr_trace,
    3. initr_reloc,
    4. initr_caches,
    5. initr_reloc_global_data,
    6. initr_barrier,
    7. initr_malloc,
    8. initr_console_record,
    9. bootstage_relocate,
    10. initr_bootstage,
    11. board_init, /* Setup chipselects */
    12. stdio_init_tables,
    13. initr_serial,
    14. initr_announce,
    15. INIT_FUNC_WATCHDOG_RESET
    16. INIT_FUNC_WATCHDOG_RESET
    17. INIT_FUNC_WATCHDOG_RESET
    18. power_init_board,
    19. initr_flash,
    20. INIT_FUNC_WATCHDOG_RESET
    21. initr_nand,
    22. initr_mmc,
    23. initr_env,
    24. INIT_FUNC_WATCHDOG_RESET
    25. initr_secondary_cpu,
    26. INIT_FUNC_WATCHDOG_RESET
    27. stdio_add_devices,
    28. initr_jumptable,
    29. console_init_r, /* fully init console as a device */
    30. INIT_FUNC_WATCHDOG_RESET
    31. interrupt_init,
    32. initr_enable_interrupts,
    33. initr_ethaddr,
    34. board_late_init,
    35. INIT_FUNC_WATCHDOG_RESET
    36. INIT_FUNC_WATCHDOG_RESET
    37. INIT_FUNC_WATCHDOG_RESET
    38. initr_net,
    39. INIT_FUNC_WATCHDOG_RESET
    40. run_main_loop,
    41. };

    2 行, initr_trace 函数,如果定义了宏 CONFIG_TRACE 的话就会调用函数 trace_init ,初始化和调试跟踪有关的内容。
    3 行, initr_reloc 函数用于设置 gd->flags ,标记重定位完成。
    4 行, initr_caches 函数用于初始化 cache ,使能 cache
    5 行, initr_reloc_global_data 函数,初始化重定位后 gd 的一些成员变量。
    6 行, initr_barrier 函数, I.MX6ULL 未用到。
    7 行, initr_malloc 函数,初始化 malloc
    8 行, initr_console_record 函数,初始化控制台相关的内容, I.MX6ULL 未用到,空函数。
    9 行, bootstage_relocate 函数,启动状态重定位。
    10 行, initr_bootstage 函数,初始化 bootstage 什么的。
    11 行, board_init 函数,板级初始化,包括 74XX 芯片, I2C FEC USB QSPI 等。
    这里 board_init 函数调用的是 mx6ull_alientek_nand.c文件中(因为这里我所使用的是 Nand-Flash版的开发板)
    12 行, stdio_init_tables 函数, stdio 相关初始化。
    13 行, initr_serial 函数,初始化串口。
    14 行, initr_announce 函数,与调试有关,通知已经在 RAM 中运行。
    18 行, power_init_board 函数,初始化电源芯片,正点原子的 I.MX6ULL 开发板没有用到。
    19 行, initr_flash 函数,对于 I.MX6ULL 而言,没有定义宏 CONFIG_SYS_NO_FLASH 的话函数 initr_flash 才有效。但是 mx6_common.h 中定义了宏 CONFIG_SYS_NO_FLASH ,所以
    此函数无效。
    21 行, initr_nand 函数,初始化 NAND ,如果使用 NAND 版本核心板的话就会初始化 NAND

    22 行, initr_mmc 函数,初始化 EMMC ,如果使用 EMMC 版本核心板的话就会初始化
    EMMC。就会有 MMC打印信息。
    23 行, initr_env 函数,初始化环境变量。
    25 行, initr_secondary_cpu 函数,初始化其他 CPU 核, I.MX6ULL 只有一个核,因此此
    函数没用。
    27 行, stdio_add_devices 函数,各种输入输出设备的初始化,如 LCD driver I.MX6ULL
    使用 drv_video_init 函数初始化 LCD 。我所使用的开发板未带LCD屏幕,所以用不到。

    28 行,initr_jumptable 函数,初始化跳转表。

    29 行 , console_init_r 函 数 , 控 制 台 初 始 化 , 初 始 化 完 成 以 后 此 函 数 会 调 用
    stdio_print_current_devices 函数来打印出当前的控制台设备。串口打印如下:
    1. In: serial
    2. Out: serial
    3. Err: serial

    31 行, interrupt_init 函数,初始化中断。
    32 行, initr_enable_interrupts 函数,使能中断。
    33 行, initr_ethaddr 函数,初始化网络地址,也就是获取 MAC 地址读取环境变量 “ ethaddr” 的值。
    34 行, board_late_init 函数,板子后续初始化,此函数定义在文件 mx6ull_alientek_emmc.c
    中,如果环境变量存储在 EMMC 或者 SD 卡中的话此函数会调用 board_late_mmc_env_init 函数
    初始化 EMMC/SD 。会切换到正在时候用的 emmc 设备。

    注意: 类似 CONFIG_CMD_SCSI这种带 CMD的是 uboot支持的 命令。配置是否使用该命令的文件是 mx6ull_alientek_nand.h。

    38 行 , initr_net 函 数 , 初 始 化 网 络 设 备 , 函 数 调 用 顺 序 为 :
    initr_net->eth_initialize->board_eth_init()

    串口打印如下:

    Net:   FEC1
    

    40 行,run_main_loop函数 ,是主循环,处理 uboot命令行模式下输入的 命令。

    uboot命令行模式:开发板上电时,uboot启动时会进入几秒的倒计时,如果在倒计时之前按下 "Enter"回车键,会进入 uboot命令行模式。uboot命令行模式下可以输入命令,开发板可以接收到 输入的命令。如下就是进入了uboot命令行模式:

    以上就是 board_init_r函数大体执行过程。

  • 相关阅读:
    kubernetes之ingress探索实践
    聊一聊Redis的离线分析
    牛客 day2 - 7
    数组的内置功能
    springboot使用配置ElasticSearch完整保姆全教程
    PCIe系列专题之二:2.6 Flow Control初始化
    无需公网IP,使用MCSM面板一键搭建我的世界Minecraft服务器联机游戏
    cesium在地形上贴地添加各种entity
    聊聊精益需求的产生过程
    NCV7705DQAR2G 汽车电机驱动器(NCV7705DQR2G)引脚配置
  • 原文地址:https://blog.csdn.net/wojiaxiaohuang2014/article/details/133692432