• uboot启动流程-uboot内存分配


    一.  uboot启动流程

    _main 函数中会调用 board_init_f 函数,本文继续简单分析一下 board_init_f 函数。

    具体分析 board_init_f函数的第二部分:内存分配代码。

    本文继上一篇文章的学习,地址如下:

    uboot启动流程-涉及board_init_f 函数-CSDN博客

    二.  uboot内存分配

    下面具体分析 board_init_f 函数的后半部分:内存分配代码。

    board_init_f 函数里面有大量的条件编译代码,这里为了缩小篇幅,将条件编译部分删除掉了,去掉条件编译以后的board_init_f 函数 后半部分代码如下:

    1. 1 static init_fnc_t init_sequence_f[] = {
    2. 2 setup_mon_len,
    3. ......
    4. 32 /*
    5. 33 * Now that we have DRAM mapped and working, we can
    6. 34 * relocate the code and continue running from DRAM.
    7. 35 *
    8. 36 * Reserve memory at end of RAM for (top down in that order):
    9. 37 * - area that won't get touched by U-Boot and Linux (optional)
    10. 38 * - kernel log buffer
    11. 39 * - protected RAM
    12. 40 * - LCD framebuffer
    13. 41 * - monitor code
    14. 42 * - board info struct
    15. 43 */
    16. 44 setup_dest_addr,
    17. 45 reserve_round_4k,
    18. 46 reserve_mmu,
    19. 47 reserve_trace,
    20. 48 reserve_uboot,
    21. 49 reserve_malloc,
    22. 50 reserve_board,
    23. 51 setup_machine,
    24. 52 reserve_global_data,
    25. 53 reserve_fdt,
    26. 54 reserve_arch,
    27. 55 reserve_stacks,
    28. 56 setup_dram_config,
    29. 57 show_dram_config,
    30. 58 display_new_sp,
    31. 59 INIT_FUNC_WATCHDOG_RESET
    32. 60 reloc_fdt,
    33. 61 setup_reloc,
    34. 62 NULL,
    35. 63 };

    44 行, setup_dest_addr 函数,设置目的地址,设 gd->ram_size gd->ram_top gd->relocaddr
    这三个的值。 我可以修改 uboot 代码,直接将这些值通过串口打印出来,比如这里我们修改文件
    common/board_f.c ,因为 setup_dest_addr 函数定义在文件 common/board_f.c 中。

    setup_dest_addr 函数加入打印如下:

    1. printf("gd->ram_size: %#x\n", gd->ram_size);
    2. printf("gd->ram_top: %#x\n", gd->ram_top);
    3. printf("gd->relocaddr: %#x\n", gd->relocaddr);

    重新编译 uboot源码后,生成 u-boot.bin。将 u-boot.bin拷贝到 ubuntu的 tftp服务设置目录下。

    通过 tftp服务将 u-boot.bin下载到开发板。开发板uboot命令模式下输入如下:

    1. => tftp 0x87800000 u-boot.bin
    2. Using FEC1 device
    3. TFTP from server 192.168.1.66; our IP address is 192.168.1.50
    4. Filename 'u-boot.bin'.
    5. Load address: 0x87800000
    6. Loading: #################################
    7. 2.7 MiB/s
    8. done
    9. Bytes transferred = 476700 (7461c hex)

    运行下载到开发板的 DRAM的uboot。操作如下:

    1. => go 0x87800000
    2. ## Starting application at 0x87800000 ...
    3. U-Boot 2016.03 (Oct 02 2023 - 21:20:41 +0800)
    4. CPU: Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)
    5. CPU: Industrial temperature grade (-40C to 105C) at 44C
    6. Reset cause: unknown reset
    7. Board: MX6ULL ALIENTEK NAND
    8. I2C: ready
    9. DRAM: gd->ram_size: 0x10000000
    10. gd->ram_top: 0x90000000
    11. gd->relocaddr: 0x90000000
    12. 256 MiB
    13. ......

    可以看出, 这里三个参数:

    1. gd->ram_size = 0X10000000 //ram 大小为 0X10000000= 256 MB
    2. gd->ram_top = 0X90000000 //ram 最高地址为 0X80000000+0X10000000=0X90000000
    3. gd->relocaddr = 0X90000000 //重定位后最高地址为 0X90000000

    45 行 , reserve_round_4k 函数用于对 gd->relocaddr 4KB 对 齐 , 因 为gd->relocaddr=0XA0000000 ,已经是 4K 对齐了,所以调整后不变。

    46 行, reserve_mmu 函数,留出 MMU TLB 表的位置,分配 MMU TLB 表内存以后,会对 gd->relocaddr 64K 字节对齐。完成以后, gd->arch.tlb_size gd->arch.tlb_addr gd->relocaddr如下所示:
    1. DRAM: gd->arch.tlb_size: 0x4000 //MMU 的 TLB 表大小
    2. gd->arch.tlb_addr: 0x8fff0000 //MMU 的 TLB 表起始地址,64KB 对齐以后
    3. gd->relocaddr: 0x8fff0000 //relocaddr 地址

    47 行,reserve_trace 函数,留出跟踪调试的内存,I.MX6ULL 没有用到!

    48 行, reserve_uboot 函数, 留出重定位后的 uboot 所占用的内存区域, uboot 所占用大小由gd->mon_len 所指定,留出 uboot 的空间以后还要对 gd->relocaddr 4K 字节对齐,并且重新设 gd->start_addr_sp ,打印如下:
     
    1. DRAM: gd->mon_len: 0xb7394
    2. gd->start_addr_sp: 0x8ff38000
    3. gd->relocaddr: 0x8ff38000

    49 行, reserve_malloc 函数,留出 malloc 区域,调整 gd->start_addr_sp 位置, malloc 区域由宏
    TOTAL_MALLOC_LEN 定义,打印如下:

    DRAM:  TOTAL_MALLOC_LEN:    0X1020000
    gd->start_addr_sp: 0X8EF18000      //0X8FF38000-16MB-4MB=0X8EF18000

    50 行, reserve_board 函数,留出板子 bd 所占的内存区, bd 是结构体 bd_t bd_t 大小为
    80 字节,打印如下:
    1. DRAM: gd->bd: 0X8EF17FB0
    2. gd->start_addr_sp: 0X8EF17FB0

    51 行, setup_machine 函数 ,设置机器 ID linux 启动的时候会和这个机器 ID 匹配,如果匹
    配的话 linux 就会启动正常。但是!! I.MX6ULL 不用这种方式了,这是以前老版本的 uboot
    linux 使用的,新版本使用设备树了,因此此函数无效。

    52 行, reserve_global_data 函数,保留出 gd_t 的内存区域, gd_t 结构体大小为 248B ,打印如下:
    1. DRAM: gd->new_gd : 0X8EF17EB8
    2. gd->start_addr_sp: 0X8EF17EB8

    53 行, reserve_fdt ,留出设备树相关的内存区域, I.MX6ULL uboot 没有用到,因此,此函数无效。
    54 行, reserve_arch 是个空函数。
    55 行, reserve_stacks ,留出栈空间,先对 gd->start_addr_sp 减去 16 ,然后做 16 字节对 齐。如果使能 IRQ 的话还要留出 IRQ 相应的内存,具体工作是由 arch/arm/lib/stack.c 文件中的 函数 arch_reserve_stacks 完成。arch_reserve_stacks 函数中 打印如下:
    gd->start_addr_sp: 0X8EF17E90

    代码执行到这里,uboot的内存分配已经分配完成了。

    下一篇文章对 uboot的内存分配工作进行总结。

  • 相关阅读:
    docker拉取镜像错误missing signature key
    RabbitMq-RabbitMq简介与七种工作模式
    负载均衡原理及算法
    controller-informer
    【Q-Learning】TD算法的一种
    PMP考试可以延缓考吗?解答来了!
    Android 更新图标
    Java web中,服务器运行不过来
    什么软件能识别软件?学会这几个软件就可以了
    (四) MdbCluster分布式内存数据库——业务消息处理
  • 原文地址:https://blog.csdn.net/wojiaxiaohuang2014/article/details/133498867