uboot移植之start_armboot()函数分析

author author     2022-08-30     602

关键词:

/********************************

uboot的第二阶段就是初始化剩下的还没在第一阶段初始化的硬件。主要是SoC外部硬件(譬如 iNand 网卡芯片....... )uboot本身的一些东西(uboot的命令 环境变量等.....)。然后最终初始化完必要的东西后进入到uboot的命令行准备接受命令。

***********************************/

void start_armboot (void)       //这个函数构成了uboot启动的第二阶段


/************************************

typedef int (init_fnc_t) (void);这是一个函数类型,所以init_fnc_t_ptr是一个二重函数指针,二重指针的作用有两个,(一个是用来指向一重指针(指针的指针)),一个用来指向一个指针数组。因此这里的init_fnc_t_ptr可以用来指向一个函数指针数组。

****************************************/

    init_fnc_t **init_fnc_ptr;

    char *s;

    int mmc_exist = 0;

#if !defined(CFG_NO_FLASH) || defined (CONFIG_VFD) || defined(CONFIG_LCD)

    ulong size;

#endif


#if defined(CONFIG_VFD) || defined(CONFIG_LCD)

    unsigned long addr;

#endif


#if defined(CONFIG_BOOT_MOVINAND)

    uint *magic = (uint *) (PHYS_SDRAM_1);

#endif


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

#ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */

    ulong gd_base;       //gd在DDR内存分配中的起始地址

/************************gd(global data)的由来******************

每个用到文件的开头都有DECLARE_GLOBAL_DATA_PTR;这句,而这个宏在我们的uboot/include/asm-arm/Global_data.h中有定义(gd_t也定义在这个文件中)

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

定义了一个全局变量名字为gd,这个全局变量是一个指针类型,占4个字节,用volatile修饰表示可变的;用register修饰表示这个变量要尽量放到寄存器中;asm("r8")是gcc支持的一种语法,意思是要把gd放到寄存器r8中。

综合分析:DECLARE_GLOBAL_DATA_PTR就是定义了一个要放在寄存器r8中的全局变量,名字叫gd,类型是一个指向gd_t类型变量的指针。gd_t中定义了很多全局变量,都是整个uboot使用的,其中有一个bd_t类型的指针bd,指向结构体bd_info,这个结构体里面定义的是和开发板硬件相关的全局变量(譬如 ip地址  串口波特率 等)

全局变量gd是uboot中很重要的一个全局变量(准确的说这个全局变量是一个结构体,里面有很多内容,这些内容加起来构成的结构体就是uboot中常用的所有全局变量),由于gd经常被访问,因此放在寄存器中提升访问效率。

**************************/

/***************************************************

typedef    struct    global_data {

    bd_t        *bd;   //指向bd_t的指针

    unsigned long    flags;

    unsigned long    baudrate;  //波特率

    unsigned long    have_console; 是否有控制台(终端,或串口之类的)

    unsigned long    reloc_off;    /* Relocation Offset */

    unsigned long    env_addr;  //  环境变量的地址

    unsigned long    env_valid;   //环境变量checksum是否有效

    unsigned long    fb_base;    //frame buffer的基地址

    void        **jt;        /* jump table */

} gd_t;

******************************************/

gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);

/******************************************

//uboot区:CFG_UBOOT_BASE (33e00000)+CFG_UBOOT_SIZE (uboot的实际大小,我们这里给了2M)

堆区:长度为CFG_MALLOC_LEN ,实际长度为912KB

栈区:长度为CFG_STACK_SIZE,实际长度为512KB

gd:长度为sizeof(gd_t),实际为36字节

bd:长度为sizeof(bd_t),实际长度为44字节左右

所以gd_base的大概位置是离uboot起始地址(33e00000)往上走624KB的位置处

**************************************/

#ifdef CONFIG_USE_IRQ

    gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);   

#endif   //CONFIG_USE_IRQ

    gd = (gd_t*)gd_base;  //上面已经得到gd_base是一个内存地址,然后通过强制类型转换使其变为一个指针,并赋给gd,使得gd指向这段内存空间

#else  //CONFIG_MEMORY_UPPER_CODE 

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

