• 二、uboot_源码分析


    一、uboot启动原理

    1、第一阶段初始化(汇编

    (1)关闭看门狗

    (2)初始化时钟

    (3)初始化SDRAM

    (4)设置堆栈

    (5)拷贝第二阶段代码

    2、第二阶段初始化(c语言)

    (1)实现读写flash

    (2)串口通信

    (3)网络通信

    (4)读取内核,引导内核

    二、源码分析

    1、第一阶段,硬件相关初始化(arch/arm/cpu/arm920t/start.S)

    1. 1、向量表
    2. .globl _start
    3. _start: b reset
    4. ldr pc, _undefined_instruction
    5. ldr pc, _software_interrupt
    6. ldr pc, _prefetch_abort
    7. ldr pc, _data_abort
    8. ldr pc, _not_used
    9. ldr pc, _irq
    10. ldr pc, _fiq
    11. 2、上电跳转reset启动
    12. 1)设置CPU为SVC32模式
    13. reset:
    14. /*
    15. * set the cpu to SVC32 mode
    16. */
    17. mrs r0,cpsr
    18. bic r0,r0,#0x1f
    19. orr r0,r0,#0xd3
    20. msr cpsr,r0
    21. 2)关闭看门狗
    22. /* turn off the watchdog */
    23. #if defined(CONFIG_S3C2400)
    24. # define pWTCON 0x15300000
    25. # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
    26. # define CLKDIVN 0x14800014 /* clock divisor register */
    27. #elif defined(CONFIG_S3C2410)
    28. # define pWTCON 0x53000000
    29. # define INTMOD 0X4A000004
    30. # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
    31. # define INTSUBMSK 0x4A00001C
    32. # define CLKDIVN 0x4C000014 /* clock divisor register */
    33. #endif
    34. #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    35. ldr r0, =pWTCON
    36. mov r1, #0x0
    37. str r1, [r0]
    38. 3)屏蔽所有中断
    39. /*
    40. * mask all IRQs by setting all bits in the INTMR - default
    41. */
    42. mov r1, #0xffffffff
    43. ldr r0, =INTMSK
    44. str r1, [r0]
    45. # if defined(CONFIG_S3C2410)
    46. ldr r1, =0x3ff
    47. ldr r0, =INTSUBMSK
    48. str r1, [r0]
    49. # endif
    50. 4)设置CPU相关设置(cpu_init_crit: 清除I/O caches,初始化存储管理器)
    51. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
    52. adr r0, _start /* r0 <- current position of code */
    53. ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
    54. cmp r0, r1 /* don't reloc during debug */
    55. blne cpu_init_crit
    56. #endif
    57. (5)设置栈
    58. /* Set up the stack */
    59. stack_setup:
    60. ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
    61. sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
    62. sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo
    63. #ifdef CONFIG_USE_IRQ
    64. sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
    65. #endif
    66. sub sp, r0, #12 /* leave 3 words for abort-stack */
    67. (6)初始化时钟
    68. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
    69. bl clock_init
    70. #endif
    71. (7)重定位,将代码拷贝至内存(SDRAM)
    72. #ifndef CONFIG_SKIP_RELOCATE_UBOOT
    73. relocate: /* relocate U-Boot to RAM */
    74. adr r0, _start /* r0 <- current position of code */
    75. ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
    76. cmp r0, r1 /* don't reloc during debug */
    77. beq clear_bss
    78. ldr r2, _armboot_start
    79. ldr r3, _bss_start
    80. sub r2, r3, r2 /* r2 <- size of armboot */
    81. #if 1
    82. bl CopyCode2Ram /* r0: source, r1: dest, r2: size */
    83. #else
    84. add r2, r0, r2 /* r2 <- source end address */
    85. copy_loop:
    86. ldmia r0!, {r3-r10} /* copy from source address [r0] */
    87. stmia r1!, {r3-r10} /* copy to target address [r1] */
    88. cmp r0, r2 /* until source end addreee [r2] */
    89. ble copy_loop
    90. #endif
    91. #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
    92. 8)清除bss段
    93. clear_bss:
    94. ldr r0, _bss_start /* find start of bss segment */
    95. ldr r1, _bss_end /* stop here */
    96. mov r2, #0x00000000 /* clear
    97. clbss_l:str r2, [r0] /* clear loop... */
    98. add r0, r0, #4
    99. cmp r0, r1
    100. ble clbss_l
    101. 9)跳转至第二阶段
    102. ldr pc, _start_armboot
    103. _start_armboot: .word start_armboot

    2、第二阶段,c语言程序(lib_arm/board.c)

    (1)lib_arm/board.c

    1. 1、设置运行环境
    2. /* Pointer is writable since we allocated a register for it */
    3. gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
    4. /* compiler optimization barrier needed for GCC >= 3.4 */
    5. __asm__ __volatile__("": : :"memory");
    6. memset ((void*)gd, 0, sizeof (gd_t));
    7. gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
    8. memset (gd->bd, 0, sizeof (bd_t));
    9. typedef struct global_data {
    10. bd_t *bd;
    11. unsigned long flags;
    12. unsigned long board_type;
    13. unsigned long baudrate;
    14. unsigned long have_console; /* serial_init() was called */
    15. unsigned long ram_size; /* RAM size */
    16. unsigned long reloc_off; /* Relocation Offset */
    17. unsigned long env_addr; /* Address of Environment struct */
    18. unsigned long env_valid; /* Checksum of Environment valid? */
    19. void **jt; /* jump table */
    20. } gd_t;
    21. 2)进一步初始化硬件
    22. monitor_flash_len = _bss_start - _armboot_start;
    23. for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
    24. if ((*init_fnc_ptr)() != 0) {
    25. hang ();
    26. }
    27. }
    28. init_fnc_t *init_sequence[] = {
    29. cpu_init, /* basic cpu dependent setup */
    30. board_init, /* basic board dependent setup */
    31. dram_init, /* configure available RAM banks */
    32. mem_malloc_init, /* dependant on dram_init */
    33. interrupt_init, /* set up exceptions */
    34. timer_init,
    35. serial_init,
    36. env_init, /* initialize environment */
    37. init_baudrate, /* initialze baudrate settings */
    38. serial_init, /* serial communications setup */
    39. display_banner,
    40. display_dram_config,
    41. NULL,
    42. };
    43. int board_init (void) // board/mini2440/mini2440.c
    44. {
    45. S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
    46. S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
    47. /* set up the I/O ports */
    48. gpio->GPACON = 0x007FFFFF;
    49. gpio->GPBCON = 0x00044555;
    50. gpio->GPBUP = 0x000007FF;
    51. gpio->GPCCON = 0xAAAAAAAA;
    52. gpio->GPCUP = 0x0000FFFF;
    53. gpio->GPDCON = 0xAAAAAAAA;
    54. gpio->GPDUP = 0x0000FFFF;
    55. gpio->GPECON = 0xAAAAAAAA;
    56. gpio->GPEUP = 0x0000FFFF;
    57. gpio->GPFCON = 0x000055AA;
    58. gpio->GPFUP = 0x000000FF;
    59. gpio->GPGCON = 0xFF95FFBA;
    60. gpio->GPGUP = 0x0000FFFF;
    61. gpio->GPHCON = 0x002AFAAA;
    62. gpio->GPHUP = 0x000007FF;
    63. /* support both of S3C2410 and S3C2440, by www.arm9.net */
    64. if ((gpio->GSTATUS1 == 0x32410000) || (gpio->GSTATUS1 == 0x32410002))
    65. {
    66. /* arch number of SMDK2410-Board */
    67. gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
    68. }
    69. else
    70. {
    71. /* arch number of SMDK2440-Board */
    72. gd->bd->bi_arch_number = MACH_TYPE_S3C2440; //机器ID,内核启动时会使用
    73. }
    74. /* adress of boot parameters */
    75. gd->bd->bi_boot_params = 0x30000100;
    76. icache_enable();
    77. #if 0
    78. dcache_enable();
    79. #endif
    80. return 0;
    81. }
    82. 3)环境变量初始化(uboot命令行的printenv)
    83. /* initialize environment */
    84. env_relocate ();
    85. 4)uboot主循环
    86. /* main_loop() can return to retry autoboot, if so just run it again. */
    87. for (;;) {
    88. main_loop ();
    89. }

    (2)common/main.c

    1. 1、获取bootcmd,如果没有命令则启动内核
    2. s = getenv ("bootcmd");
    3. debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "");
    4. if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
    5. # ifdef CONFIG_AUTOBOOT_KEYED
    6. int prev = disable_ctrlc(1); /* disable Control C checking */
    7. # endif
    8. # ifndef CFG_HUSH_PARSER
    9. #ifdef CONFIG_SURPORT_WINCE
    10. if (!TOC_Read())
    11. {
    12. /* Launch wince */
    13. char cmd_buf[16];
    14. printf("Booting wince ...\n");
    15. strcpy(cmd_buf, "wince");
    16. run_command(cmd_buf, 0);
    17. }
    18. else
    19. #endif
    20. {
    21. printf("Booting Linux ...\n");
    22. run_command (s, 0);
    23. }
    24. # else
    25. parse_string_outer(s, FLAG_PARSE_SEMICOLON |
    26. FLAG_EXIT_FROM_LOOP);
    27. # endif
    28. 2)获取命令行命令,执行命令
    29. for (;;) {
    30. #ifdef CONFIG_BOOT_RETRY_TIME
    31. if (rc >= 0) {
    32. /* Saw enough of a valid command to
    33. * restart the timeout.
    34. */
    35. reset_cmd_timeout();
    36. }
    37. #endif
    38. len = readline (CFG_PROMPT);
    39. flag = 0; /* assume no special flags for now */
    40. if (len > 0)
    41. strcpy (lastcommand, console_buffer);
    42. else if (len == 0)
    43. flag |= CMD_FLAG_REPEAT;
    44. #ifdef CONFIG_BOOT_RETRY_TIME
    45. else if (len == -2) {
    46. /* -2 means timed out, retry autoboot
    47. */
    48. puts ("\nTimed out waiting for command\n");
    49. # ifdef CONFIG_RESET_TO_RETRY
    50. /* Reinit board to run initialization code again */
    51. do_reset (NULL, 0, 0, NULL);
    52. # else
    53. return; /* retry autoboot */
    54. # endif
    55. }
    56. #endif
    57. if (len == -1)
    58. puts ("\n");
    59. else
    60. rc = run_command (lastcommand, flag);
    61. if (rc <= 0) {
    62. /* invalid command or not repeatable, forget it */
    63. lastcommand[0] = 0;
    64. }
    65. }

  • 相关阅读:
    svn服务器迁移包括日志
    c++ 后台小练习--基于Vue的在线记事本
    Java web应用性能分析之【jvisualvm远程连接云服务器】
    大厂竞相入局 Rust,性能、安全是关键,揭晓 2021 年 Rust 开发者调查报告
    C语言--数组的长度计算【详细解释】
    ubuntu从1804LTS升级至2004LTS
    二十四种设计模式与六大设计原则(三):【装饰模式、迭代器模式、组合模式、观察者模式、责任链模式、访问者模式】的定义、举例说明、核心思想、适用场景和优缺点
    王道3.2 队列
    【运维】docker如何删除所有容器
    基于Java实现的植物大战僵尸游戏
  • 原文地址:https://blog.csdn.net/liutit/article/details/127560805