u-boot之start_armboot函数分析

发布者:Shuangfei最新更新时间:2024-08-29 来源: cnblogs关键字:u-boot 手机看文章 扫描二维码
随时随地手机看文章

1、gd全局变量初始化


2、调用init_sequence函数指针数组里的初始化函数、nand初始化、环境变量初始化、USB初始化


3、死循环main_loop()分析




 


1、gd全局变量初始化


gd是全局引用的变量,它的定义在Global_data.h (includeasm-arm)中,它利用的是CPU的寄存器r8。只有在文件中引用DECLARE_GLOBAL_DATA_PTR ,就可以使用gd这个变量


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

它是一个指向gd_t结构体的指针,gd_t结构体如下所示


typedef    struct    global_data {

    bd_t        *bd;                                                //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 */  //lcd的缓存地址

#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;


其中env_addr、baudrate、bd等参数比较重要,bd也是一个结构体,在U-boot.h (includeasm-arm)里定义,定义如下所示,这里面bi_arch_number与bi_boot_params这两个参数是传给内核的,很重要。


typedef struct bd_info {

    int            bi_baudrate;    /* serial console baudrate *///串口作为控制台时的波特率

    unsigned long    bi_ip_addr;    /* IP Address */             //ip地址,可配置

    unsigned char    bi_enetaddr[6]; /* Ethernet adress */    //物理网络地址,即MAC Address,网卡决定,不可配置

    struct environment_s           *bi_env;                  //指向环境变量的指针

    ulong            bi_arch_number;    /* unique id for this board *///CPU架构号码,传给内核

    ulong            bi_boot_params;    /* where this board expects params *///标记列表的开始地址,传给内核,告诉内核从这个地方取参数

    struct                /* RAM configuration */

    {

    ulong start;

    ulong size;

    }             bi_dram[CONFIG_NR_DRAM_BANKS];//sdram的起始地址与大小

#ifdef CONFIG_HAS_ETH1

    /* second onboard ethernet port */

    unsigned char   bi_enet1addr[6];

#endif

} bd_t;


environment_s结构体定义在Environment.h (include)中,如下所示。环境变量就是以这个格式存储在nand中的


#define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE)//0x20000-5,减去的5为crc校验与flags占用的


typedef    struct environment_s {

    unsigned long    crc;        /* CRC32 over data bytes    *///crc校验

#ifdef CFG_REDUNDAND_ENVIRONMENT

    unsigned char    flags;        /* active/obsolete flags    *///环境变量标志

#endif

    unsigned char    data[ENV_SIZE]; /* Environment data        *///环境变量具体的数据。最大

} env_t;


start_armboot函数一开始先初始化gd变量。gd变量所指向的内容占用128字节存放在堆区后面,栈区前面。


    /* Pointer is writable since we allocated a register for it */

    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));//gd地址向上增长

    /* compiler optimization barrier needed for GCC >= 3.4 */

    __asm__ __volatile__('': : :'memory');


    memset ((void*)gd, 0, sizeof (gd_t));//清0 gd段 

    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));//求出bd段地址  

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


    monitor_flash_len = _bss_start - _armboot_start;//显示需要的flash长度


2、调用init_sequence函数指针数组里的初始化函数、nand初始化、环境变量初始化、USB初始化


start_armboot函数继续往下执行,执行初始化函数数组里的函数


for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {//初始化各个函数  by andy

        if ((*init_fnc_ptr)() != 0) {//函数的返回值不为0,认为出错,打印出错信息 by andy

            hang ();//打印出错信息   by andy

        }

    }

init_sequence数组的内容如下所示


    init_fnc_t *init_sequence[] = {

    cpu_init,        /* basic cpu dependent setup *///CPU的一些堆栈大小设置  by andy

    board_init,        /* basic board dependent setup *///设置芯片代码、设置与内核交互的地址 by andy

    interrupt_init,        /* set up exceptions *///10ms时钟定时器设置  by andy

    env_init,        /* initialize environment *///初始化环境变量,采用默认环境变量  by andy

    init_baudrate,        /* initialze baudrate settings *///初始化串口波特率为115200 by andy

    serial_init,        /* serial communications setup *///初始化串口在cpu/arm920t/s3c24x0中实现  by andy

    console_init_f,        /* stage 1 init of console *///设置控制台初始化标志 by andy

    display_banner,        /* say that we are here *///打印UBOOT版本信息 by andy

#if defined(CONFIG_DISPLAY_CPUINFO)

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

#endif

#if defined(CONFIG_DISPLAY_BOARDINFO)

    checkboard,        /* display board info */

#endif

    dram_init,        /* configure available RAM banks *///内存起始地址以及大小设置 by andy

    display_dram_config,//打印出DRAM的大小  by andy

    NULL,

};


start_armboot函数继续往下执行,清0分配的堆区的内容


    /* armboot_start is defined in the board-specific linker script */

    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);//清0堆区的内容