#endif   //CONFIG_MEMORY_UPPER_CODE 


    /* compiler optimization barrier needed for GCC >= 3.4 */  //避免高版本的gcc的过度优化造成错误

    __asm__ __volatile__("": : :"memory");     //内嵌汇编

/*

__asm__ :用于指示编译器在此插入汇编语句

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

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

*/

/*需要注意的是:

(1)这里的#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")只是定义了一个指针,也就说gd里的这些全局变量并没有分配内存,我们在使用gd之前要给他分配内存,否则gd只是一个野指针

(2)gd和bd需要内存,内存当前没有被人管理(因为没有操作系统统一管理内存),大片的DDR内存(0x30000000-0x4fffffff共512MB)散放着可以随意使用(只要使用内存地址直接去访问内存即可),但是因为后面的uboot还需要大片内存,所以这里要本着够用,紧凑排布的原则

****************************************************/

    memset ((void*)gd, 0, sizeof (gd_t));    //申请的内存使用之前先进行清零

    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));   //根据bd的大小计算bd的起始地址,在gd下面紧挨着

//假如改为(int *)gd - sizeof(bd_t),则实际int * 类型指针-1相当于地址-4*1,这样就会浪费一部分内存(虽然很   //小,因为这里的sizeof(bd_t)里面的就是bd的大小,所以地址直接减去这段内存即可。所以是char * gd

    memset (gd->bd, 0, sizeof (bd_t));     //申请的内存使用之前先进行清零


    monitor_flash_len = _bss_start - _armboot_start;

/********************************************************

前面已经讲到过init_fnc_ptr 是一个二重函数指针,可以指向init_sequence这个函数指针数组,而 init_sequence是一个函数指针数组,所以这个数组存放了很多函数指针,这些函数的类型都是init_fnc_ptr类型(typedef int (init_fnc_t) (void);)特殊是接收参数是void类型,返回值是int类型。这里面的内容都是函数名,也就是函数指针,这些函数都是板级初始化的代码。

*init_fnc_ptr:解引用,得到的就是一个函数指针

这个for循环的作用就是去遍历init_sequence这个函数指针数组,而遍历的目的就是去执行这个函数指针数组里面的全部函数。

和普通数组类似,函数指针数组也可以通过下标个数组里面的元素个数去遍历这个数组(for(i=0;i<n;i++  a[i])),但是这里使用的是另一种思路:通过在数组的最后设置一个标志(NULL),遍历的时候从开头开始,直到检测到标志(NULL)结束,这样的好处是不需要去确定数组元素的个数。

*****************************************/

/*

用函数指针去调用函数(得到的是函数的返回值),数组里面的函数正确执行时返回值都是0,如果错误是则挂起(hang();)启动失败

*/

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

        if ((*init_fnc_ptr)() != 0) {  

            hang ();

        }

    }


#ifndef CFG_NO_FLASH    

/*  

Nor_FLASH初始化,但是我们的开发板上面接的是NandFlash,所以这个是无效的,可以拿去

*/

    /* configure available FLASH banks */

    size = flash_init ();

    display_flash_config (size);

#endif /* CFG_NO_FLASH */


#ifdef CONFIG_VFD  

/*

uboot中自带的LCD显示架构,但是我们没有使用uboot的LCD显示架构,而是自己添加了一套LCD显示架构

*/

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

    size = 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);

        size = lcd_setmem (addr);

        gd->fb_base = addr;

    }

#endif /* CONFIG_LCD */


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

#ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */

    mem_malloc_init (CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE);

/*

   (1)mem_malloc_init函数用来初始化uboot的堆管理器。

   (2)uboot中自己维护了一段堆内存,肯定自己就有一套代码来管理这个堆内存。有了这些东西uboot中你也可以malloc、free这套机制来申请内存和释放内存。我们在DDR内存中给堆预留了896KB的内存。

*/


#else

    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

#endif


//******************************//

// Board Specific  开发板独有的配置

三星用一套uboot满足了多套开发板,开发板之间的差别就在这里分析

// #if defined(CONFIG_SMDKXXXX)

//******************************//


#if defined(CONFIG_SMDK6410)

    #if defined(CONFIG_GENERIC_MMC)

    puts ("SD/MMC:  ");

    mmc_exist = mmc_initialize(gd->bd);

