OK6410A 开发板 (三) 12 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 boot 详细解析1

发布者:EtherealGaze最新更新时间:2022-09-22 来源: csdn关键字:OK6410A  开发板  u-boot 手机看文章 扫描二维码
随时随地手机看文章

url : git@github.com:lisider/u-boot.git

branch : ok6410a

commit id : e63a4077ad3aea53107495b0b68b95e720fe6033

config : ok6410a_mini_defconfig

// 涉及的 .S .s .c 文件 有 223个


reset arch/arm/cpu/arm1176/start.S 39

lowlevel_init(108) board/samsung/ok6410a/lowlevel_init.S 72

_main(110) arch/arm/lib/crt0.S 91

board_init_f(117) common/board_f.c 954

initcall_run_list(init_sequence_f)(959) include/initcall.h 21

init_sequence_f common/board_f.c 818

board_init_r(177) common/board_r.c 901

initcall_run_list(init_sequence_r)(927) include/initcall.h 21

init_sequence_r common/board_f.c 695

run_main_loop(898) common/board_r.c 678

main_loop(685) common/main.c 39


解析概要

// 入口 为 arch/arm/lib/vectors.S 中的 _start 标号处的 b reset

reset

lowlevel_init

时钟

串口

ddr

_main

// 从代码运行起始位置0x5FB00000 往下 找 gd 和栈 的位置

bl board_init_f_alloc_reserve

// 设置栈

mov sp, r0

// 设置gd 

mov r9, r0

// 初始化gd

bl board_init_f_init_reserve 


bl board_init_f 

查找 设备树的地址

准备 early malloc

驱动模型的前期准备

定时器初始化,为delay做准备

env 初始化,为查找环境变量做准备

串口波特率环境变量的查找和串口波特率的设置,为printf做准备

从 ddr 顶端 0x5FFF FFFF 往下 找 空间

1. mmu

2. u-boot

3. malloc

4. new_gd

5. fdt

6. irq 栈

7. 栈

搬移 gd

搬移设备树(fdt)

// 搬移 u-boot 并 fixloop

b relocate_code


// 搬移向量表 到 0x0000 0000

bl relocate_vectors


CLEAR_BSS

// 清.bss 段 , 这是u-boot阶段第一次清, relocate 之前没有清过


ldr pc,=board_init_r


// 开 icache 和 dcache

initr_caches


// 为 full malloc 做准备

initr_malloc


// 驱动模型的后期准备

initr_dm


// 初始化 board ID

board_init


// 串口及控制台的初始化

stdio_init_tables

serial_initialize 

stdio_add_devices

console_init_r


// 其他设备的初始化

initr_mmc

initr_ethaddr

initr_net


// env 的后初始化

initr_env


// 跳转表???

// the jump table contains pointers to exported functions.

// A pointer to the jump table is passed to standalone applications.

// 也就是 说 导出 让 standalone 应用用的

// u-boot 命令行 可以 加载 bin 文件,并执行 这些bin文件就是 standalone applications

// 查看 doc/README.standalone

initr_jumptable


// 中断相关的初始化(开中断,相关变量)

interrupt_init


main_loop

bootcmd以及cmdline


详细解析


// common/init/board_init.c

// register volatile gd_t *gd asm ("r9");

// arch/arm/include/asm/global_data.h:112:#define DECLARE_GLOBAL_DATA_PTR          register volatile gd_t *gd asm ("r9")


reset // 运行在 5FB0 0000// sdram : 0x5000_0000 0x5FFF_FFFF

lowlevel_init

spl_config_uart_baudrate

ulong val = spl_uart_getclk(is_mpll) / 115200;

_UBRDIV = val / 16 - 1;

_UDIVSLOT = udivslot[val % 16];

mem_ctrl_asm_init

// ddr初始化

_main

board_init_f_alloc_reserve // 算出gd的地址为 0x5f9fff20

// 过程与数据和spl 完全一样

申请 struct global_data 个字节 用来存储 gd_t *gd 指向的 gd_t 结构体

// include/asm-generic/global_data.h 中 有 gd_t 的 定义

board_init_f_init_reserve // 根据 gd的地址 0x5f9fff20 算出结构体

// 过程与数据和spl 完全一样

初始化 gd_t *gd 指向的 gd_t 结构体 空间 为 0

初始化 gd_t *gd 指向的 gd_t 结构体 的 成员 malloc_base = 5F9F FFF0

// u-boot过程和 spl 过程用到的 gd 指针是同一个位置

// 但是 内容不同,因为在 初始化的时候,已经将 gd指针指向的位置全部 memset 0 了

// spl 加载 u-boot 的过程中, 就是 A加载B

// A 加载 B 可以 通过 寄存器 来传值

