Uboot分析

@lib_arm/board.c

start_armboot这个函数的功能是去执行一系列的函数进行底层硬件的初始化,最要中重要的初始化是进行内存的初始化。

u-boot 之 gd_t 和 bd_t 数据结构简介
bd_t :这个结构体是board info 的缩写 用来保存板子的信息
gd_t :这个结构体是global data的缩写,用来保存全局数据的信息
bd_t 和 gd_t 是 u-boot 中两个重要的数据结构,在初始化操作很多都要靠这两个数据结构来保存或传递。
bd_t在 include/asm-arm/u-boot.h 中定义
gd_t 在 include/asm-arm/global_data.h中定义
bd_t :board info 数据结构定义,主要是用来保存板子参数。

1、bd_t :board info数据结构定义,主要是用来保存板子参数。
typedef struct bd_info {
int bi_baudrate; /* serial console baudrate 串行终端波特率*/
unsigned long bi_ip_addr; /* IP Address IP地址 */
ulong bi_arch_number; /* unique id for this board 开发板ID 该变量标识每一种开发板相关的ID,该值将传递给内核,如果这个参数与内核配置的不相同,那么内核启动解压缩完成后将出现“Error:a”错误,开发板ID可以在内核arch/arm/tools/mach-types中查看*/

ulong bi_boot_params; /* where this board expects params u-boot传递给内核的参数的保存地址*/
struct /* RAM configuration 内存的起始地址及大小 */
{
ulong start;
ulong size;
} bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;

2、gd_t : global data数据结构定义,其成员主要是一些全局的系统初始化参数。当使用gd_t时需用宏定义进行声明:#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")指定占用寄存器R8,可避免编译器把r8分配给其它的变量。
typedef struct global_data {
bd_t *bd; //与板子相关的结构,同上
unsigned long flags; //指示标志,如设备已经初始化标志等
unsigned long baudrate; //串口波特率
unsigned long have_console; /* serial_init() was called */ //串口初始化标志
#ifdef CONFIG_PRE_CONSOLE_BUFFER //宏未定义
unsigned long precon_buf_idx; /* Pre-Console buffer index */
#endif
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 */ // frame buffer基址
#ifdef CONFIG_FSL_ESDHC //宏未在板子相关头文件中定义
unsigned long sdhc_clk;
#endif
#ifdef CONFIG_AT91FAMILY //宏未在板子相关头文件中定义
/* "static data" needed by at91's clock.c */
unsigned long cpu_clk_rate_hz;
unsigned long main_clk_rate_hz;
unsigned long mck_rate_hz;
unsigned long plla_rate_hz;
unsigned long pllb_rate_hz;
unsigned long at91_pllb_usb_init;
#endif
#ifdef CONFIG_ARM //宏未定义
/* "static data" needed by most of timer.c on ARM platforms */
unsigned long timer_rate_hz;
unsigned long tbl;
unsigned long tbu;
unsigned long long timer_reset_value;
unsigned long lastinc;
#endif
#ifdef CONFIG_IXP425 //宏未在板子相关头文件中定义
unsigned long timestamp;
#endif
unsigned long relocaddr; /* Start address of U-Boot in RAM */ //u-boot自搬移至内存后的起始地址
phys_size_t ram_size; /* RAM size */
unsigned long mon_len; /* monitor len */
unsigned long irq_sp; /* irq stack pointer */
unsigned long start_addr_sp; /* start_addr_stackpointer */
unsigned long reloc_off;
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) //宏未定义
unsigned long tlb_addr;
#endif
const void *fdt_blob; /* Our device tree, NULL if none */
void **jt; /* jump table */
char env_buf[32]; /* buffer for getenv() before reloc. */
#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) //宏未定义
unsigned long post_log_word; /* Record POST activities */
unsigned long post_log_res; /* success of POST test */
unsigned long post_init_f_time; /* When post_init_f started */
#endif
} gd_t;

/*

void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)// 这个条件不成立,下面的代码不执行
unsigned long addr;
#endif

/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");

memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));

gd->flags |= GD_FLG_RELOC;

monitor_flash_len = _bss_start - _armboot_start;

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
} @这是一个函数的初始化的循环,用循环函数去执行一系列函数
}

/* armboot_start is defined in the board-specific linker script */
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
CONFIG_SYS_MALLOC_LEN);//初始化malloc和env的内存
#ifndef CONFIG_SYS_NO_FLASH //条件不成立,接下来的代码不执行