/***********************************************************

(1)mmc_initialize():MMC相关的一些基础的初始化,其实就是用来初始化SoC内部的SD/MMC控制器的。函数在uboot/drivers/mmc/mmc.c里。

(2)mmc_initialize():是具体硬件架构无关的一个MMC初始化函数,

所有的使用了这套架构的代码都掉用这个函数来完成MMC的初始化。

mmc_initialize中再调用board_mmc_init和cpu_mmc_init来完成具体的硬件的MMC控制器初始化工作。

****************************************************/

    if (mmc_exist != 0)

    {

        puts ("0 MB ");

    }

    #else

    #if defined(CONFIG_MMC)

    puts("SD/MMC:  ");


    if (INF_REG3_REG == 0)

        movi_ch = 0;

    else

        movi_ch = 1;


    movi_set_capacity();

    movi_init();

    movi_set_ofs(MOVI_TOTAL_BLKCNT);

    #endif

    #endif


    if (INF_REG3_REG == BOOT_ONENAND) {

    #if defined(CONFIG_CMD_ONENAND)

        puts("OneNAND: ");

        onenand_init();

    #endif

        /*setenv("bootcmd", "onenand read c0008000 80000 380000;bootm c0008000");*/

    } else {

        puts("NAND:    ");

        nand_init();


        if (INF_REG3_REG == 0 || INF_REG3_REG == 7)

            setenv("bootcmd", "movi read kernel c0008000;movi read rootfs c0800000;bootm c0008000");

        else

            setenv("bootcmd", "nand read c0008000 80000 380000;bootm c0008000");

    }

#endif    /* CONFIG_SMDK6410 */


#if defined(CONFIG_SMDKC100)

//210SD卡相关配置

    #if defined(CONFIG_GENERIC_MMC)

        puts ("SD/MMC:  ");

        mmc_exist = mmc_initialize(gd->bd);

        if (mmc_exist != 0)

        {

            puts ("0 MB ");

        }

    #endif


    #if defined(CONFIG_CMD_ONENAND)

        puts("OneNAND: ");

        onenand_init();

    #endif


    #if defined(CONFIG_CMD_NAND)

        puts("NAND:    ");

        nand_init();

    #endif


#endif /* CONFIG_SMDKC100 */


#if defined(CONFIG_X210)

//结束

    #if defined(CONFIG_GENERIC_MMC)

        puts ("SD/MMC:  ");

        mmc_exist = mmc_initialize(gd->bd);

        if (mmc_exist != 0)

        {

            puts ("0 MB ");

#ifdef CONFIG_CHECK_X210CV3

            check_flash_flag=0;//check inand error!

#endif

        }

#ifdef CONFIG_CHECK_X210CV3

        else

        {

            check_flash_flag=1;//check inand ok! 

        }

#endif

    #endif


    #if defined(CONFIG_MTD_ONENAND)

        puts("OneNAND: ");

        onenand_init();

        /*setenv("bootcmd", "onenand read c0008000 80000 380000;bootm c0008000");*/

    #else

        //puts("OneNAND: (FSR layer enabled) ");

    #endif


    #if defined(CONFIG_CMD_NAND)

        puts("NAND:    ");

        nand_init();

    #endif


#endif /* CONFIG_X210 */


#if defined(CONFIG_SMDK6440)

    #if defined(CONFIG_GENERIC_MMC)

    puts ("SD/MMC:  ");

    mmc_exist = mmc_initialize(gd->bd);

    if (mmc_exist != 0)

    {

        puts ("0 MB ");

    }

    #else

    #if defined(CONFIG_MMC)

    if (INF_REG3_REG == 1) {    /* eMMC_4.3 */

        puts("eMMC:    ");

        movi_ch = 1;

        movi_emmc = 1;


        movi_init();

        movi_set_ofs(0);

    } else if (INF_REG3_REG == 7 || INF_REG3_REG == 0) {    /* SD/MMC */

        if (INF_REG3_REG & 0x1)

            movi_ch = 1;

        else

            movi_ch = 0;


        puts("SD/MMC:  ");


        movi_set_capacity();

        movi_init();

        movi_set_ofs(MOVI_TOTAL_BLKCNT);


    } else {


    }

    #endif

    #endif


    if (INF_REG3_REG == 2) {

            /* N/A */

    } else {

        puts("NAND:    ");

        nand_init();

        //setenv("bootcmd", "nand read c0008000 80000 380000;bootm c0008000");

    }

