四、第二阶段

全局数据

声明

# < lib_arm\board.c >

DECLARE_GLOBAL_DATA_PTR;

定义

# < include\asm\global_data.h >

typedef struct global_data {

bd_t *bd;

unsigned long flags;

unsigned long baudrate;

unsigned long have_console; /* serial_init() was called */

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;

phys_size_t ram_size; /* RAM size */

unsigned long reset_status; /* reset status register at boot */

#endif

void **jt; /* jump table */

} gd_t;

// 申明一个gd_t类型的指针gd,存于寄存器r8

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

字段说明

bd_t *bd:board info数据结构定义,位于文件 include/asm-arm/u-boot.h定义,主要是保存开发板的相关参数。

    typedef struct bd_info {

        int bi_baudrate; /* serial console baudrate */

        unsigned long bi_ip_addr; /* IP Address */

        struct environment_s       *bi_env;

        ulong bi_arch_number; /* unique id for this board */

        ulong bi_boot_params; /* where this board expects params */

        struct /* RAM configuration */

        {

            ulong start;    

   ulong size;

        }bi_dram[CONFIG_NR_DRAM_BANKS];

    } bd_t;

unsigned long env_addr:环境变量的地址。

unsigned long ram_top:RAM空间的顶端地址

unsigned long relocaddr:UBOOT重定向后地址

phys_size_t ram_size:物理ram的size

unsigned long irq_sp:中断的堆栈地址

unsigned long start_addr_sp:堆栈地址

unsigned long reloc_off:uboot的relocation的偏移

struct global_data *new_gd:重定向后的struct global_data结构体

const void *fdt_blob:我们设备的dtb地址

void *new_fdt:relocation之后的dtb地址

unsigned long fdt_size:dtb的长度

struct udevice *cur_serial_dev:当前使用的串口设备。

初始化序列(板子初始化函数序列)

原型

# < lib_arm\board.c >

typedef int (init_fnc_t) (void);

int print_cpuinfo (void);

init_fnc_t *init_sequence[] = {

#if defined(CONFIG_ARCH_CPU_INIT)

arch_cpu_init, /* basic arch cpu dependent setup */

#endif

board_init, /* basic board dependent setup */

#if defined(CONFIG_USE_IRQ)

interrupt_init, /* set up exceptions */

#endif

timer_init, /* initialize timer */

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 */

#if defined(CONFIG_DISPLAY_CPUINFO)

print_cpuinfo, /* display cpu info (and speed) */

#endif

#if defined(CONFIG_DISPLAY_BOARDINFO)

checkboard, /* display board info */

#endif

#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)

init_func_i2c,

#endif

dram_init, /* configure available RAM banks */

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)

arm_pci_init,

#endif

display_dram_config,

NULL,

};

结果

init_fnc_t *init_sequence[] = {

board_init, /* basic board dependent setup */

timer_init, /* initialize timer */

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,

NULL,

};

入口函数

入口

# < lib_arm\board.c >

void start_armboot (void)

申请gd全局数据

gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

防止高版本gcc优化产生错误

    _asm__ __volatile__("": : :"memory");

说明:

1)   __asm__用于指示编译器在此插入汇编语句。

2)    __volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。

3)    memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。

4)      "":::表示这是个空指令。barrier()不用在此插入一条串行化汇编指令。

清空全局数据

    memset ((void*)gd, 0, sizeof (gd_t));

    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

    memset (gd->bd, 0, sizeof (bd_t));

设置标志位(当前代码在RAM)

    gd->flags |= GD_FLG_RELOC;

获取整个uboot长度

monitor_flash_len = _bss_start - _armboot_start;

说明:

_bss_start是bss的开始地址,_armboot_start是Uboot的开始代码地址,这里monitor_flash_len得到的是整个Uboot的长度

使用初始化函数序列初始化

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)

    {

        if ((*init_fnc_ptr)() != 0) //函数返回值不为零,直接进入死循环

        {

            hang ();    //死循环 { for(;;); }

        }

    }

初始化内存堆区

mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);

说明:

_armboot_start = TEXT_BASE = 0x33F80000

# < common\dlmalloc.c >

void mem_malloc_init(ulong start, ulong size)

{

mem_malloc_start = start;

mem_malloc_end = start + size;

mem_malloc_brk = start;

memset((void *)mem_malloc_start, 0, size);

}

flash驱动器初始化

#ifndef CONFIG_SYS_NO_FLASH

    /* configure available FLASH banks */

    display_flash_config (flash_init ());

#endif /* CONFIG_SYS_NO_FLASH */

说明:

# < lib_arm\board.c >

static void display_flash_config (ulong size)

{

puts ("Flash: ");

print_size (size, "\n");

}

初始化Nand驱动器

#if defined(CONFIG_CMD_NAND)

    puts ("NAND:  ");

    nand_init(); /* go init the NAND */

#endif

说明:

# < include\configs\mini2440.h >

#define CONFIG_SYS_MAX_NAND_DEVICE 1

# < drivers\mtd\nand\nand.c >

void nand_init(void)

{

int i;

unsigned int size = 0;

for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {

nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);

size += nand_info[i].size / 1024;

if (nand_curr_device == -1)

nand_curr_device = i;

}

printf("%u MiB\n", size / 1024);

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE

/*

* Select the chip in the board/cpu specific driver

*/

board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);

#endif

}

环境变量初始化

    env_relocate ();