void mem_malloc_init (ulong dest_addr)

{

    mem_malloc_start = dest_addr;                //堆区的首地址

    mem_malloc_end = dest_addr + CFG_MALLOC_LEN; //堆区的结束地址

    mem_malloc_brk = mem_malloc_start;


    memset ((void *) mem_malloc_start, 0,

            mem_malloc_end - mem_malloc_start);//清0堆区的内容

}


start_armboot函数继续往下执行,初始化nand,环境变量的内容存储在nand中


puts ('NAND:  ');//打印出nand的大小  

    nand_init();        /* go init the NAND *///初始化nand flash

start_armboot函数继续往下执行,重新检测环境变量,环境变量在初始化函数数组中已经初始化过,因为nand初始化后,所以再检测一般环境变量是否需要重新加载。env_relocate 函数大致的意思是检查nand中的存放环境变量位置的crc校验是否有效,如果无效则采用默认的环境变量,如果有效则采用nand中的环境变量


/* initialize environment */

    env_relocate ();//初始化环境变量,crc有效的话从nand中读取存储的环境变量,否则采用默认的环境变量  by andy

默认的环境变量的值如下


uchar default_environment[] = {

#ifdef    CONFIG_BOOTARGS

    'bootargs='    CONFIG_BOOTARGS            ''//'noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0',传给内核的参数

#endif

#ifdef    CONFIG_BOOTCOMMAND

    'bootcmd='    CONFIG_BOOTCOMMAND        ''//'nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0'。启动内核的命令

#endif

#ifdef    CONFIG_RAMBOOTCOMMAND

    'ramboot='    CONFIG_RAMBOOTCOMMAND        ''

#endif

#ifdef    CONFIG_NFSBOOTCOMMAND

    'nfsboot='    CONFIG_NFSBOOTCOMMAND        ''

#endif

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)

    'bootdelay='    MK_STR(CONFIG_BOOTDELAY)    ''//延时参数2S 

#endif

#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)

    'baudrate='    MK_STR(CONFIG_BAUDRATE)        ''//波特率115200

#endif

#ifdef    CONFIG_LOADS_ECHO

    'loads_echo='    MK_STR(CONFIG_LOADS_ECHO)    ''

#endif

#ifdef    CONFIG_ETHADDR

    'ethaddr='    MK_STR(CONFIG_ETHADDR)        ''//08:00:3e:26:0a:5b;MAC地址

#endif

#ifdef    CONFIG_ETH1ADDR

    'eth1addr='    MK_STR(CONFIG_ETH1ADDR)        ''

#endif

#ifdef    CONFIG_ETH2ADDR

    'eth2addr='    MK_STR(CONFIG_ETH2ADDR)        ''

#endif

#ifdef    CONFIG_ETH3ADDR

    'eth3addr='    MK_STR(CONFIG_ETH3ADDR)        ''

#endif

#ifdef    CONFIG_IPADDR

    'ipaddr='    MK_STR(CONFIG_IPADDR)        ''//板子IP192.168.7.17

#endif

#ifdef    CONFIG_SERVERIP

    'serverip='    MK_STR(CONFIG_SERVERIP)        ''//服务器IP192.168.7.11

#endif

#


start_armboot函数继续往下执行,从环境变量中获取IP地址以及MAC地址