#endif /* CONFIG_SMDK6440 */


#if defined(CONFIG_SMDK6430)

    #if defined(CONFIG_GENERIC_MMC)

    puts ("SD/MMC:  ");

    mmc_exist = mmc_initialize(gd->bd);

    if (mmc_exist != 0)

    {

        puts ("0 MB ");

    }

    #else

    #if defined(CONFIG_MMC)

    puts("SD/MMC:  ");


    if (INF_REG3_REG == 0)

        movi_ch = 0;

    else

        movi_ch = 1;


    movi_set_capacity();

    movi_init();

    movi_set_ofs(MOVI_TOTAL_BLKCNT);

    #endif

    #endif


    if (INF_REG3_REG == BOOT_ONENAND) {

    #if defined(CONFIG_CMD_ONENAND)

        puts("OneNAND: ");

        onenand_init();

    #endif

        /*setenv("bootcmd", "onenand read c0008000 80000 380000;bootm c0008000");*/

    } else if (INF_REG3_REG == BOOT_NAND) {

        puts("NAND:    ");

        nand_init();

    } else {

    }


    if (INF_REG3_REG == 0 || INF_REG3_REG == 7)

        setenv("bootcmd", "movi read kernel c0008000;movi read rootfs c0800000;bootm c0008000");

    else

        setenv("bootcmd", "nand read c0008000 80000 380000;bootm c0008000");

#endif    /* CONFIG_SMDK6430 */


#if defined(CONFIG_SMDK6442)

    #if defined(CONFIG_GENERIC_MMC)

    puts ("SD/MMC:  ");

    mmc_exist = mmc_initialize(gd->bd);

    if (mmc_exist != 0)

    {

        puts ("0 MB ");

    }

    #else

    #if defined(CONFIG_MMC)

    puts("SD/MMC:  ");


    movi_set_capacity();

    movi_init();

    movi_set_ofs(MOVI_TOTAL_BLKCNT);


    #endif

    #endif


    #if defined(CONFIG_CMD_ONENAND)

    if (INF_REG3_REG == BOOT_ONENAND) {

        puts("OneNAND: ");

        onenand_init();

        }

    #endif


#endif    /* CONFIG_SMDK6442 */


#if defined(CONFIG_SMDK2416) || defined(CONFIG_SMDK2450)

    #if defined(CONFIG_NAND)

    puts("NAND:    ");

    nand_init();

    #endif


    #if defined(CONFIG_ONENAND)

    puts("OneNAND: ");

    onenand_init();

    #endif


    #if defined(CONFIG_BOOT_MOVINAND)

    puts("SD/MMC:  ");


    if ((0x24564236 == magic[0]) && (0x20764316 == magic[1])) {

        printf("Boot up for burning ");

    } else {

            movi_init();

            movi_set_ofs(MOVI_TOTAL_BLKCNT);

    }

    #endif

#endif    /* CONFIG_SMDK2416 CONFIG_SMDK2450 */


#ifdef CONFIG_HAS_DATAFLASH

    AT91F_DataflashInit();

    dataflash_print_info();

#endif


    /* initialize environment */

    env_relocate ();  

/******************************************

环境变量的重定位,将SD卡中的环境变量搬移到DDR中

****************************************/


#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  IP地址设置 */

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


    /* MAC 地址设置 */

    {

        int i;

        ulong reg;

        char *s, *e;

        char tmp[64];


        i = getenv_r ("ethaddr", tmp, sizeof (tmp));

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


        for (reg = 0; reg < 6; ++reg) {

            gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;

            if (s)

                s = (*e) ? e + 1 : e;

        }


#ifdef CONFIG_HAS_ETH1

        i = getenv_r ("eth1addr", tmp, sizeof (tmp));

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


        for (reg = 0; reg < 6; ++reg) {

            gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;

            if (s)

                s = (*e) ? e + 1 : e;

        }

#endif

    }

/*设备初始化,和内核类似*/

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


#ifdef CONFIG_CMC_PU2

    load_sernum_ethaddr ();