// 但是 spl 加载 u-boot 的过程中可以说没有传递任何值

// 虽然 都用r9 保存了 gd的指针值,但是 r9 是算出来的,不是 spl 传过来的.

/*

下面的这几行有两个目标

1. 设置sp

2. 存储gd指针变量并clear gd指针变量指向的空间,并设置 gd->malloc_base = 0x5f9f ff20;

ldr r0, =((0x5FB00000 - 0x0C)) => r0 : 5FAF FFF4

bic r0, r0, #7 => r0 : 5FAF FFF0

mov sp, r0 => sp : 5FAF FFF0

bl board_init_f_alloc_reserve => r0 : 5f9f ff20 (5FAF FFF0 - 0x10 0000 - 0xD0)

mov sp, r0 => sp : 5f9f ff20             ***** 设置了 栈指针

mov r9, r0 => r9 : 5f9f ff20   ***** 存储了 gd指针变量的值

bl board_init_f_init_reserve => 初始化 (5f9fff20 - 5f9fff20+0xD0) 的空间

*/


/*

// .code .rodata .data .bss .stack .heap

此时的内存分布

5FFF FFFF---------------------5FFF FFFF

5120KB(0x500000)大小,被512KB u-boot.bin占据 // 不管u-boot.bin有没有512KB,都会从mmc上拷贝512KB过来 // U-boot.bin实际大小 248K

内存中的u-boot.bin 中存在 .bss段,起始为5FB3 61F0,结束为5FB3 BAD4

内存中的u-boot.bin 也存在 .code .rodata .data

5FB0 0000---------------------

16B(0x10)大小,空洞

5FAF FFF0---------------------

1024KB(0x100000)大小,用于sys_malloc (.heap)

5F9F FFF0---------------------

208B(0xD0)大小,用于gd (很特殊的一个全局变量)

5F9F FF20---------------------

255999KB(约250MB)大小,用于栈 (.stack)

5000 0000---------------------5000 0000

*/





board_init_f // 被调用的时候传递的参数为 0 ,用来设置flags.

gd->flags = 0;

gd->have_console = 0;


setup_mon_len // 第一次使用栈,(sp) // 重要参考点1

gd->mon_len = (ulong)&__bss_end - (ulong)_start;

// = 0x3bc4c

// 为 reserve_uboot 做准备

fdtdec_setup // 为设备树的解析做准备

gd->fdt_blob = board_fdt_blob_setup();

return (ulong *)&_end;

gd->fdt_blob = map_sysmem (env_get_ulong("fdtcontroladdr", 16, (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);

// 解码fdtcontroladdr环境变量的值,16进制,如果为空则为gd->fdt_blob

fdtdec_prepare_fdt 

// 检查gd->fdt_blob为空,则报错

fdtdec_board_setup

// null

initf_malloc // 为 early malloc 做准备

// 用于 early malloc

// 此前 gd->malloc_base 已经被初始化为 5F9F FFF0 // base address of early malloc

gd->malloc_limit = 0x100000; // limit address of early malloc

gd->malloc_ptr = 0; // current address of early malloc

log_init

// null

initf_bootstage

bootstage_init(1)

// null

bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f")

show_boot_progress(id);

//null // TODO, 另一个路径大概率是 printf

setup_spl_handoff

// null

initf_console_record

// null

arch_cpu_init

// null

mach_cpu_init

// null

initf_dm // dm 架构(driver-model),比较复杂,后续有空更新专题 // 为 驱动和设备的注册做准备

bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f");

// null

dm_init_and_scan(1)

dm_init(0)

INIT_LIST_HEAD(&(((gd_t *)gd)->uclass_root));

list->next = list;

list->prev = list;

device_bind_by_name(0,0,&root_info, &(((gd_t *)gd)->dm_root)));

lists_driver_lookup_name(info->name);

device_bind_common(parent, drv, info->name, (void *)info->platdata, 0, ofnode_null(), platdata_size, devp);

(((gd_t *)gd)->dm_root)->node = offset_to_ofnode(0)

device_probe((((gd_t *)gd)->dm_root))

dm_scan_platdata(1)

lists_bind_drivers((((gd_t *)gd)->dm_root), 1)

dm_extended_scan_fdt(gd->fdt_blob, 1)

dm_scan_fdt(gd->fdt_blob,1)

dm_scan_fdt_node(gd->dm_root, blob, 0, 1);

for_each_node dm_scan_fdt_ofnode_path(blob, nodes[i], 1);

dm_scan_other(1)

// null

bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);

// null

arch_cpu_init_dm

// null

timer_init // 为 delay 做准备

// 设置 s3c6410的 硬件timer

gd->arch.timer_rate_hz = pre_freq/1;

gd->arch.timer_rate_hz *= 1000;

