• u-boot简单学习笔记(三)——AR9331 uboot启动分析


    1.最开始系统上电后 ENTRY(_start)程序入口点是 _start  由board/ap121/u-boot.lds引导

    2._start: cpu/mips/start.S 是第一个源程序文件,主要完成初始化看门狗、定时器、重定位(拷贝代码段到内存中)、初始化堆  栈、  跳转到第二阶段等工作。

    3. la t9, board_init_f 将函数board_init_f地址赋予t9
    j t9 跳转到t9寄存器中保存的地址指向的指令
    即跳转到RAM 中执行 C 代码
    这里会打印一些信息。

    3.1 board_init_f() lib_mips/board.c
    初始化外部内存
    relocate_code() 回到cpu/mips/start.S中继续执行

    4.la t9,board_init_r cpu/mips/start.S
    j t9 将函数board_init_r地址赋予t9
    跳转到t9寄存器中保存的地址指向的指令
    即跳转到RAM 中执行 C 代码
    这里会打印一些信息
    4.1 board_init_r() 函数 lib_mips/board.c

    4.2 main_loop() common/main.c
    s=getenv ("bootcmd") 取得环境变量中的启动命令行,如bootcmd=bootm 0xbf020000
    run_command (s, 0); //执行这个命令行 ,即bootm
    4.3 do_bootm() common/cmd_bootm.c
    // printf ("## Booting image at %08lx .../n", addr); //比如

    5. bootm 启动内核
    5.1 do_bootm_linux() lib_mips/mips_linux.c

    函数解析

    1.board_init_f()

    1.1

    1. void board_init_f(ulong bootflag)  
    2. {  
    3. for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)  
    4. { if ((*init_fnc_ptr)() != 0)  
    5. { hang (); }  
    6. }  
    7. //调用init_sequence 函数队列,对板子进行一些初始化,详细见后面
    8. 初始化external memory,初始化堆栈用cache作堆栈,为  
    9. relocate_code (addr_sp, id, addr); //回到cpu/mips/start.S 中
    10. /* NOTREACHED - relocate_code() does not return */

    1.2

    1. typedef int (init_fnc_t) (void);  
    2. init_fnc_t *init_sequence[] =  
    3. { clx_board_init, //初始化GPIO,CPU速度,PLL,SDRAM 等
    4. timer_init, //时钟初始化
    5. env_init, //环境变脸初始化
    6. incaip_set_cpuclk, //根据环境变量设置CPU 时钟
    7. init_baudrate, //初始化串口波特率
    8. serial_init, /* serial communications setup */
    9. console_init_f, //串口初始化,后面才能显示
    10. display_banner, //在屏幕上输出一些显示信息
    11. checkboard,  
    12. init_func_ram,  
    13. NULL,  
    14. }; 

    2.board_init_r()
    (1)调用一系列的初始化函数。
    (2)初始化Flash设备。
    (3)初始化系统内存分配函数。
    (4)如果目标系统拥有NAND设备,则初始化NAND设备。
    (5)如果目标系统有显示设备,则初始化该类设备。
    (6)初始化相关网络设备,填写IP、MAC地址等。
    (7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作

    1. void board_init_r (gd_t *id, ulong dest_addr)  
    2. {  
    3. /* configure available FLASH banks */ //配置可用的flash单元
    4. size = flash_init(); //初始化flash
    5. display_flash_config (size); //显示flash 的大小
    6. /* initialize malloc() area */
    7. mem_malloc_init();  
    8. malloc_bin_reloc();  
    9. puts ("NAND:");  
    10. nand_init(); /* go init the NAND */ //NAND初始化
    11. /* relocate environment function pointers etc. */
    12. env_relocate(); //初始化环境变量
    13. /* board MAC address */
    14. s = getenv ("ethaddr"); //以太网MAC地址
    15. for (i = 0; i < 6; ++i) {  
    16. bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;  
    17. if (s)  
    18. s = (*e) ? e + 1 : e;  
    19. }  
    20. /* IP Address */
    21. bd->bi_ip_addr = getenv_IPaddr("ipaddr");  
    22. pci_init(); //pci初始化配置
    23. /** leave this here (after malloc(), environment and PCI are working) **/
    24. /* Initialize devices */
    25. devices_init ();  
    26. jumptable_init ();  
    27. /* Initialize the console (after the relocation and devices init) */
    28. console_init_r (); //串口初始化
    29. /* miscellaneous platform dependent initialisations */
    30. misc_init_r ();  
    31. puts ("Net: ");  
    32. eth_initialize(gd->bd);  
    33. /* main_loop() can return to retry autoboot, if so just run it again. */
    34. for (;;) {  
    35. main_loop (); //循环执行,试图自动启动,接受用户从串口输入的命令,然后进行相应的工作,设置延时时间,确定目标板是进入下载模式还是启动加载模式
    36. }  
    37. /* NOTREACHED - no way out of command loop except booting */
    38. }  
    39. 3.main_loop()  
    40. void main_loop (void)  
    41. {  
    42. s = getenv ("bootdelay"); //从环境变量中取得bootdelay 内核等待延时
    43. bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;  
    44. debug ("### main_loop entered: bootdelay=%d/n/n", bootdelay);  
    45. s = getenv ("bootcmd"); //从环境变量中取得bootcmd 启动命令行
    46. 如bootcmd=tftp;bootm 或者 bootcmd=bootm 0xbf020000  
    47. char *s1 = getenv ("bootargs"); //从环境变量中取得bootargs 启动参数
    48. debug ("### main_loop: bootcmd=/"%s/"/n", s ? s : "<UNDEFINED>");  
    49. run_command (s, 0); //执行启动命令
    50. //手动输入命令
    51. for (;;) {  
    52. len = readline (CFG_PROMPT); //读取键入的命令到CFG_PROMPT 中
    53. rc = run_command (lastcommand, flag); //执行这个命令
    54. }  
    55. #endif /*CFG_HUSH_PARSER*/

    4.do_bootm()
    int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
    这个函数看着挺长的,其实无非就是将内核解压缩,然后调用do_bootm_linux引导内核

    5.do_bootm_linux() lib_mips/mips_linux.c
    打印信息Starting kernel ...

    1. void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],  
    2. ulong addr, ulong * len_ptr, int verify)  
    3. {  
    4. char *commandline = getenv ("bootargs");  
    5. theKernel =  
    6. (void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep);  
    7. //hdr为指向image header的指针,hdr->ih_ep就是我们用mkimage创建image时-e选项的参数:内核的入口地址
    8. linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline);  
    9. /* we assume that the kernel is in place */
    10. printf ("/nStarting kernel .../n/n");  
    11. theKernel (linux_argc, linux_argv, linux_env, 0); //启动内核

    u-boot向内核传递启动参数由一系列在include/configs/.h中的宏控制,启动参数传递的地址在board_init中初始化

  • 相关阅读:
    linux修改时间
    关于PGSQL连接问题
    windows与linux的文件路径
    node js 判断数组中是否包含某个值
    cmd设置utf8编码
    Spring异步请求处理
    Spring任务执行和任务调度
    Tomcat线程池配置
    Apache HttpClient和HttpAsyncClient应用
    FreeMarker导出复杂Excel
  • 原文地址:https://www.cnblogs.com/xuyh/p/5092252.html
Copyright © 2020-2023  润新知