U-boot(四):start_armboot

        本文主要探讨210的uboot启动的第二阶段,主要函数为start_armboot。

uboot
    一阶段初始化SoC内部部件(看门狗、时钟等),初始化DDR,重定位
    二阶段初始化其余硬件(iNand、网卡芯片···)以及命令、环境变量等···
    启动打印硬件信息,进入bootdelay,读秒完后执行bootcmd启动内核或打断读秒进入命名状态

     一阶段为汇编,在SRAM中,主要在SoC内部,二阶段为C阶,在DRAM中,主要在Board内部


start_armboot(函数在uboot/lib_arm/board.c(444~908))

    全局变量

            全局变量定义

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
    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;
    phys_size_t    ram_size;    /* RAM size */
    unsigned long    reset_status;    /* reset status register at boot */
    #endif
    void        **jt;        /* jump table */
    } gd_t;


                    定义全局变量gd到寄存器r8中,为gd_t类型变量指针
                    gd_t定义在include/asm-arm/global_data.h中
                    gd_t中定义全局变量,其中bd_t结构体包含硬件参数(波特率,IP,mac,机器码,启动参数,环境变量,DDR,网卡)


            全局变量内存分配    

#ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */
    ulong gd_base;

    gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);
    #ifdef CONFIG_USE_IRQ
    gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
    #endif
    gd = (gd_t*)gd_base;
    #else
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
    #endif

    gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);
    gd = (gd_t*)gd_base;
    #define CFG_UBOOT_BASE        0xc3e00000                
    #define CFG_UBOOT_SIZE        (2*1024*1024)             
    #define CFG_MALLOC_LEN        (CFG_ENV_SIZE + 896*1024)     
    #define CFG_ENV_SIZE          0x4000    //(16字节)
    #define CFG_STACK_SIZE        512*1024   

         
                    uboot        CFG_UBOOT_BASE(2MB)
                    堆             CFG_MALLOC_LEN(912KB)
                    栈             CFG_STACK_SIZE(512KB)
                    gd             sizeof(gd_t)(36字节)
                    bd             sizeof(bd_t)(44字节左右)


                    全局变量内存清空 

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

    monitor_flash_len = _bss_start - _armboot_start;


board级硬件初始化

    init_fnc_t **init_fnc_ptr;

    typedef int (init_fnc_t) (void); //函数类型

            init_fnc_ptr是二重函数指针,用来指向函数指针数组

   for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }

  

 init_fnc_t *init_sequence[] = {
        cpu_init,        /* basic cpu dependent setup */
        #if defined(CONFIG_SKIP_RELOCATE_UBOOT)
        reloc_init,        /* Set the relocation done flag, must
                   do this AFTER cpu_init(), but as soon
                   as possible */
        #endif
        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 */
        #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 */
        display_dram_config,
        NULL,
    };

            cpu_init

    int cpu_init (void)
    {
        /*
         * setup up stacks if necessary
         */
        #ifdef CONFIG_USE_IRQ
        IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
        FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
        #endif
        return 0;
    }

                    空函数,cpu初始化在一阶段cpu_init_crit函数中完成(汇编)

    
            board_init(uboot/board/samsung/x210/x210.c)

    int board_init(void)
    {
        DECLARE_GLOBAL_DATA_PTR;
        #ifdef CONFIG_DRIVER_SMC911X
        smc9115_pre_init();
        #endif

        #ifdef CONFIG_DRIVER_DM9000
        dm9000_pre_init();
        #endif

        gd->bd->bi_arch_number = MACH_TYPE;
        gd->bd->bi_boot_params = (PHYS_SDRAM_1+0x100);

        return 0;
    }
    static void dm9000_pre_init(void)
    {
        unsigned int tmp;

        #if defined(DM9000_16BIT_DATA)
        SROM_BW_REG &= ~(0xf << 4);
        SROM_BW_REG |= (1<<7) | (1<<6) | (1<<5) | (1<<4);
        #else
        SROM_BW_REG &= ~(0xf << 4);
        SROM_BW_REG |= (0<<6) | (0<<5) | (0<<4);
        #endif
        SROM_BC1_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0));//uboot
        //SROM_BC1_REG = ((0<<28)|(0<<24)|(5<<16)|(0<<12)|(0<<8)|(0<<4)|(0<<0));//kernel
        tmp = MP01CON_REG;
        tmp &=~(0xf<<4);
        tmp |=(2<<4);
        MP01CON_REG = tmp;
    }


            dm9000_pre_init函数为网卡初始化(GPIO和端口配置非驱动),gd->bd->bi_arch_number定义机器码,gd->bd->bi_boot_params为内核启动传递参数内存地址(0x30000100)

  

  gd->bd->bi_boot_params = (PHYS_SDRAM_1+0x100);

    

