本文还是以u-boot-1.1.4为例,以make smdk2410_config命令配置源代码之后进行分析。
对于C语言部分代码的调用出现在cpu/arm920t/start.S的第223行:
[code]
ldr pc, _start_armboot
_start_armboot: .word start_armboot
[/code]
这里的start_armboot就是lib_arm/board.c中第207行的start_armboot()函数,由此U-Boot开始执行C语言部分的代码。
start_armboot()函数一开始首先是一个宏调用:
[code]
DECLARE_GLOBAL_DATA_PTR;
[/code]
这个宏的定义在include/asm-arm/global_data.h文件的第64行:
[code]
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
[/code]
大概的意思是声明一个指向gd_t结构体变量的指针gd,并固定使用寄存器r8来存放该指针。而对gd_t结构体的定义从上面的第36行开始:
[code]
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */
#ifdef CONFIG_VFD
unsigned char vfd_type; /* display type */
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
unsigned long ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table */
} gd_t;
[/code]
在lib_arm/board.c文件中之所以能够直接使用这个宏和gd_t结构体是因为包含了include/common.h头文件,在common.h的第115行包含了include/asm-arm/global_data.h头文件。
继续来看start_armboot()函数的执行。lib_arm/board.c第229行开始的一个for循环:
[code]
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
[/code]
这里的init_sequence是定义在上面第190行处的一个指针数组:
[code]
init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
dram_init, /* configure available RAM banks */
display_dram_config,
#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
checkboard,
#endif
NULL,
};
[/code]
数组类型init_fnc_t则是一个定义在第188行的函数指针类型:
[code]
typedef int (init_fnc_t) (void);
[/code]
由此可知,init_sequence[]数组当中的所有元素都是函数指针了,而这个for循环的作用就是遍历这个数组的所有元素,然后用“(*init_fnc_ptr)()”就依次调用了这些函数来进行初始化的工作。
书接上回,我们依次来看看init_sequence[]数组当中的各个元素。
首先是cpu_init()函数,定义于lib_arm/arm920t/cpu.c第88行。
接下来的board_init()函数定义于board/smdk2410/smdk2410.c第68行:
int board_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
/* some delay between MPLL and UPLL */
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
/* some delay between MPLL and UPLL */
delay (8000);
/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
|
interrupt_init()函数定义于cpu/arm920t/s3c24x0/interrupts.c第55行:
int interrupt_init (void)
{
S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
/* use PWM Timer 4 because it has no output */
/* prescaler for Timer 4 is 16 */
timers->TCFG0 = 0x0f00;
if (timer_load_val == 0)
{
/*
* 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
*/
timer_load_val = get_PCLK()/(2 * 16 * 100);
}
/* load value for 10 ms timeout */
lastdec = timers->TCNTB4 = timer_load_val;
/* auto load, manual update of Timer 4 */
timers->TCON = (timers->TCON & ~0x0700000) | 0x600000;
/* auto load, start Timer 4 */
timers->TCON = (timers->TCON & ~0x0700000) | 0x500000;
timestamp = 0;
return (0);
}
|
相关推荐
《U-Boot启动流程分析——深入理解ARM启动》 在嵌入式系统的世界里,U-Boot作为一款广泛应用的引导加载程序,对于系统的初始化和启动起着至关重要的作用。本文将详细探讨U-Boot在ARM架构下的启动流程,旨在帮助读者...
U-Boot启动流程分析: U-Boot是一种非常流行的开源Bootloader,广泛应用于嵌入式系统中,负责初始化硬件设备,建立内存空间的映射图,从而为操作系统的运行创造条件。U-Boot启动流程分为两个主要阶段:第一阶段和第...
基于PXA255的U-Boot启动分析及移植 U-Boot是一款功能强大、灵活性高的开放源码Bootloader,能够支持多种处理器架构和开发板。为了在PXA255目标板上移植U-Boot,需要详细了解U-Boot的启动流程和移植过程。 U-Boot的...
### U-BOOT启动过程分析 #### 一、概述 U-Boot(Universal Boot Loader)是一种广泛应用于嵌入式系统的引导加载程序,它支持多种处理器架构和操作系统。U-Boot的启动过程是理解整个嵌入式系统启动流程的关键所在。...
### U-Boot代码详细分析 #### 1. U-Boot简介 ##### 1.1 U-Boot的来源 U-Boot(Universal Boot Loader)是一种开源的Bootloader项目,旨在为不同架构的处理器提供通用的引导加载支持。U-Boot最初是由DENX软件工程...
### U-Boot启动过程详解 #### 一、U-Boot简介 U-Boot(Universal Boot Loader)是一款开源的通用引导加载程序,适用于多种处理器架构,包括但不限于ARM、PowerPC、x86等。U-Boot的主要功能是初始化硬件资源、加载...
U-Boot第一阶段的启动流程。(nandflash启动,把nand的4k代码考到sram中,因为nand没址线,不能映射到内存,所以通过sram进行过度,sram中4k代码把整个uboot拷贝到sdram上,初始化好堆栈,为c语言提供条件,进入uboot...
U-BOOT启动流程一般分为两个阶段:Stage 1和Stage 2。 - **Stage 1(start.s代码结构)** - 入口点定义:Bootloader通常从ROM(通常是Flash)的0x0地址开始执行。 - 异常向量设置:配置异常处理机制。 - CPU配置...
总结来说,U-Boot启动流程的分析涵盖了从硬件初始化到操作系统加载的全过程,理解这一流程对于嵌入式系统的开发和调试至关重要。通过对链接脚本、汇编代码和C代码的深入理解,我们可以更好地定制和优化U-Boot以适应...
总结起来,ARm处理器上的U-boot启动过程涉及了硬件初始化、设备检测、环境变量管理、操作系统加载等多个环节,是嵌入式系统和服务器启动流程中的重要组成部分。理解这个过程对于系统开发、调试和故障排查都至关重要...
### U-Boot启动过程完全分析 U-Boot是一款开源的嵌入式系统引导程序,广泛应用于各类嵌入式系统中,尤其是基于ARM架构的设备。它不仅能够引导各种操作系统,如Linux、FreeBSD等,还提供了丰富的命令行接口,允许...
#### 三、S3C2440上的u-boot启动过程分析 针对S3C2440平台,我们将详细介绍u-boot第一阶段的实现细节。 ##### 3.1 硬件初始化 硬件初始化部分主要包括以下步骤: - **设置异常向量**:通过修改程序计数器(PC)...
《庖丁解牛分析U-BOOT启动过程》 U-Boot作为嵌入式系统中广泛使用的引导加载程序,它的启动过程对于理解系统运作至关重要。本文将深入解析DM368平台下U-Boot的启动流程,帮助初学者掌握移植U-Boot的基础知识。 一...
### U-Boot启动过程分析 #### 一、概述 U-Boot(Universal Boot Loader)是一种广泛应用于嵌入式系统的引导加载程序,它支持多种处理器架构和操作系统。在启动过程中,U-Boot首先通过汇编语言完成CPU的初始化,...
一、U-Boot启动流程详解 1. 上电自检(POST):硬件初始化,包括CPU、内存、时钟等基本组件的检测。 2. 引导加载器加载:通常U-Boot程序位于设备的固件存储区,如ROM或闪存中。 3. 系统设置:配置CPU频率、内存参数...
在学习和修改xilinx u-boot源代码时,你需要有扎实的C语言基础,了解汇编语言和嵌入式系统原理。同时,对Xilinx的硬件平台和相关开发工具(如Vivado或SDK)的熟悉也是必不可少的。通过阅读源代码、理解其架构、调试...