gd->bd->bi_ip_addr = getenv_IPaddr ('ipaddr');//从环境变量获得IP地址  by andy

    i = getenv_r ('ethaddr', tmp, sizeof (tmp));//从环境变量获得MAC地址

        s = (i > 0) ? tmp : NULL;


        for (reg = 0; reg < 6; ++reg) {//判断获得的MAC地址有效后存储在gd->bd->bi_enetaddr中

[1] [2]
关键字:u-boot 引用地址:u-boot之start_armboot函数分析

上一篇:u-boot之内核是怎么启动的
下一篇:u-boot之NAND启动与NOR启动的区别

推荐阅读最新更新时间:2026-03-19 11:10

IMX6ULL学习笔记(7)——通过SD卡启动U-Boot
一、简介 在 Ubuntu 下可以更精细地操作 SD/TF 卡:可以把 sdcoard.img 整个烧写到卡上,也可以单独烧写 U-Boot 到卡上,甚至挂接卡上的文件系统后单独更新里面的文件。 常用于做 U-Boot 测试。 1.1 dd命令 主用功能是用于拷贝文件,也就是用指定大小的块去拷贝一个文件,并在拷贝的同时进行指定的转换(默认从标准输入拷贝到标准输出,这意味dd可以在管道中使用)。这个拷贝过程简单理解就是读取,转换并输出数据。 用法: dd 二、识别SD卡 首先 SD 卡插入读卡器,再把读卡器插入电脑。 VMWare 有时候会自动弹出对话框,选择 连接到虚拟机 即可。 如果没有对话框,可以通过
[单片机]
U-Boot Makefile分析(5)主控Makefile分析
  这次分析源码根目录下的Makefile,它负责读入配置过的信息,通过OBJS、LIBS等变量设置能够参与镜像链接的目标文件,设定编译的目标等等。 1 HOSTARCH := $(shell uname -m | 2 sed -e s/i.86/x86/ 3 -e s/sun4u/sparc64/ 4 -e s/arm.*/arm/ 5 -e s/sa110/arm/ 6 -e s/ppc64/powerpc/ 7 -e s/ppc/powerpc/ 8 -e s/macppc/powerpc/ 9 -e s/sh.*/sh/) 10 11 HOS
[单片机]
tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——移植u-boot.bin(打印串口控制台)
在之前我们移植的代码中,都没看到明显的效果,这节我们实现控制台的信息打印。 在上节。我们看到调用 relocate_code 重定位。在 u-boot 的帮助文档 doc/README.arm-relocation 中对重定位有说明。 u-boot 为了生成位置无关码,在链接时指定了-pie 选项,这个选项在 u-boot-2014.04/arch/arm/config.mk 中指定: 当使用-pie 选项后。链接器会生成一个修正表(fixup tables)。在终于的二进制文件 u-boot.bin 中表现为多了 2 个段 .rel.dyn 和 .dynsym。还须要在链接脚本文件里添加这 2 个段,u-boot.b
[单片机]
tiny210(s5pv210)移植<font color='red'>u-boot</font>(基于 2014.4 版本号)——移植u-boot.bin(打印串口控制台)
u-boot 移植 --->5、友善之臂Tiny210底板王网卡驱动移植
网卡芯片的工作原理 DM9000AE具有以下主要性能: ①48管脚的LQFP封装,管脚少体积小; ②支持8/16位数据总线; ③适用于10Base-T和100Base-T,10/100M自适应,适应不同的网络速度要求 ④内置16KB的SRAM,用于收发缓冲,降低对主处理器的速度要求; ⑤支持IP /TCP /UDP加速,减轻了CPU负担,提高网络速度;⑥支持Back pressure半双工流量控制,与IEEE802.3u兼容,支持IEEE802.3x全双工流量控制; ⑦20ns响应时间,2.5V/3.3V低功耗。下图是DM9000网卡芯片常用在嵌入式网络系统上的结构框图。 数据支持8位和16位,不同模式下的PIN脚定义是不
[单片机]
<font color='red'>u-boot</font> 移植 --->5、友善之臂Tiny210底板王网卡驱动移植
tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动
我们知道 s5pv210启动方式有非常多种,sd卡和nand flash 启动就是当中的两种,前面我们实现的都是基于sd卡启动,这节我们開始实现从nand flash 启动: 从 NAND 启动 u-boot,须要 BL1 初始化 NAND 控制器,然后从 NAND 拷贝 BL2 到 DDR 内存。这里的BL1 即我们移植的 u-boot-spl.bin,BL2 即我们移植的 u-boot.bin。在 u-boot.bin 中的 NAND 驱动比較大,它包括了非常多功能,而 u-boot-spl.bin 中仅仅须要从 NAND 拷贝BL2 到 DDR 即可了,因此我们能够在 u-boot-spl.bin 进行简单的 N
[单片机]
tiny210(s5pv210)移植<font color='red'>u-boot</font>(基于 2014.4 版本号)——NAND 启动
U-boot内核移植步骤
Linux 3.3.5系统移植 将arch/arm/mach-s3c6410/下的,mach-smdk6410.c cp为mach-my6410.c; 打开arch/arm/mach-s3c6410/下的Kconfig,仿照MACH_SMDK6410做一个菜单项: config MACH_MY6410 bool MY6410 select CPU_S3C6410 select SAMSUNG_DEV_ADC select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_I2C1 select SAMSUNG_DEV_IDE select
[单片机]
u-boot中添加命令
u-boot是嵌入式系统中广泛使用的一种bootloader。它不仅支持众多的平台和参考板,而且支持丰富的命令,可以让用户对开发板进行各种操作。关于u-boot使用和移植的资料很多,这里不再赘述。下面用问答的方式介绍u-boot中命令的实现机制。 Q1: u-boot中命令的实现代码在什么地方? A1: 在u-boot源码的common目录下。通常一个或多个命令在对应的某个C文件中实现。如果用户要增加一个新命令的话,要在common目录下添加对应的C文件,并在Makefile中指定编译该文件。 Q2: 能不能给个命令的实现模板先? A2: #include common.h #include command.h
[单片机]
u-boot分析与移植——基于u-boot-2011.3和FL2440
关于移植的基本方法可以先阅读u-boot的README文档 If the system board that you have is not listed, then you will need to port U-Boot to your hardware platform. To do this, follow these steps: 1. Add a new configuration option for your board to the toplevel Makefile and to the MAKEALL script, using the existing entries as example
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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