@在include/configs/smdkc100.h中定义的宏为1 #define CONFIG_SYS_NO_FLASH 1
/* configure available FLASH banks */
display_flash_config (flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */

#ifdef CONFIG_VFD// //宏没有定义,接下来的代码不执行
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
/*
* reserve memory for VFD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD // 宏没有定义,下面的代码不执行
/* board init may have inited fb_base */
if (!gd->fb_base) {
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
/*
* reserve memory for LCD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
lcd_setmem (addr);
gd->fb_base = addr;
}
#endif /* CONFIG_LCD */

#if defined(CONFIG_CMD_NAND) //这个宏没有定义,条件不成立,后面的代码不执行
puts ("NAND: ");
nand_init(); /* go init the NAND */
#endif

#if defined(CONFIG_CMD_ONENAND) // 这个宏定义了,下面的代码能够执行
onenand_init();
#endif

#ifdef CONFIG_HAS_DATAFLASH// 宏没有定义,条件没有成立,下面的代码不能够执行
AT91F_DataflashInit();
dataflash_print_info();
#endif

/* initialize environment */
env_relocate ();

#ifdef CONFIG_VFD// 宏没有定义,条件没有成立,下面的代码不能够执行
/* must do this after the framebuffer is allocated */
drv_vfd_init();
#endif /* CONFIG_VFD */

#ifdef CONFIG_SERIAL_MULTI //这个宏定义了,下面的代码能够执行
serial_initialize();
#endif

/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

stdio_init (); /* get the devices list going. */

jumptable_init ();

#if defined(CONFIG_API)// 宏没有定义,条件不成立
/* Initialize API */
api_init ();
#endif

console_init_r (); /* fully init console as a device */

#if defined(CONFIG_ARCH_MISC_INIT)// 条件不成立,下面的代码不执行
/* miscellaneous arch dependent initialisations */
arch_misc_init ();
#endif
#if defined(CONFIG_MISC_INIT_R)// 条件不成立,下面的代码不成立
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif

/* enable exceptions */
enable_interrupts ();

/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC //宏没有定义,条件不成立
/* XXX: this needs to be moved to board init */
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
davinci_eth_set_mac_addr(enetaddr);
}
#endif

#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) 宏没有定义,下面的代码不执行
/* XXX: this needs to be moved to board init */
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
smc_set_mac_addr(enetaddr);
}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */

/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
#if defined(CONFIG_CMD_NET) // 宏没有定义,后面的代码不执行
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif

#ifdef BOARD_LATE_INIT // 宏没有定义,代码不执行
board_late_init ();
#endif

#ifdef CONFIG_GENERIC_MMC // 宏没有定义,代码不执行
puts ("MMC: ");
mmc_initialize (gd->bd);
#endif

#ifdef CONFIG_BITBANGMII // 宏没有定义,代码不执行
bb_miiphy_init();
#endif
#if defined(CONFIG_CMD_NET) // 宏没有定义,代码不执行
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif
eth_initialize(gd->bd);
eth_init(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
debug ("Reset Ethernet PHY\n");
reset_phy();
#endif
#endif
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}

/* NOTREACHED - no way out of command loop except booting */
}

void hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");
for (;;);
}


*********************************************************************************************************

u-boot中typedef应用解析___init_fnc_t *init_sequence[]        


*********************************************************************************************************

/*这里定义了一个新的数据类型init_fnc_t

*这个数据类型是参数为空,返回值为int的函数。
*/

typedef int (init_fnc_t) (void);
/*init_sequence是一个指针数组,指向的是init_fnc_t类型的函数*/
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,
};

/*init_fnc_ptr为指向函数指针的指针*/
init_fnc_t **init_fnc_ptr;
/*init_fnc_ptr初始化指向init_sequence指针数组,下面的循环遇到NULL结束*/
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {/*(*init_fnc_ptr)()为C中调用指针指向的函数*/
hang ();
}
}


自己写了2个test程序
一个typedef int (test_fnc_t) (void);
一个typedef int (*test_fnc_t) (void);

#include<stdio.h>

int test0 (void);
int test1 (void);

typedef int (*test_fnc_t) (void);

test_fnc_t test_sequence[] = {
test0,
test1,
NULL,
};


//int _tmain(int argc, _TCHAR* argv[])

int main()
{
test_fnc_t *test_fnc_ptr;

for (test_fnc_ptr = test_sequence; *test_fnc_ptr; ++test_fnc_ptr) {
if ((*test_fnc_ptr)() != 0) {
printf("error here!");
}
}

return 0;
}

int test0 (void)
{
printf("test0\n");
return 0;
}

int test1 (void)
{
printf("test1\n");
return 0;
}

#include<stdio.h>

int test0 (void);
int test1 (void);


typedef int (test_fnc_t) (void);

test_fnc_t *test_sequence[] = {
test0,
test1,
NULL,
};


//int _tmain(int argc, _TCHAR* argv[])

int main()
{
test_fnc_t **test_fnc_ptr;

for (test_fnc_ptr = test_sequence; *test_fnc_ptr; ++test_fnc_ptr) {
if ((*test_fnc_ptr)() != 0) {
printf("error here!");
}
}

return 0;
}

int test0 (void)
{
printf("test0\n");
return 0;
}

int test1 (void)
{
printf("test1\n");
return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值