buildroot构建项目(七)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之四
设置完寄存器控制器后,则跳出cpu_init_crit,进入_main 函数。即进入crt0.S (arch\arm\lib)
跟着代码流程慢慢走
一、crt0.S
1.1 第一步执行代码
/* 预设堆栈指针为CONFIG_SYS_INIT_SP_ADDR */
/* #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) */
/* #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 */
/* #define PHYS_SDRAM_1 0x30000000 SDRAM Bank #1 */
/* #define GENERATED_GBL_DATA_SIZE 176 */
/* CONFIG_SYS_INIT_SP_ADDR = 0x3000 0000 + 0x1000 - 176 */
/* 这里是预设的堆栈地址,而不是最终的堆栈地址 */
ldr r0, =(CONFIG_SYS_INIT_SP_ADDR) /* 0x3000 0f52*/
bic r0, r0, # /* 8字节对齐后为,0x3000 0f50 */
mov sp, r0 /* sp 指针指向 0x3000 0f50 */
bl board_init_f_alloc_reserve /* 给 gd 分配内存大小, 通过 u-boot.dis 文件可知 gd 大小为168 */
跳转到 board_init_f_alloc_reserve 中执行:
/* 这个函数用于给global_data分配空间,在relocation之前调用
* 传入的参数是顶部地址,但是不一定是要内存顶部的地址,可以自己进行规划
*/
ulong board_init_f_alloc_reserve(ulong top)
{
/* Reserve early malloc arena */
/* 先从顶部向下分配一块CONFIG_SYS_MALLOC_F_LEN大小的空间给early malloc使用 */
/* 关于CONFIG_SYS_MALLOC_F_LEN可以参考README */
/* 这块内存是用于在relocation前用于给malloc函数提供内存池。 */
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
top -= CONFIG_VAL(SYS_MALLOC_F_LEN);
#endif
/* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
/* 继续向下分配sizeof(struct global_data)大小的内存给global_data使用,向下16byte对齐 */
/* 这时候得到的地址就是global_data的地址。 */
top = rounddown(top-sizeof(struct global_data), ); return top; /* 将top,也就是global_data的地址返回 */
}
设置完后,返回继续执行crt0.S中的代码:
mov sp, r0 /* 分配后的栈顶为 3000 0de0,16字节对其后为 3000 0de0 */
/* set up gd here, outside any C code */
mov r9, r0
bl board_init_f_init_reserve /* 启动前初始化完成 */
进入 board_init_f_init_reserve 中执行:
/* 这个函数用于对global_data区域进行初始化,也就是清空global_data区域 */
/* 传入的参数就是global_data的基地址 */
void board_init_f_init_reserve(ulong base)
{
struct global_data *gd_ptr; /*
* clear GD entirely and set it up.
* Use gd_ptr, as gd may not be properly set yet.
*/ gd_ptr = (struct global_data *)base;
/* zero the area, 先通过memset函数对global_data数据结构进行清零 */
memset(gd_ptr, '\0', sizeof(*gd));
/* set GD unless architecture did it already */
#if !defined(CONFIG_ARM)
arch_setup_gd(gd_ptr);
#endif
/* next alloc will be higher by one GD plus 16-byte alignment */
/* global_data区域是16Byte对齐的,对齐后,后面的地址就是early malloc的内存池的地址 */
/* 这里就获取了early malloc的内存池的地址,S3C2440中我们没有分配此内存池。*/
/* roundup计算处来的大小为 176,基地址为 0x3000 0e90 */
base += roundup(sizeof(struct global_data), ); /*
* record early malloc arena start.
* Use gd as it is now properly set for all architectures.
*/ #if CONFIG_VAL(SYS_MALLOC_F_LEN)
/* go down one 'early malloc arena' */
gd->malloc_base = base;
/* next alloc will be higher by one 'early malloc arena' size */
base += CONFIG_VAL(SYS_MALLOC_F_LEN);
#endif
}
上面进行的初始化,只是临时的初始化,执行完后,跳出,继续在 crt0.S中执行
mov r0, # /* r0 清零 */
bl board_init_f /* 启动前初始化完成 */
1.2 执行 board_init_f
进入 board_init_f 则正式进入了C语言部分的初始化:
/* 启动前,板初始化,传入参数 boot_flags = 0 */
void board_init_f(ulong boot_flags)
{
gd->flags = boot_flags;
gd->have_console = ; /* 初始化 函数 结构体数组链表 */
if (initcall_run_list(init_sequence_f))
hang(); #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64)
/* NOTREACHED - jump_to_copy() does not return */
hang();
#endif
}
整个代码就是在执行 init_sequence_f 中的函数
static const init_fnc_t init_sequence_f[] = {
setup_mon_len, /* 获取 u-boot 的大小 */
initf_malloc, /* early malloc的大小,没有设置,为0 */
initf_bootstage, /* uses its own timer, so does not need DM */
initf_console_record, /* 直接返回0,没定义宏 */
#if !defined(CONFIG_M68K)
timer_init, /* initialize timer,初始化PWM定时器 */
#endif
env_init, /* initialize environment,环境变量初始化 */
init_baud_rate, /* initialze baudrate settings,串口波特率初始化115200 */
serial_init, /* serial communications setup,串口初始化 */
console_init_f, /* stage 1 init of console,阶段1初始化终端 */
display_options, /* say that we are here,打印缓存信息 */
display_text_info, /* show debugging info if required,打印u-boot 的大小 */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed),打印CPU信息 */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
show_board_info, /* 打印板信息*/
#endif
announce_dram_init, /* DRAM打印初始化 */
/* 给gd->bd中内存信息表赋值而已。 */
/* gd->ram_size = PHYS_SDRAM_1_SIZE; */
dram_init, /* configure available RAM banks,DRAM初始化,RAM SIZE大小获取 64M */
/*
* Now that we have DRAM mapped and working, we can
* relocate the code and continue running from DRAM.
*
* Reserve memory at end of RAM for (top down in that order):
* - area that won't get touched by U-Boot and Linux (optional)
* - kernel log buffer
* - protected RAM
* - LCD framebuffer
* - monitor code
* - board info struct
*/
setup_dest_addr, /* 设置重定向的地址为 0x3400 0000 */
reserve_round_4k, /* 4字节对齐后为 0x3400 0000 */
#ifdef CONFIG_ARM
reserve_mmu, /* 直接返回0,其中的宏未定义 */
#endif
reserve_video, /* 直接返回0,其中的宏未定义 */
reserve_trace, /* 直接返回0,其中的宏未定义 */
reserve_uboot, /* 保留 u-boot 区域,u-boot 的启动地址为当前减去u-boot大小后的地址 */
reserve_malloc, /* 分配堆区大小 为 4M */
reserve_board, /* bd-t 结构体大小 */
setup_machine, /* 直接返回0,其中的宏未定义 */
reserve_global_data,/* gd-t 结构体大小 */
reserve_fdt, /* fdt 大小 栈在此处*/
reserve_bootstage, /* 直接返回0,其中的宏未定义 */
reserve_arch, /* 直接返回0,其中的宏未定义 */
reserve_stacks, /* 直接返回0,其中的宏未定义 */
dram_init_banksize, /* banksize 大小设定 */
show_dram_config, /* dram 配置 */
display_new_sp, /* 打印当前栈位置 */
reloc_fdt, /* 设置 gd->fdt_blob */
reloc_bootstage, /* 直接返回0,其中的宏未定义 */
setup_reloc, /* 设置 gd->reloc_off为 0x3400 0000 */
NULL,
};
1.2.1 setup_mon_len
/* #define CONFIG_SYS_MONITOR_LEN (448 * 1024) */
/* #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE */
/* #define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 */
/* #define PHYS_FLASH_1 0x00000000 /* Flash Bank #0 */ */
static int setup_mon_len(void)
{
/* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */
/* 设置gd->mon_len 为编译出来的 u-boot.bin+bss 段的大小 */
gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
return ;
}
1.2.2 timer_init
/* PWM定时器设置 */
int timer_init(void)
{
/* 获取定时器的基地址 */
struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
ulong tmr; /* use PWM Timer 4 because it has no output */
/* prescaler for Timer 4 is 16 */
writel(0x0f00, &timers->tcfg0); /* 启动定时器4 */
if (gd->arch.tbu == ) {
/*
* for 10 ms clock period @ PCLK with 4 bit divider = 1/2
* (default) and prescaler = 16. Should be 10390
* @33.25MHz and 15625 @ 50 MHz
*/
gd->arch.tbu = get_PCLK() / ( * * );
gd->arch.timer_rate_hz = get_PCLK() / ( * );
}
/* load value for 10 ms timeout */
writel(gd->arch.tbu, &timers->tcntb4);
/* auto load, manual update of timer 4 */
tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
writel(tmr, &timers->tcon);
/* auto load, start timer 4 */
tmr = (tmr & ~0x0700000) | 0x0500000;
writel(tmr, &timers->tcon);
gd->arch.lastinc = ;
gd->arch.tbl = ; return ;
}
1.2.3 setup_dest_addr
/* 设置重定向的地址为 0x3400 0000 */
static int setup_dest_addr(void)
{
#ifdef CONFIG_SYS_SDRAM_BASE
gd->ram_top = CONFIG_SYS_SDRAM_BASE; /* SDRAM 基地址 0x3000 0000,栈顶此时在此处 */
#endif
gd->ram_top += get_effective_memsize(); /* SDRAM 栈顶为 0x3400 0000 = 0x3000 000 + 400 0000 */
gd->ram_top = board_get_usable_ram_top(gd->mon_len); /* SDRAM 栈顶为 0x3400 0000 */
gd->relocaddr = gd->ram_top; /* 重定向的地址为 0x3400 0000 */
return ;
}
1.2.4 reserve_uboot
保留 u-boot 区域,u-boot 的启动地址为当前减去u-boot大小后的地址
static int reserve_uboot(void)
{
/*
* reserve memory for U-Boot code, data & bss
* round down to next 4 kB limit
*/
gd->relocaddr -= gd->mon_len; /* 减去 u-boot 大小 */
gd->relocaddr &= ~( - ); /* gd->relocaddr 地址在u-boot的起始地址 */
gd->start_addr_sp = gd->relocaddr; /* 栈地址为当前减去u-boot大小后的地址 */ return ;
}
1.2.5 reserve_malloc
/* reserve memory for malloc() area */
/* malloc大小 */
static int reserve_malloc(void)
{
/* #define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024) 40 0000*/
gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;
debug("Reserving %dk for malloc() at: %08lx\n",
TOTAL_MALLOC_LEN >> , gd->start_addr_sp);
return ;
}
1.2.6 reserve_board
给 gd->bd 分配大小
static int reserve_board(void)
{
if (!gd->bd) {
gd->start_addr_sp -= sizeof(bd_t);
gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t));
memset(gd->bd, '\0', sizeof(bd_t));
debug("Reserving %zu Bytes for Board Info at: %08lx\n",
sizeof(bd_t), gd->start_addr_sp);
}
return ;
}
1.2.7 reserve_global_data
gd大小分配,gd在bd的下方
static int reserve_global_data(void)
{
gd->start_addr_sp -= sizeof(gd_t);
gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
debug("Reserving %zu Bytes for Global Data at: %08lx\n",
sizeof(gd_t), gd->start_addr_sp);
return ;
}
1.2.8 reserve_fdt
fdt大小分配
static int reserve_fdt(void)
{
#ifndef CONFIG_OF_EMBED
/*
* If the device tree is sitting immediately above our image then we
* must relocate it. If it is embedded in the data section, then it
* will be relocated with other data.
*/
if (gd->fdt_blob) {
gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, ); gd->start_addr_sp -= gd->fdt_size;
/* gd->new_fdt 指向当前栈地址 */
gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
debug("Reserving %lu Bytes for FDT at: %08lx\n",
gd->fdt_size, gd->start_addr_sp);
}
#endif return ;
}
1.2.9 dram_init_banksize
设置DRAM
/* 设置物理地址 bank,这里只设置了SDRAM的bank */
__weak int dram_init_banksize(void)
{
/* #define CONFIG_NR_DRAM_BANKS 1 */
/* #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 0x3000 0000 */
#if defined(CONFIG_NR_DRAM_BANKS) && defined(CONFIG_SYS_SDRAM_BASE)
gd->bd->bi_dram[].start = CONFIG_SYS_SDRAM_BASE;
gd->bd->bi_dram[].size = get_effective_memsize();
#endif return ;
}
1.2.10 setup_reloc
static int setup_reloc(void)
{
if (gd->flags & GD_FLG_SKIP_RELOC) {
debug("Skipping relocation due to flag\n");
return ;
} /* #define CONFIG_SYS_TEXT_BASE 0x0 */
#ifdef CONFIG_SYS_TEXT_BASE
/* gd->relocaddr 为 0x3400 0000 - u-boot 大小,即在u-boot的起始地址处 */
gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;
#endif
memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); return ;
}
buildroot构建项目(七)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之四的更多相关文章
- buildroot构建项目(六)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之三
一.内存控制器 在关闭了MMU和caches 之后 就进入lowlevel_init 函数,对内存控制器进行初始化.lowlevel_init.S (board\samsung\mini2440) 1 ...
- buildroot构建项目(五)--- u-boot 2017.11 适配开发板修改 3 ---- 系统启动初始化之二
一.cpu_init_crit 当执行完时钟初始化后,程序执行: bl cpu_init_crit 跳转到CPU初始化处进行,在其中主要是执行 caches 的关闭 和 MMU的关闭,之后跳转到 ...
- buildroot构建项目(八)--- u-boot 2017.11 适配开发板修改 5 ---- 系统启动初始化之五
执行完 board_init_f 后,跳回到 crt0.S中继续执行汇编语言 ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp, ...
- buildroot构建项目(四)--- u-boot 2017.11 适配开发板修改 2 ---- 系统启动初始化之一
一.代码分析 上一节已经分析了链接文件,知道了首先代码是从 _start 开始,之后设置了中断向量表,然后从 start.s 开始运行. _start:vectors.S (arch\arm\lib) ...
- buildroot构建项目(三)--- u-boot 2017.11 适配开发板修改 1
当前虽然编译成功了,但是对于我们自己的目标板并不太适用.还得做一系列得修改. 一.lds 文件分析 u-boot 中最重要得链接文件即是,u-boot.lds.我们可以查看我们编译出来得 u-boot ...
- buildroot构建项目(二)--- u-boot 2017.11 建立 2440 开发板
一.准备工作 在建立之前,先需要将下载的u-boot 拷贝一份出来解压,在此工程下进行更改和创建.同时根据前面搜索到的 mini2440开发板所在的版本,下载一份u-boot 拷贝出 mini2440 ...
- buildroot构建项目(一)---buildroot介绍
1.1 什么是buildroot Buildroot是Linux平台上一个构建嵌入式Linux系统的框架.整个Buildroot是由Makefile脚本和Kconfig配置文件构成的.你可以和编译Li ...
- iTOP-IMX6UL 实战项目:ssh 服务器移植到 arm 开发板
实验环境:迅为提供的Ubuntu12.04.2 以及虚拟机 编译器:arm-2009q3 编译器 开发板系统:QT系统 开发板使用手册中给Windows 系统安装了 ssh 客户端,给 Ubunt ...
- 迅为iTOP-4412物联网开发板入门学习高手进阶项目开发超树莓派
免费视频教程: 为初学者精心录制的整套视频教程全部免费,随IT技术发展而不断增添的视频教程仍然免费!一支有经验的工程师团队会始终成为您的后盾. 项目实战---全开源: 手机远程控制开发板 门禁系统 W ...
随机推荐
- loadrunner基础学习笔记七-面向目标场景
部署应用程序之前,要执行验收测试以确保系统能够承担预期的实际工作量. 可以为想要生成的每秒点击次数,每秒事务数或事务响应时间设置目标 loadrunner将使用面向目标的场景自动生成所需的目标,当应用 ...
- 我是如何沉迷于linux系统的?
Linux?这个对大多数人来说,是一个陌生的词.曾经的我,对这个也是一无所知的,我没有编程背景,我的专业知识是英语,而不是计算机语言. 我是如何和这个词搭上联系的呢?还是缘于一段一次奇妙的社团活动,我 ...
- BZOJ2863[SHOI2012]魔法树——树链剖分+线段树
题目描述 输入 输出 样例输入 4 0 1 1 2 2 3 4 Add 1 3 1 Query 0 Query 1 Query 2 样例输出 3 3 2 树链剖分模板题,路径修改子树查询,注意节点 ...
- BZOJ3160 万径人踪灭(FFT+manacher)
容易想到先统计回文串数量,这样就去掉了不连续的限制,变为统计回文序列数量. 显然以某个位置为对称轴的回文序列数量就是2其两边(包括自身)对称相等的位置数量-1.对称有啥性质?位置和相等.这不就是卷积嘛 ...
- BZOJ5093 图的价值(NTT+斯特林数)
显然每个点会提供相同的贡献.于是现在只考虑1号点的贡献.若其度数为i,则在2~n号点选i个连上,剩下的边随便连,这样可以算出答案为 这个式子可以O(n)计算.发现k比较小,于是考虑如何将这个式子化为与 ...
- wordpress 页面显示指定分类文章
首页显示指定分类备份主题文件夹中的 index.php 文件,修改index.php找到如下一行代码:<?php if (have_posts()) : ?>在上面这行代码的前面加上:&l ...
- 自学Zabbix3.12.3-动作Action-自动发现action配置
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix3.12.3-动作Action-自动发现action配置 1. 首先先学习 Ne ...
- 自学Zabbix11.6 Zabbix SNMP自定义OID
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix11.6 Zabbix SNMP自定义OID 为什么要自定义OID? 前面已经讲过 ...
- Android 设置Activity样式 透明度
一.设置Activity透明度有几种方法:1>.在清单文件中配置Activity时声明android:theme="@android:style/Theme.Translucent&q ...
- 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)
[BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...