#define CONFIG_NR_DRAM_BANKS    2          /* we have 2 bank of DRAM */
    #define SDRAM_BANK_SIZE         0x10000000 //256   /*0x20000000*/    /* 512 MB */
    #define PHYS_SDRAM_1            MEMORY_BASE_ADDRESS /* SDRAM Bank #1 */
    #define PHYS_SDRAM_1_SIZE       SDRAM_BANK_SIZE
    #define PHYS_SDRAM_2            MEMORY_BASE_ADDRESS2 /* SDRAM Bank #2 */
    #define PHYS_SDRAM_2_SIZE       SDRAM_BANK_SIZE
 #define CFG_FLASH_BASE        0x80000000
#define MEMORY_BASE_ADDRESS    0x30000000

                    一阶段汇编lowlevel_init初始化DDR为硬件初始化(gpio),DDR可工作,此处为DDR属性配置、地址初始化
                    x210_sd.h(496~501)宏定义DDR参数(内存个数,内存起始地址,内存长度)

            

                interrupt_init

    int interrupt_init(void)
    {

        S5PC11X_TIMERS *const timers = S5PC11X_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  @ 66 MHz
             */
            timer_load_val = get_PCLK() / (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 & ~0x00700000) | TCON_4_AUTO | TCON_4_UPDATE;
        /* auto load, start Timer 4 */
        timers->TCON = (timers->TCON & ~0x00700000) | TCON_4_AUTO | COUNT_4_ON;
        timestamp = 0;


        return (0);
    }

                    初始化定时器(Timer4),210有5个PWM定时器,Timer0-timer3对应PWM信号输出引脚,Timer4无引脚用来做计时


            env_init

    int env_init(void)
    {
        #if defined(ENV_IS_EMBEDDED)
        ulong total;
        int crc1_ok = 0, crc2_ok = 0;
        env_t *tmp_env1, *tmp_env2;

        total = CFG_ENV_SIZE;

        tmp_env1 = env_ptr;
        tmp_env2 = (env_t *)((ulong)env_ptr + CFG_ENV_SIZE);

        crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
        crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);

        if (!crc1_ok && !crc2_ok)
            gd->env_valid = 0;
        else if(crc1_ok && !crc2_ok)
            gd->env_valid = 1;
        else if(!crc1_ok && crc2_ok)
            gd->env_valid = 2;
        else {
            /* both ok - check serial */
            if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
                gd->env_valid = 2;
            else if(tmp_env2->flags == 255 && tmp_env1->flags == 0)
                gd->env_valid = 1;
            else if(tmp_env1->flags > tmp_env2->flags)
                gd->env_valid = 1;
            else if(tmp_env2->flags > tmp_env1->flags)
                gd->env_valid = 2;
            else /* flags are equal - almost impossible */
                gd->env_valid = 1;
        }

        if (gd->env_valid == 1)
            env_ptr = tmp_env1;
        else if (gd->env_valid == 2)
            env_ptr = tmp_env2;
        #else /* ENV_IS_EMBEDDED */
            gd->env_addr  = (ulong)&default_environment[0];
            gd->env_valid = 1;
        #endif /* ENV_IS_EMBEDDED */

        return (0);
    }


                    环境变量初始化,开发板可能包含不同启动介质(norflash、nandflash、inand、sd卡·····),故env的存取需要支持多种存储方式,210使用的为inand(env_movi.c)
                    函数有无环境变量(无),start_armboot函数(776)调用env_relocate将环境变量从SD卡重定位到DDR,重定位从SD卡中读取

    /* initialize environment */
    env_relocate ();


            init_baudrate
    