gd->arch.lastinc = timers->TCNTB4 = gd->arch.timer_rate_hz;

gd->arch.timer_reset_value = 0;

env_init

env_driver_lookup

env_get_location

return env_locations[prio] ; // ENVL_MMC

_env_driver_lookup

n_ents = xxx

in section .u_boot_list_2_env_driver ,根据 ENVL_MMC 找到对应的 驱动对应的结构体 struct env_driver

drv->init // drv 为找到的结构体 struct env_driver _u_boot_list_2_env_driver_2_mmc 中没有 init 成员

env_set_inited(drv->location)

gd->env_has_init |= (1UL << (location));

gd->env_addr = (ulong)&default_environment[0]; // 待研究

gd->env_valid = ENV_VALID;

init_baud_rate

gd->baudrate = env_get_ulong("baudrate", 10, 115200);

const char *str = env_get(name);

env_get_f

env_get_char

env_match

return str ? simple_strtoul(str,0,10) : default_val;

serial_init

serial_find_console_or_panic

serial_check_stdout

str = fdtdec_get_chosen_prop(blob, "stdout-path");

node = fdt_path_offset_namelen(blob, str, namelen);

lists_bind_fdt

device_probe(&dev)

gd->cur_serial_dev = dev;

gd->flags |= GD_FLG_SERIAL_READY;

serial_setbrg

gd->cur_serial_dev->driver->ops->setbrg(gd->cur_serial_dev, gd->baudrate)// s3c_serial_setbrg

s3c_serial_setbrg_internal((struct s3c64xx_uart * )CONFIG_DEBUG_UART_BASE, 0 /*CFG_SERIAL_ID*/,CONFIG_BAUDRATE);

u32 uclk = get_uart_clk(id)

s3c64xx_serial_baud(uart, uclk, baudrate);

uart->UBRDIV = uclk / baudrate / 16 - 1;

uart->UDIVSLOT = udivslot[val];

barrier(); // 内存顺序模型相关

console_init_f

gd->have_console = 1;

console_update_silent

// null

print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);

// null TODO

// PRE_CONSOLE_BUFFER

display_options // printf 可以使用 // 重要参考点2

display_options_get_banner(true, buf, sizeof(buf));

display_options_get_banner_priv

snprintf

printf("%s", buf);

display_text_info

bss_start = (ulong)&__bss_start;

bss_end = (ulong)&__bss_end;

text_base = 0x5FB00000;

checkcpu

// null

print_cpuinfo

printf("**    Updated for OK6410A Board        **rn");

show_board_info

model = fdt_getprop(gd->fdt_blob, 0, "model", ((void *)0));

printf("Model: %sn", model);

// 实际打印 为 Model: Samsung SMDK6410 based on S3C6410

// 打印的字符串为 arch/arm/dts/s3c64xx-ok6410a.dts 中的 model 节点的属性

checkboard

printf("Board:   OK6410An");

announce_dram_init

puts("DRAM:  ");

dram_init

gd->ram_size += SDRAM_BANK_SIZE; // = 0x1000 0000

setup_dest_addr

gd->ram_base = 0x50000000;

gd->ram_top = gd->ram_base + get_effective_memsize();

// get_effective_memsize: gd->ram_size

// = 0x6000 0000

gd->ram_top = board_get_usable_ram_top(gd->mon_len);

// = gd->ram_top 

// = 0x6000 0000

gd->relocaddr = gd->ram_top;

// = 0x6000 0000

reserve_round_4k

gd->relocaddr &= ~(4096 - 1);

// hex 后三位与0

// 0x6000 0000

arch_reserve_mmu

arm_reserve_mmu

gd->arch.tlb_size = (4096 * 4);

// 0x4000 16K

[1] [2]
关键字:OK6410A  开发板  u-boot 引用地址:OK6410A 开发板 (三) 12 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 boot 详细解析1

上一篇:OK6410A 开发板 (三) 13 u-boot-2021.01 boot 解析 SPL 镜像运行部分 boot 详细解析
下一篇:OK6410A 开发板 (三) 11 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 命令的执行

推荐阅读最新更新时间:2024-11-09 11:28