从环境变量获取ip

    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

说明:

IPaddr_t getenv_IPaddr (char *var)

{

return (string_to_ip(getenv(var)));

}

char *getenv (char *name)

{

int i, nxt;

WATCHDOG_RESET();

        // 便利所有字符串

for (i=0; env_get_char(i) != '\0'; i=nxt+1)

        {

int val;

                // 查找出一个字符串(以'\0'结束)

for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)

                {

if (nxt >= CONFIG_ENV_SIZE)

                        {

return (NULL);

}

}

if ((val=envmatch((uchar *)name, i)) < 0) // 判断名称

continue;

return ((char *)env_get_addr(val));

}

return (NULL);

}

uchar env_get_char_memory (int index)

{

if (gd->env_valid) {

return ( *((uchar *)(gd->env_addr + index)) );

} else {

return ( default_environment[index] );

}

}

uchar *env_get_addr (int index)

{

if (gd->env_valid) {

return ( ((uchar *)(gd->env_addr + index)) );

} else {

return (&default_environment[index]);

}

}

标准输入、标准输出、标准错误初始化("stdin", "stdout", "stderr")

    stdio_init()

int stdio_init (void)

{    //其余代码由于宏被屏蔽

drv_system_init ();

return (0);

}

static void drv_system_init (void)

{

struct stdio_dev dev;

memset (&dev, 0, sizeof (dev));

strcpy (dev.name, "serial");

dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;

dev.putc = serial_putc;

dev.puts = serial_puts;

dev.getc = serial_getc;

dev.tstc = serial_tstc;

stdio_register (&dev);

}

struct stdio_dev {

int flags; /* Device flags: input/output/system */

int ext; /* Supported extensions */

char name[16]; /* Device name */

/* GENERAL functions */

int (*start) (void); /* To start the device */

int (*stop) (void); /* To stop the device */

/* OUTPUT functions */

void (*putc) (const char c); /* To put a char */

void (*puts) (const char *s); /* To put a string (accelerator) */

/* INPUT functions */

int (*tstc) (void); /* To test if a char is ready... */

int (*getc) (void); /* To get that char */

/* Other functions */

void *priv; /* Private extensions */

struct list_head list;

};

int stdio_register (struct stdio_dev * dev)

{

struct stdio_dev *_dev;

_dev = stdio_clone(dev);

if(!_dev)

return -1;

list_add_tail(&(_dev->list), &(devs.list));

return 0;

}

struct stdio_dev* stdio_clone(struct stdio_dev *dev)

{

struct stdio_dev *_dev;

if(!dev)

return NULL;

_dev = calloc(1, sizeof(struct stdio_dev));

if(!_dev)

return NULL;

memcpy(_dev, dev, sizeof(struct stdio_dev));

strncpy(_dev->name, dev->name, 16);

return _dev;

}

跳转表初始化

    jumptable_init ();

void jumptable_init (void)

{    //函数地址

int i;

gd->jt = (void **) malloc (XF_MAX * sizeof (void *));

for (i = 0; i < XF_MAX; i++)

gd->jt[i] = (void *) dummy;

gd->jt[XF_get_version] = (void *) get_version;

gd->jt[XF_malloc] = (void *) malloc;

gd->jt[XF_free] = (void *) free;

gd->jt[XF_getenv] = (void *) getenv;

gd->jt[XF_setenv] = (void *) setenv;

gd->jt[XF_get_timer] = (void *) get_timer;

gd->jt[XF_simple_strtoul] = (void *) simple_strtoul;

gd->jt[XF_udelay] = (void *) udelay;

gd->jt[XF_simple_strtol] = (void *) simple_strtol;

gd->jt[XF_strcmp] = (void *) strcmp;

#if defined(CONFIG_I386) || defined(CONFIG_PPC)

gd->jt[XF_install_hdlr] = (void *) irq_install_handler;

gd->jt[XF_free_hdlr] = (void *) irq_free_handler;

#endif /* I386 || PPC */

#if defined(CONFIG_CMD_I2C)

gd->jt[XF_i2c_write] = (void *) i2c_write;

gd->jt[XF_i2c_read] = (void *) i2c_read;

#endif

#ifdef CONFIG_CMD_SPI

gd->jt[XF_spi_init] = (void *) spi_init;

gd->jt[XF_spi_setup_slave] = (void *) spi_setup_slave;

gd->jt[XF_spi_free_slave] = (void *) spi_free_slave;

gd->jt[XF_spi_claim_bus] = (void *) spi_claim_bus;

gd->jt[XF_spi_release_bus] = (void *) spi_release_bus;

gd->jt[XF_spi_xfer] = (void *) spi_xfer;

#endif

}

终端设备第二阶段初始化

    console_init_r ();

中断初始化

    enable_interrupts ();

说明:

根据宏:CONFIG_USE_IRQ,该函数功能被屏蔽

void enable_interrupts (void)

{

return;

}

从环境变量获取加载地址(未使用,环境变量没有该参数)

    if ((s = getenv ("loadaddr")) != NULL) {

        load_addr = simple_strtoul (s, NULL, 16);

    }

主循环

    for (;;)

    {

        main_loop ();

    }

滞后说明

各种初始化(init_sequence)

nand初始化(nand_init)

环境变量初始化(env_relocate)

终端初始化(console_init_r)

主循环(main_loop )

猜你喜欢

转载自blog.csdn.net/liutit/article/details/130034421