static int init_baudrate (void)
    {
        char tmp[64];    /* long enough for environment variables */
        int i = getenv_r ("baudrate", tmp, sizeof (tmp));
        gd->bd->bi_baudrate = gd->baudrate = (i > 0)
            ? (int) simple_strtoul (tmp, NULL, 10)
            : CONFIG_BAUDRATE;

        return (0);
    }


    int getenv_r (char *name, char *buf, unsigned len)
    {
        int i, nxt;

        for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
        int val, n;

        for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {
            if (nxt >= CFG_ENV_SIZE) {
                return (-1);
            }
        }
        if ((val=envmatch((uchar *)name, i)) < 0)
            continue;
        /* found; copy out */
        n = 0;
        while ((len > n++) && (*buf++ = env_get_char(val++)) != '\0')
            ;
        if (len == n)
            *buf = '\0';
        return (n);
        }
        return (-1);
    }

                    初始化串口通信的波特率,getenv_r函数读取环境变量值,读取环境变量值为字符串类型在转成相应类型(simple_strtoul将字符串转int)
                    读取环境变量中波特率值(gd->baudrate,gd->bd->bi_baudrate),若没有则在x210_sd.h中CONFIG_BAUDRATE值作为波特率(环境变量优先级高)

    

        serial_init    

int serial_init(void)
    {
        serial_setbrg();

        return (0);
    }

    空函数,一阶段汇编lowlevel_init中uart_asm_init初始化串口


    console_init_f

    int console_init_f (void)
    {
        gd->have_console = 1;

        #ifdef CONFIG_SILENT_CONSOLE
        if (getenv("silent") != NULL)
            gd->flags |= GD_FLG_SILENT;
        #endif

        return (0);
    }

                    console_init_f是console(控制台)一阶段初始化


            display_banner

 static int display_banner (void)
    {
        printf ("\n\n%s\n\n", version_string);
        debug ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
            _armboot_start, _bss_start, _bss_end);
        #ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */
            debug("\t\bMalloc and Stack is above the U-Boot Code.\n");
        #else
            debug("\t\bMalloc and Stack is below the U-Boot Code.\n");
        #endif
        #ifdef CONFIG_MODEM_SUPPORT
            debug ("Modem Support enabled\n");
        #endif
        #ifdef CONFIG_USE_IRQ
            debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
            debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
        #endif
        open_backlight();//lqm.
        //open_gprs();

        return (0);
    }

                    串口输出显示uboot的logo,U_BOOT_VERSION在makefile中定义,编译时生成到include/version_autogenerated.h的宏中


    print_cpuinfo


    