U-boot 在 mini2440-S3C2440 上的移植(2)
1.本文主要讲解U-boot 在 mini2440-S3C2440 上的移植,用到的版本为 U-boot-2009.11_tekkaman-master,下载地址: https://download.csdn.net/download/jinanhezhuang/20823342?spm=1001.2014.3001.5501 1.下载官方u-boot:下载地址: 2.用xftp软件将压缩包上传到ubuntu; 3.解压安装包;tar命令 4.建立开发板文件: 我们将在smdk2410基础上移植,为了不破坏原本的代码,在board目录下将smdk2410复制到board下新建的文件夹tekkaman中的mini2440中;将m
[单片机]
<font color='red'>U-boot</font> 在 mini2440-S3C2440 上的移植(2)
OK6410A 开发板 (八) 5 linux-5.11 OK6410A usb 移植
s3c6410 有两个USB实例(板子也都引出来了), 分别是 USB host 和 USB OTG , 这里说的是 usb host 代码 : https://github.com/lisider/linux/tree/ok6410a-linux-5.11 提交id : dc485e937e8bccc1fc01b5e6d9025bf83b2b6f83 defconfig : arch/arm/configs/ok6410A_sdboot_mini_net_lcd_x11_usb_defconfig CONFIG_USB_NET_DRIVERS=y CONFIG_USB_HID=y CONFIG_USB_OHCI_LI
[单片机]
<font color='red'>OK6410A</font> <font color='red'>开发板</font> (八) 5 linux-5.11 <font color='red'>OK6410A</font> usb 移植
mini2440 u-boot linux 内核启动,移植较新(Linux3.19)内核至mini2440开发板(一)
s3c24xx-nand s3c2440-nand: Tacls=1, 9ns Twrph0=3 29ns, Twrph1=2 19ns s3c24xx-nand s3c2440-nand: NAND soft ECC nand: device found, Manufacturer ID: 0xec, Chip ID: 0xda nand: Samsung NAND 256MiB 3,3V 8-bit nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 Creating 5 MTD partitions on nand : 0x000000
[单片机]
OK6410A 开发板 (八) 111 linux-5.11 OK6410A tmpfs 文件系统 CONFIG_SHMEM=y & CONFIG_TMPFS=n
公有部分 ▼ variables -shm_mnt ▼ functions -__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size, unsigned long flags, unsigned int i_flags) shmem_file_setup(const char *name, loff_t size, unsigned long flags) shmem_file_setup_with_mnt(struct vfsmount *mnt, const char *name, loff_t size, unsigne
[单片机]
使用u-boot_2016_01启动mini2440(一)启动代码
mini2440的soc用的是s3c2440,因为板子买回来烧写过NOR,而且NOR启动也过于简单,所以我主要记录下NAND启动。s3c2440的NAND启动原理,是硬件通过引脚判断NAND启动后,会搬运NAND从0地址开始的前4K内容到SRAM上,然后在SRAM上运行起来,这段4K的代码,必须至少要初始化DDR,并且搬运bootloader到DDR,才能运行接下来的代码。普通的arm bootloader的启动流程来看,board_init_f应该在relocate_code之前运行,用来计算将要搬运的目的地址和栈寄存器地址等等,但是因为board_init_f代码段太大,编译不进前4K,所以,网上通用的做法好像是先预设relo
[单片机]
OK6410A 开发板 (三) 9 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 bootcmd
url : git@github.com:lisider/u-boot.git branch : ok6410a commit id : e63a4077ad3aea53107495b0b68b95e720fe6033 config : ok6410a_mini_defconfig // 涉及的 .S .s .c 文件 有 223个 reset arch/arm/cpu/arm1176/start.S 39 lowlevel_init(108) board/samsung/ok6410a/lowlevel_init.S 72 _main(110) arch/arm/lib/crt0.
[单片机]
OK6410A 开发板 (二) 环境熟悉
这是开始移植最新(2021-3-1 18:49:35) u-boot kernel 和 busybox 到 ok6410a 上的 开端 资料包 OK6410-A-1G用户光盘(A)-20160812 链接:https://pan.baidu.com/s/1FqrI_UdiA6F2jAB__byoKQ 提取码:sk0p 复制这段内容后打开百度网盘手机App,操作更方便哦 其中有 核心板电路图 : 开发板底板封装、PCB、原理图文件 底板电路图 : 开发板底板封装、PCB、原理图文件 s3c6410数据手册 : S3C6410 datasheet.pdf s3c6410 boot 参考手册
[单片机]
<font color='red'>OK6410A</font> <font color='red'>开发板</font> (二) 环境熟悉
U-Boot-2011.06-rc2移植到mini2440开发板
一、移植环境 u-boot版本:u-boot-2011.06-rc2 Linux版本:Ubuntu 11.04 交叉编译工具:arm-linux-gcc-4.3.2(友善之臂) 开发板:友善之臂mimi2440 CPU:s3c2440 SDRAM:64MB Nor Flash:2MB Nand Flash:128MB 网卡:DM9000 二、准备工作 1、下载u-boot-2011.06-rc2,地址:http://www.linuxidc.com/Linux/2011-07/38897.htm 2、解压u-boot到工作路径。tar -xvjf u-boot-2011.06-rc2.tar.bz2 /home/prince/wo
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved