zoukankan      html  css  js  c++  java
  • buildroot构建项目(七)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之四

      设置完寄存器控制器后,则跳出cpu_init_crit,进入_main 函数。即进入crt0.S (archarmlib) 
      跟着代码流程慢慢走

    一、crt0.S

    1.1 第一步执行代码

     1     /* 预设堆栈指针为CONFIG_SYS_INIT_SP_ADDR */
     2     /* #define CONFIG_SYS_INIT_SP_ADDR    (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) */
     3     /* #define CONFIG_SYS_SDRAM_BASE    PHYS_SDRAM_1 */
     4     /* #define PHYS_SDRAM_1        0x30000000  SDRAM Bank #1  */
     5     /* #define GENERATED_GBL_DATA_SIZE 176 */
     6     /* CONFIG_SYS_INIT_SP_ADDR = 0x3000 0000 + 0x1000 - 176 */
     7     /* 这里是预设的堆栈地址,而不是最终的堆栈地址 */
     8     ldr    r0, =(CONFIG_SYS_INIT_SP_ADDR)  /* 0x3000 0f52*/
     9     bic    r0, r0, #7    /* 8字节对齐后为,0x3000 0f50 */
    10     mov    sp, r0      /* sp 指针指向 0x3000 0f50 */
    11     bl    board_init_f_alloc_reserve  /* 给 gd 分配内存大小, 通过 u-boot.dis 文件可知 gd 大小为168 */

      跳转到 board_init_f_alloc_reserve  中执行:

     1 /* 这个函数用于给global_data分配空间,在relocation之前调用
     2  * 传入的参数是顶部地址,但是不一定是要内存顶部的地址,可以自己进行规划
     3  */
     4 ulong board_init_f_alloc_reserve(ulong top)
     5 {
     6     /* Reserve early malloc arena */
     7     /* 先从顶部向下分配一块CONFIG_SYS_MALLOC_F_LEN大小的空间给early malloc使用 */
     8     /* 关于CONFIG_SYS_MALLOC_F_LEN可以参考README */
     9     /* 这块内存是用于在relocation前用于给malloc函数提供内存池。 */
    10 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
    11     top -= CONFIG_VAL(SYS_MALLOC_F_LEN);
    12 #endif
    13     /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
    14     /* 继续向下分配sizeof(struct global_data)大小的内存给global_data使用,向下16byte对齐 */
    15     /* 这时候得到的地址就是global_data的地址。 */
    16     top = rounddown(top-sizeof(struct global_data), 16);
    17 
    18     return top; /* 将top,也就是global_data的地址返回 */
    19 }

       设置完后,返回继续执行crt0.S中的代码:

    1     mov    sp, r0      /* 分配后的栈顶为 3000 0de0,16字节对其后为 3000 0de0 */
    2     /* set up gd here, outside any C code */
    3     mov    r9, r0
    4     bl    board_init_f_init_reserve   /* 启动前初始化完成 */

      进入 board_init_f_init_reserve 中执行:

     1 /* 这个函数用于对global_data区域进行初始化,也就是清空global_data区域 */
     2 /* 传入的参数就是global_data的基地址 */
     3 void board_init_f_init_reserve(ulong base)
     4 {
     5     struct global_data *gd_ptr;
     6 
     7     /*
     8      * clear GD entirely and set it up.
     9      * Use gd_ptr, as gd may not be properly set yet.
    10      */
    11 
    12     gd_ptr = (struct global_data *)base;
    13     /* zero the area, 先通过memset函数对global_data数据结构进行清零 */
    14     memset(gd_ptr, '', sizeof(*gd));
    15     /* set GD unless architecture did it already */
    16 #if !defined(CONFIG_ARM)
    17     arch_setup_gd(gd_ptr);
    18 #endif
    19     /* next alloc will be higher by one GD plus 16-byte alignment */
    20     /* global_data区域是16Byte对齐的,对齐后,后面的地址就是early malloc的内存池的地址 */
    21     /* 这里就获取了early malloc的内存池的地址,S3C2440中我们没有分配此内存池。*/
    22     /* roundup计算处来的大小为 176,基地址为 0x3000 0e90 */
    23     base += roundup(sizeof(struct global_data), 16);    
    24 
    25     /*
    26      * record early malloc arena start.
    27      * Use gd as it is now properly set for all architectures.
    28      */
    29 
    30 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
    31     /* go down one 'early malloc arena' */
    32     gd->malloc_base = base;
    33     /* next alloc will be higher by one 'early malloc arena' size */
    34     base += CONFIG_VAL(SYS_MALLOC_F_LEN);
    35 #endif
    36 }

      上面进行的初始化,只是临时的初始化,执行完后,跳出,继续在 crt0.S中执行

    1     mov    r0, #0      /* r0 清零 */
    2     bl    board_init_f    /* 启动前初始化完成 */

    1.2 执行  board_init_f

      进入 board_init_f  则正式进入了C语言部分的初始化:

     1 /* 启动前,板初始化,传入参数 boot_flags = 0 */
     2 void board_init_f(ulong boot_flags)
     3 {
     4     gd->flags = boot_flags;
     5     gd->have_console = 0;
     6 
     7     /* 初始化 函数 结构体数组链表 */
     8     if (initcall_run_list(init_sequence_f))
     9         hang();
    10 
    11 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && 
    12         !defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64)
    13     /* NOTREACHED - jump_to_copy() does not return */
    14     hang();
    15 #endif
    16 }

      整个代码就是在执行  init_sequence_f  中的函数

     1 static const init_fnc_t init_sequence_f[] = {
     2     setup_mon_len,  /* 获取 u-boot 的大小 */
     3     initf_malloc,       /* early malloc的大小,没有设置,为0 */ 
     4     initf_bootstage,    /* uses its own timer, so does not need DM */
     5     initf_console_record,   /* 直接返回0,没定义宏 */
     6 
     7 #if !defined(CONFIG_M68K)
     8     timer_init,        /* initialize timer,初始化PWM定时器 */
     9 #endif
    10     env_init,            /* initialize environment,环境变量初始化 */
    11     init_baud_rate,        /* initialze baudrate settings,串口波特率初始化115200 */
    12     serial_init,        /* serial communications setup,串口初始化 */
    13     console_init_f,        /* stage 1 init of console,阶段1初始化终端 */
    14     display_options,    /* say that we are here,打印缓存信息 */
    15     display_text_info,    /* show debugging info if required,打印u-boot 的大小 */
    16 
    17 #if defined(CONFIG_DISPLAY_CPUINFO)
    18     print_cpuinfo,        /* display cpu info (and speed),打印CPU信息 */
    19 #endif
    20 
    21 #if defined(CONFIG_DISPLAY_BOARDINFO)
    22     show_board_info,        /* 打印板信息*/
    23 #endif
    24     announce_dram_init,         /* DRAM打印初始化 */
    25     /* 给gd->bd中内存信息表赋值而已。 */
    26     /* gd->ram_size = PHYS_SDRAM_1_SIZE; */
    27     dram_init,        /* configure available RAM banks,DRAM初始化,RAM SIZE大小获取 64M */
    28     /*
    29      * Now that we have DRAM mapped and working, we can
    30      * relocate the code and continue running from DRAM.
    31      *
    32      * Reserve memory at end of RAM for (top down in that order):
    33      *  - area that won't get touched by U-Boot and Linux (optional)
    34      *  - kernel log buffer
    35      *  - protected RAM
    36      *  - LCD framebuffer
    37      *  - monitor code
    38      *  - board info struct
    39      */
    40     setup_dest_addr,    /* 设置重定向的地址为 0x3400 0000 */
    41     reserve_round_4k,   /* 4字节对齐后为 0x3400 0000 */
    42 #ifdef CONFIG_ARM
    43     reserve_mmu,        /* 直接返回0,其中的宏未定义 */
    44 #endif
    45     reserve_video,      /* 直接返回0,其中的宏未定义 */
    46     reserve_trace,      /* 直接返回0,其中的宏未定义 */
    47     reserve_uboot,      /* 保留 u-boot 区域,u-boot 的启动地址为当前减去u-boot大小后的地址 */
    48     reserve_malloc,     /* 分配堆区大小 为 4M */
    49     reserve_board,      /* bd-t 结构体大小 */
    50     setup_machine,      /* 直接返回0,其中的宏未定义 */
    51     reserve_global_data,/* gd-t 结构体大小 */
    52     reserve_fdt,        /* fdt 大小 栈在此处*/
    53     reserve_bootstage,  /* 直接返回0,其中的宏未定义 */
    54     reserve_arch,       /* 直接返回0,其中的宏未定义 */
    55     reserve_stacks,     /* 直接返回0,其中的宏未定义 */
    56     dram_init_banksize, /* banksize 大小设定 */ 
    57     show_dram_config,   /* dram 配置 */
    58     display_new_sp,     /* 打印当前栈位置 */
    59     reloc_fdt,          /* 设置 gd->fdt_blob */
    60     reloc_bootstage,    /* 直接返回0,其中的宏未定义 */
    61     setup_reloc,        /* 设置 gd->reloc_off为 0x3400 0000 */
    62     NULL,
    63 };

    1.2.1 setup_mon_len

     1 /* #define CONFIG_SYS_MONITOR_LEN    (448 * 1024) */
     2 /* #define CONFIG_SYS_MONITOR_BASE    CONFIG_SYS_FLASH_BASE */
     3 /* #define CONFIG_SYS_FLASH_BASE    PHYS_FLASH_1 */
     4 /* #define PHYS_FLASH_1        0x00000000 /* Flash Bank #0 */ */
     5 static int setup_mon_len(void)
     6 {
     7     /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */
     8     /* 设置gd->mon_len 为编译出来的 u-boot.bin+bss 段的大小 */
     9     gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
    10     return 0;
    11 }

    1.2.2 timer_init

     1 /* PWM定时器设置 */
     2 int timer_init(void)
     3 {
     4     /* 获取定时器的基地址 */
     5     struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
     6     ulong tmr;
     7 
     8     /* use PWM Timer 4 because it has no output */
     9     /* prescaler for Timer 4 is 16 */
    10     writel(0x0f00, &timers->tcfg0); /* 启动定时器4 */
    11     if (gd->arch.tbu == 0) {
    12         /*
    13          * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
    14          * (default) and prescaler = 16. Should be 10390
    15          * @33.25MHz and 15625 @ 50 MHz
    16          */
    17         gd->arch.tbu = get_PCLK() / (2 * 16 * 100);
    18         gd->arch.timer_rate_hz = get_PCLK() / (2 * 16);
    19     }
    20     /* load value for 10 ms timeout */
    21     writel(gd->arch.tbu, &timers->tcntb4);
    22     /* auto load, manual update of timer 4 */
    23     tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
    24     writel(tmr, &timers->tcon);
    25     /* auto load, start timer 4 */
    26     tmr = (tmr & ~0x0700000) | 0x0500000;
    27     writel(tmr, &timers->tcon);
    28     gd->arch.lastinc = 0;
    29     gd->arch.tbl = 0;
    30 
    31     return 0;
    32 }

    1.2.3 setup_dest_addr

      /* 设置重定向的地址为 0x3400 0000 */

     1 static int setup_dest_addr(void)
     2 {
     3 #ifdef CONFIG_SYS_SDRAM_BASE
     4     gd->ram_top = CONFIG_SYS_SDRAM_BASE;    /* SDRAM 基地址 0x3000 0000,栈顶此时在此处 */
     5 #endif
     6     gd->ram_top += get_effective_memsize(); /* SDRAM 栈顶为 0x3400 0000 = 0x3000 000 + 400 0000 */
     7     gd->ram_top = board_get_usable_ram_top(gd->mon_len);    /* SDRAM 栈顶为 0x3400 0000 */
     8     gd->relocaddr = gd->ram_top;            /* 重定向的地址为 0x3400 0000 */
     9     return 0;
    10 }

    1.2.4 reserve_uboot

      保留 u-boot 区域,u-boot 的启动地址为当前减去u-boot大小后的地址

     1 static int reserve_uboot(void)
     2 {
     3     /*
     4      * reserve memory for U-Boot code, data & bss
     5      * round down to next 4 kB limit
     6      */
     7     gd->relocaddr -= gd->mon_len;   /* 减去 u-boot 大小 */
     8     gd->relocaddr &= ~(4096 - 1);    /* gd->relocaddr 地址在u-boot的起始地址 */
     9     gd->start_addr_sp = gd->relocaddr; /* 栈地址为当前减去u-boot大小后的地址 */
    10 
    11     return 0;
    12 }

    1.2.5 reserve_malloc

     1 /* reserve memory for malloc() area */
     2 /* malloc大小 */
     3 static int reserve_malloc(void)
     4 {
     5     /* #define CONFIG_SYS_MALLOC_LEN    (4 * 1024 * 1024) 40 0000*/
     6     gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;
     7     debug("Reserving %dk for malloc() at: %08lx
    ",
     8             TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp);
     9     return 0;
    10 }

    1.2.6 reserve_board

      给 gd->bd  分配大小

     1 static int reserve_board(void)
     2 {
     3     if (!gd->bd) {
     4         gd->start_addr_sp -= sizeof(bd_t);
     5         gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t));
     6         memset(gd->bd, '', sizeof(bd_t));
     7         debug("Reserving %zu Bytes for Board Info at: %08lx
    ",
     8               sizeof(bd_t), gd->start_addr_sp);
     9     }
    10     return 0;
    11 }

    1.2.7 reserve_global_data

      gd大小分配,gd在bd的下方

    1 static int reserve_global_data(void)
    2 {
    3     gd->start_addr_sp -= sizeof(gd_t);
    4     gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
    5     debug("Reserving %zu Bytes for Global Data at: %08lx
    ",
    6             sizeof(gd_t), gd->start_addr_sp);
    7     return 0;
    8 }

    1.2.8 reserve_fdt

      fdt大小分配

     1 static int reserve_fdt(void)
     2 {
     3 #ifndef CONFIG_OF_EMBED
     4     /*
     5      * If the device tree is sitting immediately above our image then we
     6      * must relocate it. If it is embedded in the data section, then it
     7      * will be relocated with other data.
     8      */
     9     if (gd->fdt_blob) {
    10         gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
    11 
    12         gd->start_addr_sp -= gd->fdt_size;
    13         /* gd->new_fdt 指向当前栈地址 */
    14         gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
    15         debug("Reserving %lu Bytes for FDT at: %08lx
    ",
    16               gd->fdt_size, gd->start_addr_sp);
    17     }
    18 #endif
    19 
    20     return 0;
    21 }

    1.2.9 dram_init_banksize

      设置DRAM

     1 /* 设置物理地址 bank,这里只设置了SDRAM的bank */
     2 __weak int dram_init_banksize(void)
     3 {
     4 /* #define CONFIG_NR_DRAM_BANKS    1  */
     5 /* #define CONFIG_SYS_SDRAM_BASE    PHYS_SDRAM_1 0x3000 0000 */
     6 #if defined(CONFIG_NR_DRAM_BANKS) && defined(CONFIG_SYS_SDRAM_BASE)
     7     gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
     8     gd->bd->bi_dram[0].size = get_effective_memsize();
     9 #endif
    10 
    11     return 0;
    12 }

    1.2.10 setup_reloc

     1 static int setup_reloc(void)
     2 {
     3     if (gd->flags & GD_FLG_SKIP_RELOC) {
     4         debug("Skipping relocation due to flag
    ");
     5         return 0;
     6     }
     7 
     8 /* #define CONFIG_SYS_TEXT_BASE    0x0 */
     9 #ifdef CONFIG_SYS_TEXT_BASE
    10     /* gd->relocaddr 为 0x3400 0000 - u-boot 大小,即在u-boot的起始地址处 */
    11     gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;
    12 #endif
    13     memcpy(gd->new_gd, (char *)gd, sizeof(gd_t));
    14 
    15     return 0;
    16 }
  • 相关阅读:
    使用Hibernate实现简单的增、改、删、查操作
    Hibernate 配置
    Win7/8下Oracle的安装
    Android从相册获取图片
    Android图片缓存分析(一)
    TextView淡入淡出效果
    Android动画全解
    ListView的getChildAt(i)方法
    AIDL小记
    自定义SeekBar的Thumb不对齐的解决方法。
  • 原文地址:https://www.cnblogs.com/kele-dad/p/8331362.html
Copyright © 2011-2022 走看看