int print_cpuinfo(void)
    {
        uint set_speed;
        uint tmp;
        uchar result_set;

        #if defined(CONFIG_CLK_533_133_100_100)
            set_speed = 53300;
        #elif defined(CONFIG_CLK_667_166_166_133)
            set_speed = 66700;
        #elif defined(CONFIG_CLK_800_200_166_133)
            set_speed = 80000;
        #elif defined(CONFIG_CLK_1000_200_166_133)
            set_speed = 100000;
        #elif defined(CONFIG_CLK_1200_200_166_133)
            set_speed = 120000;
        #else
            set_speed = 100000;
            printf("Any CONFIG_CLK_XXX is not enabled\n");
        #endif
        tmp = (set_speed / (get_ARMCLK()/1000000));

        if((tmp < 105) && (tmp > 95)){
            result_set = 1;
        } else {
            result_set = 0;
        }

    #ifdef CONFIG_MCP_SINGLE
        printf("\nCPU:  S5PV210@%ldMHz(%s)\n", get_ARMCLK()/1000000, ((result_set == 1) ? "OK" : "FAIL"));
    #else
        printf("\nCPU:  S5PC110@%ldMHz(%s)\n", get_ARMCLK()/1000000, ((result_set == 1) ? "OK" : "FAIL"));
    #endif
        printf("        APLL = %ldMHz, HclkMsys = %ldMHz, PclkMsys = %ldMHz\n",
            get_FCLK()/1000000, get_HCLK()/1000000, get_PCLK()/1000000);
    #if 1
        printf("    MPLL = %ldMHz, EPLL = %ldMHz\n",
            get_MPLL_CLK()/1000000, get_PLLCLK(EPLL)/1000000);
        printf("               HclkDsys = %ldMHz, PclkDsys = %ldMHz\n",
            get_HCLKD()/1000000, get_PCLKD()/1000000);
        printf("               HclkPsys = %ldMHz, PclkPsys = %ldMHz\n",
            get_HCLKP()/1000000, get_PCLKP()/1000000);
        printf("               SCLKA2M  = %ldMHz\n", get_SCLKA2M()/1000000);
    #endif
        puts("Serial = CLKUART ");

    return 0;
}
CPU:  S5PV210@1000MHz(OK)
APLL = 1000MHz, HclkMsys = 200MHz, PclkMsys = 100MHz
MPLL = 667MHz, EPLL = 96MHz
HclkDsys = 166MHz, PclkDsys = 83MHz
HclkPsys = 133MHz, PclkPsys = 66MHz
SCLKA2M  = 200MHz
Serial = CLKUART 

                print_cpuinfo打印uboot启动时的cpu参数信息


            checkboard

  int checkboard(void)
    {
        #ifdef CONFIG_MCP_SINGLE
        #if defined(CONFIG_VOGUES)
            printf("\nBoard:   VOGUESV210\n");
        #else
            printf("\nBoard:   X210\n");
        #endif //CONFIG_VOGUES
        #else
            printf("\nBoard:   X210\n");
        #endif
            return (0);
    }

                打印开发板名字


    init_func_i2c

 

   static int init_func_i2c (void)
    {
        puts ("I2C:   ");
        i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
        puts ("ready\n");
        return (0);
    }


            X210的uboot未使用I2C,此函数无用

    dram_init

    int dram_init(void)
    {
        DECLARE_GLOBAL_DATA_PTR;

        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
        gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;

        #if defined(PHYS_SDRAM_2)
        gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
        gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
        #endif

        #if defined(PHYS_SDRAM_3)
        gd->bd->bi_dram[2].start = PHYS_SDRAM_3;
        gd->bd->bi_dram[2].size = PHYS_SDRAM_3_SIZE;
        #endif

        return 0;
    }

                    dram_init在一阶段初始化low_level_init中初始化,此处为给全局变量定义赋值,记录DDR配置(gd->bd->bi_dram)

    display_dram_config

    static int display_dram_config (void)
    {
        int i;

        #ifdef DEBUG
        puts ("RAM Configuration:\n");

        for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
            printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
            print_size (gd->bd->bi_dram[i].size, "\n");
        }
        #else
            ulong size = 0;

            for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
                size += gd->bd->bi_dram[i].size;
        }

        puts("DRAM:    ");
        print_size(size, "\n");
        #endif

        return (0);
    }


                    打印显示dram配置信息,uboot启动信息(DRAM:    512 MB)在该处打印
                    uboot命令bdinfo,打印的位gd->bd中记录硬件全局变量(DDR信息)

    DRAM bank   = 0x00000000
    -> start    = 0x30000000
    -> size     = 0x10000000
    DRAM bank   = 0x00000001
    -> start    = 0x40000000
    -> size     = 0x10000000

堆管理器初始化

static 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);
}

        初始化uboot堆管理器,DDR内存中堆预留896KB


mmc初始化

#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\n");
    #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)\n");
    #endif

    #if defined(CONFIG_CMD_NAND)
        puts("NAND:    ");
        nand_init();
    #endif

    #endif /* CONFIG_X210 */

            mmc_initialize是MMC基础初始化(SoC内部的SD/MMC控制器),函数在uboot/drivers/mmc/mmc.c
            uboot对硬件操作(网卡、SD卡···)是用linux内核驱动实现的(drivers目录)
            mmc_initialize初始化函数实际调用board_mmc_init和cpu_mmc_init初始化
            cpu_mmc_init在uboot/cpu/s5pc11x/cpu.c,实际调用drivers/mmc/s3c_mmcxxx.c驱动代码初始化MMC


环境变量重定位

      

  /* initialize environment */
    env_relocate ();

            SD卡有独立扇区作为环境变量存储区域,uboot代码中包含默认环境变量,运行时会被读取到DDR环境变量中,在写入SD卡中


IP,MAC地址
  

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

    /* MAC Address */
    {
        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
    }


            初始化全局变量中的IP和MAC(gd->bd)

devices_init

int devices_init (void)
{
    #ifndef CONFIG_ARM     /* already relocated for current ARM implementation */
    ulong relocation_offset = gd->reloc_off;
    int i;

    /* relocate device name pointers */
    for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
        stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
                        relocation_offset);
    }
    #endif

    /* Initialize the list */
    devlist = ListCreate (sizeof (device_t));

    if (devlist == NULL) {
        eputs ("Cannot initialize the list of devices!\n");
        return -1;
    }
    #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
        i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
    #endif
    #ifdef CONFIG_LCD
        drv_lcd_init ();
    #endif
    #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
        drv_video_init ();
    #endif
    #ifdef CONFIG_KEYBOARD
        drv_keyboard_init ();
    #endif
    #ifdef CONFIG_LOGBUFFER
        drv_logbuff_init ();
    #endif
        drv_system_init ();
    #ifdef CONFIG_SERIAL_MULTI
        serial_devices_init ();
    #endif
    #ifdef CONFIG_USB_TTY
        drv_usbtty_init ();
    #endif
    #ifdef CONFIG_NETCONSOLE
        drv_nc_init ();
    #endif

    return (0);
}

        函数执行所有从linux内核中继承来的那些硬件驱动的初始化函数


跳转表

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
}

            未使用

控制台二阶段初始化

/* Called after the relocation - use desired console functions */
int console_init_r (void)
{
    device_t *inputdev = NULL, *outputdev = NULL;
    int i, items = ListNumItems (devlist);

    #ifdef CONFIG_SPLASH_SCREEN
    /* suppress all output if splash screen is enabled and we have
       a bmp to display                                            */
    if (getenv("splashimage") != NULL)
        gd->flags |= GD_FLG_SILENT;
    #endif

    /* Scan devices looking for input and output devices */
    for (i = 1;
         (i <= items) && ((inputdev == NULL) || (outputdev == NULL));
         i++
        ) {
        device_t *dev = ListGetPtrToItem (devlist, i);

        if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
            inputdev = dev;
        }
        if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
            outputdev = dev;
        }
    }

    /* Initializes output console first */
    if (outputdev != NULL) {
        console_setfile (stdout, outputdev);
        console_setfile (stderr, outputdev);
    }

    /* Initializes input console */
    if (inputdev != NULL) {
        console_setfile (stdin, inputdev);
    }

    gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */

    #ifndef CFG_CONSOLE_INFO_QUIET
    /* Print information */
    puts ("In:      ");
    if (stdio_devices[stdin] == NULL) {
        puts ("No input devices available!\n");
    } else {
        printf ("%s\n", stdio_devices[stdin]->name);
    }

    puts ("Out:     ");
    if (stdio_devices[stdout] == NULL) {
        puts ("No output devices available!\n");
    } else {
        printf ("%s\n", stdio_devices[stdout]->name);
    }

    puts ("Err:     ");
    if (stdio_devices[stderr] == NULL) {
        puts ("No error devices available!\n");
    } else {
        printf ("%s\n", stdio_devices[stderr]->name);
    }
    #endif /* CFG_CONSOLE_INFO_QUIET */

    #ifndef    CONFIG_X210
    /* Setting environment variables */
    for (i = 0; i < 3; i++) {
        setenv (stdio_names[i], stdio_devices[i]->name);
    }
    #endif

    #if 0
    /* If nothing usable installed, use only the initial console */
    if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
        return (0);
    #endif

    return (0);
}

        console_init_r初始化数据结构配置值


使能中断

void enable_interrupts (void)
{
    return;
}


初始化网卡地址

#ifdef CONFIG_DRIVER_CS8900
    cs8900_get_enetaddr (gd->bd->bi_enetaddr);
#endif

初始化网卡地址(gd->bd)


loadaddr和bootfile

/* 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));
    }


                初始化环境变量,启动linux内核使用该值

空函数

#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\n");
    reset_phy();
#endif
#endif

#if defined(CONFIG_CMD_IDE)
    puts("IDE:   ");
    ide_init();
#endif


        board_late_init,eth_initialize空函数

LCD初始化和logo显示

#ifdef CONFIG_MPAD
    extern int x210_preboot_init(void);
    x210_preboot_init();
#endif

extern void mpadfb_init(void);
int x210_preboot_init(void)
{
    mpadfb_init();
    return 1;
}
void mpadfb_init()
{
    //    unsigned short int *pFB;//杩欓噷涓€瀹氳鐢╯hort绫诲瀷!
    //    int i;
    fb_init();//lqm masked for test
    lcd_port_init();
    lcd_reg_init();
    #ifdef CONFIG_CHECK_X210CV3
        init_logo();
    #endif
        display_logo(&s5pv210_fb);
    #if(DISP_MODE == TRULY043)
        backlight_brigness_init(0);
    #else//AT070TN92
        backlight_brigness_init(1);
    #endif

    //    pFB = (unsigned short int *)CFG_LCD_FBUFFER;
    /*
        for(i=0; i<800*480; i++)
            *pFB++ = 0xf800;
        */
    /*     for(i=0; i<800*100; i++)
        *pFB++ = 0xf800;
     for(i=800*100; i<800*200; i++)
        *pFB++ = 0x07e0;
     for(i=800*200; i<800*480; i++)
        *pFB++ = 0x001f;
    */

    #if(DISP_MODE == TRULY043)
        writel((readl(GPF3DAT) & ~(0x1<<5)) | (0x1<<5), GPF3DAT);
    #endif
}