#endif /* CONFIG_CMC_PU2 */

/*跳转表*/

    jumptable_init ();

#if !defined(CONFIG_SMDK6442)

/********************************************

控制台初始化的第二阶段,之前讲过console_init_f是第一阶段初始化,实际上第一阶段没有做什么实际的事情(只是执行了gd->have_console = 1;将这个变量设置为1),而控制台的初始化代码是在第二阶段完成的

**********************************/

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

#endif


#if defined(CONFIG_MISC_INIT_R)

    /* miscellaneous platform dependent initialisations */

    misc_init_r ();

#endif


    /* enable exceptions CPSR中的总中断标志位使能,,通过条件编译来选择函数的实体,也就是说uboot中有多个enable_interrupts ();函数,然后通过宏来决定使用哪个*/


    enable_interrupts ();


    /* Perform network card initialisation if necessary */

#ifdef CONFIG_DRIVER_TI_EMAC

extern void dm644x_eth_set_mac_addr (const u_int8_t *addr);

    if (getenv ("ethaddr")) {

        dm644x_eth_set_mac_addr(gd->bd->bi_enetaddr);

    }

#endif


#ifdef CONFIG_DRIVER_CS8900

    cs8900_get_enetaddr (gd->bd->bi_enetaddr);

#endif


#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)

    if (getenv ("ethaddr")) {

        smc_set_mac_addr(gd->bd->bi_enetaddr);

    }

#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */


    /* Initialize from environment loadaddr:内核启动有关的环境变量 */

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

        load_addr = simple_strtoul (s, NULL, 16);

    }

#if defined(CONFIG_CMD_NET)

/*   bootfile:内核启动有关的环境变量  */

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

        copy_filename (BootFile, s, sizeof (BootFile));

    }

#endif


#ifdef BOARD_LATE_INIT

    board_late_init ();   //开发板后期(剩余部分)的初始化

#endif

#if defined(CONFIG_CMD_NET)

#if defined(CONFIG_NET_MULTI)

    puts ("Net:   ");

#endif

    eth_initialize(gd->bd);

#if defined(CONFIG_RESET_PHY_R)

    debug ("Reset Ethernet PHY ");

    reset_phy();

#endif

#endif


#if defined(CONFIG_CMD_IDE)

    puts("IDE:   ");

    ide_init();

#endif


/****************lxg added**************/

#ifdef CONFIG_MPAD

    extern int x210_preboot_init(void);

    x210_preboot_init();

#endif

/****************end**********************/


    /* check menukey to update from sd */

/*****************************************************

(1)uboot启动的最后阶段设计了一个自动更新的功能。就是:我们可以将要升级的镜像放到SD卡的固定目录中,然后开机时在uboot启动的最后阶段检查升级标志(是一个按键。按键中标志为"LEFT"的那个按键,这个按键如果按下则表update mode,如果启动时未按下则表示boot mode)。如果进入update mode则uboot会自动从SD卡中读取镜像文件然后烧录到iNand中;如果进入boot mode则uboot不执行update,直接启动正常运行。

(2)这种机制能够帮助我们快速烧录系统,常用于量产时用SD卡进行系统烧录部署。

********************************************************/

    extern void update_all(void);

    if(check_menu_update_from_sd()==0)//update mode

    {

        puts ("[LEFT DOWN] update mode ");

        run_command("fdisk -c 0",0);

        update_all();

    }

    else

        puts ("[LEFT UP] boot mode ");


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

}




本文出自 “11664570” 博客,请务必保留此出处http://11674570.blog.51cto.com/11664570/1922441

uboot移植之九鼎提供的uboot的文件夹分析

...到的一些函数,这些函数都是硬件无关的,所以和我们的移植没多大关系(2)api_examples:api的示例代码(3)board:开发板相关的文件夹,这个文件夹里面存放的一个文件夹对应一款开发板或者是一个芯片厂商。我们在config配置... 查看详情

uboot移植之start.s分析

