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_VFDunsigned char    vfd_type;    /* display type */#endif#if 0unsigned 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 */#endifvoid        **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_IRQgd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);#endifgd = (gd_t*)gd_base;#elsegd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));#endifgd_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, mustdo this AFTER cpu_init(), but as soonas possible */#endifboard_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,#endifdram_init,        /* configure available RAM banks */display_dram_config,NULL,};

            cpu_init

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

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

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

    int board_init(void){DECLARE_GLOBAL_DATA_PTR;#ifdef CONFIG_DRIVER_SMC911Xsmc9115_pre_init();#endif#ifdef CONFIG_DRIVER_DM9000dm9000_pre_init();#endifgd->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);#elseSROM_BW_REG &= ~(0xf << 4);SROM_BW_REG |= (0<<6) | (0<<5) | (0<<4);#endifSROM_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));//kerneltmp = 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_fint console_init_f (void){gd->have_console = 1;#ifdef CONFIG_SILENT_CONSOLEif (getenv("silent") != NULL)gd->flags |= GD_FLG_SILENT;#endifreturn (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");#elsedebug("\t\bMalloc and Stack is below the U-Boot Code.\n");#endif#ifdef CONFIG_MODEM_SUPPORTdebug ("Modem Support enabled\n");#endif#ifdef CONFIG_USE_IRQdebug ("IRQ Stack: %08lx\n", IRQ_STACK_START);debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);#endifopen_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;#elseset_speed = 100000;printf("Any CONFIG_CLK_XXX is not enabled\n");#endiftmp = (set_speed / (get_ARMCLK()/1000000));if((tmp < 105) && (tmp > 95)){result_set = 1;} else {result_set = 0;}#ifdef CONFIG_MCP_SINGLEprintf("\nCPU:  S5PV210@%ldMHz(%s)\n", get_ARMCLK()/1000000, ((result_set == 1) ? "OK" : "FAIL"));#elseprintf("\nCPU:  S5PC110@%ldMHz(%s)\n", get_ARMCLK()/1000000, ((result_set == 1) ? "OK" : "FAIL"));#endifprintf("        APLL = %ldMHz, HclkMsys = %ldMHz, PclkMsys = %ldMHz\n",get_FCLK()/1000000, get_HCLK()/1000000, get_PCLK()/1000000);#if 1printf("    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);#endifputs("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");#elseprintf("\nBoard:   X210\n");#endif //CONFIG_VOGUES#elseprintf("\nBoard:   X210\n");#endifreturn (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;#endifreturn 0;}

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

    display_dram_config

    static int display_dram_config (void){int i;#ifdef DEBUGputs ("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");}#elseulong size = 0;for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {size += gd->bd->bi_dram[i].size;}puts("DRAM:    ");print_size(size, "\n");#endifreturn (0);}


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

    DRAM bank   = 0x00000000-> start    = 0x30000000-> size     = 0x10000000DRAM 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_X210CV3check_flash_flag=0;//check inand error!#endif}#ifdef CONFIG_CHECK_X210CV3else{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_ETH1i = 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_LCDdrv_lcd_init ();#endif#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)drv_video_init ();#endif#ifdef CONFIG_KEYBOARDdrv_keyboard_init ();#endif#ifdef CONFIG_LOGBUFFERdrv_logbuff_init ();#endifdrv_system_init ();#ifdef CONFIG_SERIAL_MULTIserial_devices_init ();#endif#ifdef CONFIG_USB_TTYdrv_usbtty_init ();#endif#ifdef CONFIG_NETCONSOLEdrv_nc_init ();#endifreturn (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 havea 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);#endifreturn (0);
}

        console_init_r初始化数据结构配置值


使能中断

void enable_interrupts (void)
{return;
}


初始化网卡地址

#ifdef CONFIG_DRIVER_CS8900cs8900_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_INITboard_late_init ();
#endif
#if defined(CONFIG_CMD_NET)
#if defined(CONFIG_NET_MULTI)puts ("Net:   ");
#endifeth_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_MPADextern int x210_preboot_init(void);x210_preboot_init();
#endifextern 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 testlcd_port_init();lcd_reg_init();#ifdef CONFIG_CHECK_X210CV3init_logo();#endifdisplay_logo(&s5pv210_fb);#if(DISP_MODE == TRULY043)backlight_brigness_init(0);#else//AT070TN92backlight_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();}elseputs ("[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 && makecd sd_fusing/make clean./sd_fusing.sh /dev/sdb

        结果示例:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud Alibaba集成 Gateway(自定义负载均衡器)、Nacos(配置中心、注册中心)、loadbalancer

文章目录 POM依赖环境准备配置配置文件配置类 案例展示 POM依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.10</version><relativePath/></p…

百度ai试用

JMaven Central: com.baidu.aip:java-sdk (sonatype.com) Java sdk地址如上&#xff1a; 文心一言开发者 文心一言 (baidu.com) ERNIE Bot SDK提供便捷易用的接口&#xff0c;可以调用文心一言的能力&#xff0c;包含文本创作、通用对话、语义向量、AI作图等。 pip install…

什么是轻量应用服务器?可以从亚马逊云科技的优势入手了解

什么是轻量应用服务器&#xff1f; 随着如今各行各业对云计算的需求越来越多&#xff0c;云服务器也被越来越多的企业所广泛采用。其中&#xff0c;轻量应用服务器是一种简单、高效、可靠的云计算服务&#xff0c;能够为开发人员、企业和个人提供轻量级的虚拟专用服务器&#x…

Centos部署GitLab-备份恢复

1. 下载rpm包 wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-10.8.4-ce.0.el7.x86_64.rpm2. 安装依赖 yum -y install policycoreutils openssh-server openssh-clients postfix policycoreutils-python3. rpm安装 rpm -ivh gitlab-ce-10.8.4-ce.…

TCP 重传、滑动窗口、流量控制、拥塞控制的剖析

TCP 是一个可靠传输的协议&#xff0c;那它是如何保证可靠的呢&#xff1f; 为了实现可靠性传输&#xff0c;需要考虑很多事情&#xff0c;例如数据的破坏、丢包、重复以及分片顺序混乱等问题。如不能解决这些问题&#xff0c;也就无从谈起可靠传输。 那么&#xff0c;TCP 是…

zend studio 的主题安装、卸载和更新

zend studio的主题插件安装 我的zend studio版本是13.6 在Welcome页面右侧看到有好多插件可以安装&#xff0c;现在我们来安装主题&#xff0c;主题插件就是Eclipse Color Theme。先选中Eclipse Color Theme选项打勾&#xff0c;然后点击Apply changs 按钮进行安装。 安装完成…

亚马逊云科技向量数据库助力生成式AI成功落地实践探秘(一) ​

随着大语言模型效果明显提升&#xff0c;其相关的应用不断涌现呈现出越来越火爆的趋势。其中一种比较被广泛关注的技术路线是大语言模型&#xff08;LLM&#xff09;知识召回&#xff08;Knowledge Retrieval&#xff09;的方式&#xff0c;在私域知识问答方面可以很好的弥补通…

案例023:基于微信小程序的童装商城的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

Java常量池理论篇:Class常量池、运行时常量池、String常量池、基本类型常量池,intern方法1.6、1.7的区别

文章目录 Class常量池运行时常量池String常量池基本类型常量池Integer 常量池Long 常量池 加餐部分 Class常量池 每个Class字节码文件中包含类常量池用来存放字面量以及符号引用等信息。 运行时常量池 java文件被编译成class文件之后&#xff0c;也就是会生成我上面所说的 …

webshell之基于框架免杀

thinkphp array_map_recursive函数 array_map_recursive函数分析 这里存在一个call_user_func命令执行函数 免杀效果 B函数 免杀效果 B函数分析 exec函数分析 在exec函数用存在有个类调用&#xff0c;且所有的参数都可控 smarty_php_tag函数 免杀效果 smarty_php_tag函数分析…

【开源】基于Vue.js的数据可视化的智慧河南大屏

项目编号&#xff1a; S 059 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S059&#xff0c;文末获取源码。} 项目编号&#xff1a;S059&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 …

打印菱形-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第9讲。 打印菱形&#xff…

周转箱与工具柜的智能化应用

在当今制造业激烈竞争的市场中&#xff0c;6S管理方法作为提高企业竞争力的有力工具&#xff0c;与精益生产中的周转箱和工具柜相结合&#xff0c;将为企业带来更大的优势。通过实施6S管理方法&#xff0c;企业不仅能够提高生产效率、降低成本&#xff0c;还能够改善产品质量、…

GDPU 数据结构 天码行空11

文章目录 数据结构实验十一 图的创建与存储一、实验目的二、实验内容三、【实验源代码】&#x1f37b; CPP版&#x1f37b; c 语言版&#x1f37b; java版 四、【实验结果】五、【实验总结】 数据结构实验十一 图的创建与存储 一、实验目的 1、 理解图的存储结构与基本操作&a…

nf_conntrack内核模块常见问题

nf_conntrack内核模块常见问题 问题描述排查步骤前置条件&#xff1a;启用nf_conntrack内核模块检查nf_conntrack配置 解决办法1:半数减少nf_conntrack buckets的值解决办法2:加倍调大m.min_free_kbytes值解决办法3:Linux社区权威答复-忽略告警 问题描述 内核报错 falling bac…

什么是 npm —— 写给初学者的编程教程

原文链接&#xff1a; 什么是 npm —— 写给初学者的编程教程 自 2009 年以来&#xff0c;Node.js 一直席卷全球。成千上万个系统基于 Node.js 构建&#xff0c;促使开发者在社区宣称“JavaScript 正在吞噬软件”。 Node 成功的主要因素之一是它广受欢迎的软件包管理器——np…

前k个高频单词(C++实现)

前k个高频单词 题目思路代码代码讲解 题目 思路 通过统计字符串的出现次数&#xff0c;并根据出现次数和字典序对字符串进行排序&#xff0c;找出出现频率最高的前k个字符串。使用一个自定义的仿函数作为排序的比较函数&#xff0c;通过map容器进行统计&#xff0c;然后将结果…

前端已死?看看我的秋招上岸历程

背景 求职方向&#xff1a;web前端 技术栈&#xff1a;vue2、springboot&#xff08;学校开过课&#xff0c;简单的学习过&#xff09; 实习经历&#xff1a;两段&#xff0c;但都是实训类的&#xff0c;说白了就是类似培训&#xff0c;每次面试官问起时我也会坦诚交代&…

关于鸿蒙网络请求的问题

https://developer.huawei.com/consumer/cn/forum/topic/0204136145853212268?fid0102683795438680754 鸿蒙OS 代码 import http from ohos.net.http;export const httpUtils (url: string, data: any) > {return new Promise((resolve, reject) > {let httpRequest …

创意设计与个性化定制:酒精壁炉的独特之处

在当今家居装饰的潮流中&#xff0c;人们越来越注重个性化和创意&#xff0c;而酒精壁炉正是在这一趋势中崭露头角。它不仅成为家居的温馨之选&#xff0c;更因其设计的灵活性而成为创意焦点&#xff0c;吸引了越来越多注重家居设计的人群。 酒精壁炉的设计灵活性为家居注入了新…