快速烧录(镜像升级)

/* check menukey to update from sd */
    extern void update_all(void);
    if(check_menu_update_from_sd()==0)//update mode
    {
        puts ("[LEFT DOWN] update mode\n");
        run_command("fdisk -c 0",0);
        update_all();
    }
    else
        puts ("[LEFT UP] boot mode\n");

        镜像烧录到SD卡,开机按键LEFT键烧录到iNand中

死循环

    for (;;) {
        main_loop ();
    }

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


        开机延时,命令解析执行

 

demo:

        烧录修改并编译的uboot

make distclean && make x210_sd_config && make

cd sd_fusing/

make clean

./sd_fusing.sh /dev/sdb

        结果示例:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/183524.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二十一、文档操作

目录 一、添加文档 1、编写代码 2、运行并查看 二、查询文档 1、编写代码 2、运行并查看 三、删除文档 1、编写代码 2、运行并查看 四、修改文档 方式一&#xff1a;全量修改&#xff0c;会删除旧文档&#xff0c;添加新文档 方式二&#xff1a;局部修改。增量修改&…

nodejs 如何将 Buffer 数据转为 String

问题说明 使用webSocket的时候出现了一个问题&#xff0c;前端小程序和nodejs后端建立websocket连接后&#xff0c;使用send方法发送到后端为buffer格式&#xff0c;以下为我前后端代码 1、前端小程序代码 //创建webSocket连接 const socket uni.connectSocket({url: wss…

工作中死循环害死人

背景&#xff1a;研发的一段代码&#xff0c;循环一直没有跳出&#xff0c;导致其他依赖逻辑有问题&#xff0c;生产事故导致9万左右数据不正常。 这里while&#xff08;true&#xff09;真的不要轻易用 &#xff0c;后来研发改动限制mysql的id切分步长&#xff0c;控制不会有数…

FreeRTOS源码阅读笔记4--semphr.h

信号量是特殊的队列--无法存储消息的队列&#xff0c;相关的接口函数声明在semphr.h中&#xff0c;通过宏定义替换队列函数实现。 4.1创建二值信号量xSemaphoreCreateBinary() 4.1.1函数原型 queueQUEUE_TYPE_BINARY_SEMAPHORE&#xff1a;一个宏&#xff0c;表示创建队列的…

gitt开源项目的意义,公司为什么会对在gitt上有开源项目的人更大机会

Git是一种分布式版本控制系统&#xff0c;它可以帮助程序员管理代码的历史版本和协同工作。同时&#xff0c;Git也成为了开源项目的主要托管平台之一。Git的开源项目意义重大&#xff0c;因为这种开源项目托管平台可以帮助开发者将代码和项目分享给全球的开发者&#xff0c;并且…

node版本管理工具-nvm

1、 下载地址 https://github.com/coreybutler/nvm-windows/releases/tag/1.1.11 2、 选择安装地址不能有空格&#xff0c;中文 3、 使用命令

微服务学习(十二):安装Minio

微服务学习&#xff08;十二&#xff09;&#xff1a;安装Minio 一、简介 MinIO 是一款基于Go语言发开的高性能、分布式的对象存储系统。客户端支持Java,Net,Python,Javacript, Golang语言。MinIO系统&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视…

linux上的通用拍照程序

最近因为工作需要&#xff0c;在ubuntu上开发了一个拍照程序。 为了找到合适的功能研究了好几种实现方式&#xff0c;在这里记录一下。 目录 太长不看版 探索过程 v4l2 QT opencv4.2 打开摄像头 为什么不直接打开第一个视频节点 获取所有分辨率 切换摄像头 太长不看…

MySQL错误之ONLY_FULL_GROUP_BY

报错信息&#xff1a; 翻译&#xff1a; 对该报错的解释 所以&#xff0c;实际上该报错是由于在SQL查询语句中有group by&#xff0c;而这个包含group by的SQL查询写的并不规范导致的&#xff0c;这个ONLY_FULL_GROUP_BY模式开启之后检查就会很严格&#xff0c;如果select列表…