uboot的函数入口要查看链接脚本中ENTTRY的入口参数,我们这里的链接脚本在board/samsung/x210/u-boot.lds,这个文件里面的开头有一句ENTRY(_start),所以uboot的入口就是在_start这个标识的地方。 * Base codes by scsuh (sc.su... 查看详情

uboot移植之九鼎提供的uboot的文件分析

文件分析(1).gitignore:git管理工具相关的文件。(2)arm_config.mk:一个Makefile文件,将来会被Makefile里面的某句代码调用。(3)CHANGELOG、Changelog_Samsung、CHANGELOG-before-U-Boot-1.1.5:三个CHANELOG文件,其实就是该版本的uboot的变迁记录... 查看详情

uboot移植之主makefile分析

1:#uboot的版本号VERSION   =1            #主版本号PATCHLEVEL =3         #次版本号SUBLEVE 查看详情

uboot移植之tag传参

1:什么是tag(1)tag是一种数据结构,用于uboot向内核传递参数,一个tag代表了一个参数,uboot在向kernel传参时,就是通过一个个tag来实现的。(2)每个tag都有一个tag_header(一个结构体),包含了tag的类型和大小,然后tag中剩余... 查看详情

uboot移植之uboot中的sd卡驱动解析

1:地址对硬件操作的影响    (1)操作系统(指的是linux)下MMU肯定是开启的,也就是说linux驱动中肯定都使用的是虚拟地址。而纯裸机程序中根本不会开MMU,全部使用的是物理地址。这是裸机下和驱动中操控硬件的... 查看详情

x-003friendlyarmtiny4412uboot移植之添加相应目录文件

  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 查看详情

x-005friendlyarmtiny4412uboot移植之时钟初始化

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 查看详情

x-009friendlyarmtiny4412uboot移植之sdcard用起来kernelboot起来

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 查看详情

uboot启动源码分析

...化 6、拷贝uboot到ram 7、清除bss段 8、setPreLoadedONRAM 9、执行start_armboot,进入第二阶段入口 问题: 1、汇编中标号的实质? 2、内存控制参数拷贝过程中,源地址的计算问题? 3、时钟参数的计算问题? 二、第二阶段 start_armboot()... 查看详情

一,移植uboot,分析uboot启动流程(代码片段)

文档时间:2018-08-08交叉编译器:arm-linux-gcc-4.3.2Ubuntu版本:16.04uboot版本:2013.10uboot启动流程简要如下:    a,设置CPU为管理模式    b,关闭看门狗    c,关闭中断    d,设置时钟频率    e,进入lowlevel_init.S,... 查看详情

x-001friendlyarmtiny4412uboot移植前奏

...链:linaro提供的gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabi要移植的u-boot版本:u-boot-2016-09参考u-boot版本:友善之臂提供的u-boot-2010-12Tiny4412开发板硬件版本 查看详情

uboot移植:移植前的准备工作

一:uboot的来源    uboot的获取途径一般有三种,一种是uboot官方提供的这uboot,这里面是针对多种开发板和芯片的uboot代码,是全球各地上传,然后由uboot官方提供的,因为它里面包含了很多种开发板的uboot,所以文... 查看详情

u-boot启动流程分析--start_armboot函数

...上读到RAM空间中  为内核设置启动参数  调用内核从start_armboot开始,程序流程如图  查看详情

uboot移植一uboot架构分析

开发环境:  1.开发板mini2440  2. u-boot-2010.12参考i资料:https://blog.csdn.net/androidbbc/article/details/50961163     http://www.cnblogs.com/kele-dad/p/8969174.html一、下载u-boot-2010.12,并且解压二、分析u-boor-2010.12a 查看详情

powerpcuboot链接脚本大改造

在做完了linux由arm处理器核移植到ppc处理器核的工作后,还需要进行uboot的移植,之前对uboot的分析文章都是基于arm平台,感兴趣的朋友可以看看,链接如下:http://blog.csdn.net/column/details/uboot-note.html借这次ppc移... 查看详情

三,移植uboot-支持nand启动

文档时间:2018-08-10交叉编译器:arm-linux-gcc-4.3.2Ubuntu版本:16.04uboot版本:2013.10  查看详情

uboot配置编译源码分析

一、X210官方uboot配置编译实践1、找到官方移植好的uboot(BSP概念)(1)源头的源代码是uboot官网下载的。这个下载的源代码可能没有你当前使用的开发板的移植,甚至找不到当前开发板使用的SoC对应的移植版本。(2)SoC厂商在推出一... 查看详情