51单片机IO口的四种工作状态切换

51单片机IO口的四种工作状态切换 1.概述 这篇文章介绍单片机IO引脚的四种工作模式&#xff0c;每个模式都有各自的用武之地&#xff0c;后面在驱动外设硬件时会用它不同的模式。 2.IO口四种工作模式介绍 PnM1PnM0I/O口工作模式00准双向口&#xff1a;灌电流达20mA&#xff…

leetcode:合并两个有序链表

题目描述 题目链接&#xff1a;21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 题目分析 这个算法思路很简单&#xff1a;就是直接找小尾插 定义一个tail和head&#xff0c;对比两个链表结点的val&#xff0c;小的尾插到tail->next&#xff0c;如果一个链表…

ebpf实战(一)-------监控udp延迟

问题背景: 为了分析udp数据通信中端到端的延迟,我们需要对整个通信链路的每个阶段进行监控,找出延迟最长的阶段. udp接收端有2个主要路径 1.数据包到达本机后&#xff0c;由软中断处理程序将数据包接收并放入udp socket的接收缓冲区 数据接收流程 2. 应用程序调用recvmsg等a…

如何解决tinder注册失败的问题?

tinder创立在2012年&#xff0c;是一款海外热门的交友软件。2020年&#xff0c;Tinder拥有620万用户和7500万月活跃用户。截至2021年&#xff0c;Tinder在全球范围内的匹配记录超过650亿。已成为全球最受欢迎的约会软件之一。 目前tinder暂时未对中国大陆开发使用&#xff0c;…

一个最简单的工业通讯数据分析例子

1.背景 对工业设备的通讯协议进行分析可以帮助我们更好地理解其工作原理和相关技术&#xff0c;并且有助于以下几个方面&#xff1a; 1. 优化工业设备的通讯效率&#xff1a;了解通讯协议的细节可以帮助我们找到通讯效率低下的原因并进行优化&#xff0c;提高设备的通讯效率和…

vue3实现验证码校验的功能

&#x1f4d3;最近想实现使用vue3实现一个简易的前端验证码校验的功能&#xff0c;就花了点时间实现了&#xff0c;这只是一个简易版的&#xff0c;但是用在项目中是没有啥问题的&#xff0c;废话不多说&#xff0c;先来看下最终实现的效果。 &#x1f4d3;现在让我们来一步一步…

java制作简单飞翔的鸟

创建三个包&#xff0c;存放代码。把图片放进文件中 APP包&#xff08;运行&#xff09; GameApp类 package APP; import mian.GameFrame;public class GameApp {public static void main(String[] args) {new GameFrame();} } mian包&#xff08;主内容&#xff09; Barri…

如何开发洗鞋店用的小程序

随着人们生活水平的提高&#xff0c;洗护行业是越来越细分化了&#xff0c;从最开始的干洗店包含洗护行业的所有服务到现在有专门为洗鞋开的店&#xff0c;如果开发一款洗鞋店用的小程序&#xff0c;可以实现用户在家下单直接有人上门取鞋的话&#xff0c;应该如何去开发呢&…

高质量短效SOCKS5代理IP是什么意思?作为技术你了解吗

小张是一位网络安全技术测试员&#xff0c;最近他接到了一个头疼的任务&#xff0c;那就是评估公司系统的安全性&#xff0c;因此他前来咨询&#xff0c;在得知SOCKS5代理IP可以帮他之后&#xff0c;他不禁产生疑问&#xff0c;这是什么原理&#xff1f;其实和小张一样的朋友不…

Lua脚本解决redis实现的分布式锁多条命令原子性问题

线程1现在持有锁之后&#xff0c;在执行业务逻辑过程中&#xff0c;他正准备删除锁&#xff0c;而且已经走到了条件判断的过程中&#xff0c;比如他已经拿到了当前这把锁确实是属于他自己的&#xff0c;正准备删除锁&#xff0c;但是此时他的锁到期了&#xff0c;那么此时线程2…

Flutter 小技巧之 3.16 升级最坑 M3 默认适配技巧

如果要说 Flutter 3.16 升级里是最坑的是什么&#xff1f;那我肯定要说是 Material 3 default &#xff08;M3&#xff09;。 倒不是说 M3 bug 多&#xff0c;也不是 M3 在 3.16 上使用起来多麻烦&#xff0c;因为虽然从 3.16 开始&#xff0c;MaterialApp 里的 useMaterial3 …