中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
uboot第二階段代碼詳細(xì)分析
Stage2 C語言代碼部分
lib_arm/board.c
中的start arm bootC語言開始的函數(shù)也是整個(gè)啟動(dòng)代碼中C語言的主函數(shù),同時(shí)還是整個(gè)u-bootarmboot)的主函數(shù),該函數(shù)只要完成如下操作:
1)調(diào)用一系列的初始化函數(shù)。
2)初始化Flash設(shè)備。
3)初始化系統(tǒng)內(nèi)存分配函數(shù)。
4)如果目標(biāo)系統(tǒng)擁有NAND設(shè)備,則初始化NAND設(shè)備。
5)如果目標(biāo)系統(tǒng)有顯示設(shè)備,則初始化該類設(shè)備。
6)初始化相關(guān)網(wǎng)絡(luò)設(shè)備,填寫IP、MAC地址等。
7)進(jìn)去命令循環(huán)(即整個(gè)boot的工作循環(huán)),接受用戶從串口輸入的命令,然后進(jìn)行相應(yīng)的工作。
對(duì)于內(nèi)核啟動(dòng)來說,這部分主要是完成全局?jǐn)?shù)據(jù)gd的初始化,以便內(nèi)核訪問

start_armbootU-Boot執(zhí)行的第一個(gè)C語言函數(shù),完成系統(tǒng)初始化工作,進(jìn)入主循環(huán),處理用戶輸入的命令。這里只簡要列出了主要執(zhí)行的函數(shù)流程:

  void start_armboot (void)

{

init_fnc_t **init_fnc_ptr;

char *s;

#ifndef CFG_NO_FLASH

ulong size;

#endif

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

unsigned long addr;

#endif

 

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

//獲取全局gd指針

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

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

__asm__ __volatile__("": : :"memory");

//清空該結(jié)構(gòu)體

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

//獲取bd_info結(jié)構(gòu)體指針

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

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

gd->flags |= GD_FLG_RELOC; //標(biāo)志位已經(jīng)重定向

//整個(gè)代碼區(qū)的長度

monitor_flash_len = _bss_start - _armboot_start;

//調(diào)用初始化函數(shù),用來初始化gd結(jié)構(gòu)體

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

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

hang ();

}

}

#ifndef CFG_NO_FLASH

/* configure available FLASH banks */

//board/smdk2410/flash.c配置flash

//從其實(shí)現(xiàn)來看,好像只是配置nor flash

size = flash_init ();//初始化flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS],nor flash基地址和扇區(qū)大小

//顯示flash信息

display_flash_config (size);

#endif /* CFG_NO_FLASH */

//定義顯示類型

#ifdef CONFIG_VFD

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

//按頁對(duì)其方式保留顯存

addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);

size = vfd_setmem (addr);

gd->fb_base = addr;//幀緩沖基地址

#endif /* CONFIG_VFD */

//顯示器為LCD,同上

#ifdef CONFIG_LCD

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

//初始化CFG_MALLOC_LEN大小空間

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

mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

 

//初始化nand flash,這是在nand flash啟動(dòng)的s3c2410移植u-boot的關(guān)鍵,根據(jù)flash時(shí)序編寫函數(shù)即可

//include/configs/smdk2410.h中的command definition中增加CONFIG_COMMANDSCFG_CMD_NAND命令

#if (CONFIG_CMD_NAND)

puts ("NAND: ");

nand_init(); //board/smdk2410/smdk2410.c,獲取nand的基地址和 大小信息

#endif

 

#ifdef CONFIG_HAS_DATAFLASH

AT91F_DataflashInit();

dataflash_print_info();

#endif

 

/* initialize environment */

//初始化環(huán)境參數(shù)

env_relocate ();

//framebuffer初始化

#ifdef CONFIG_VFD

/* must do this after the framebuffer is allocated */

drv_vfd_init();

#endif /* CONFIG_VFD */

//通過命令行參數(shù)傳遞獲取ip地址

/* IP Address */

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

//調(diào)用相應(yīng)驅(qū)動(dòng)函數(shù)對(duì)硬件設(shè)備進(jìn)行初始化

stdio_init (); /* get the devices list going標(biāo)準(zhǔn)輸入輸出和設(shè)備初始化. */

 

#ifdef CONFIG_CMC_PU2

load_sernum_ethaddr ();

#endif /* CONFIG_CMC_PU2 */

 

jumptable_init ();

//初始化串口

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

 

#if defined(CONFIG_MISC_INIT_R)

/* miscellaneous platform dependent initialisations */

misc_init_r ();

#endif

 

/* enable exceptions */

//啟用中斷

enable_interrupts ();

 

/* Perform network card initialisation if necessary */

//初始化網(wǎng)卡

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

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

load_addr = simple_strtoul (s, NULL, 16);

}

#if (CONFIG_COMMANDS & CFG_CMD_NET)

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

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

}

#endif /* CFG_CMD_NET */

 

#ifdef BOARD_LATE_INIT

board_late_init ();

#endif

#if (CONFIG_COMMANDS & CFG_CMD_NET)

#if defined(CONFIG_NET_MULTI)

puts ("Net: ");

#endif

eth_initialize(gd->bd);

#endif

/* main_loop() can return to retry autoboot, if so just run it again. */

for (;;) {

main_loop ();

}//end start_armboot

 

//下面詳細(xì)分析下init_sequence

 

typedef int (init_fnc_t) (void);  //注意這種用法,linux內(nèi)核中也經(jīng)常使用

 

int print_cpuinfo (void);

 

init_fnc_t *init_sequence[] = {

#if defined(CONFIG_ARCH_CPU_INIT)

       arch_cpu_init,             /* basic arch cpu dependent setup //cpu/arm920t/cpu.c中定義,該函數(shù)為空,因?yàn)闆]有采用IRQFIQ模式*/

#endif

       board_init,           /* basic board dependent ,初始化時(shí)鐘頻率,配置IO口,初始化全局?jǐn)?shù)據(jù)bd(如平臺(tái)號(hào),傳遞內(nèi)核參數(shù)的地址) ,setup   //board/smdk2410/smdk2410.c */

#if defined(CONFIG_USE_IRQ)

       interrupt_init,              /* set up exceptions */

#endif

       timer_init,            /* initialize timer 使用定時(shí)器4 cpu/arm920t/s3c24x0/timer.c */

#ifdef CONFIG_FSL_ESDHC

       get_clocks,

#endif

       env_init,              /* initialize environment   common/Env_nand.c   校驗(yàn)環(huán)境變量,并獲取環(huán)境變量的地址 */

       init_baudrate,            /* initialze baudrate settings 獲取波特率環(huán)境變量,初始化全局?jǐn)?shù)據(jù)的中波特率 /lib_arm/board.c */

       serial_init,            /* serial communications setup  driver/serial/serial_s3c24x0.c  初始化串口0,用于打印信息,該平臺(tái)只支持配置串口1來打印信息 */

       console_init_f,             /* stage 1 init of console */

       display_banner,          /* say that we are here  打印uboot代碼段和數(shù)據(jù)段地址信息 */

#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 ,獲取ram的地址和大小,banks  board/sunsang/smdk2410/smdk2410.c*/

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

       arm_pci_init,

#endif

//打印BANK的相關(guān)信息

       display_dram_config,  //lib_arm/board.c

       NULL,

};

 

int board_init (void)

{

;將時(shí)間相關(guān)的寄存器定義為結(jié)構(gòu)體S3C24X0_CLOCK_POWER,S3C24X0_GPIO也是一樣

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

;設(shè)置cpu時(shí)鐘

/* to reduce PLL lock time, adjust the LOCKTIME register */

clk_power->LOCKTIME = 0xFFFFFF;

 

/* configure MPLL */

//M_MDIV=0xA1,M_PDIV=0x3,M_SDIV=0x1

//這樣系統(tǒng)時(shí)鐘為202.80M

clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);

 

/* some delay between MPLL and UPLL */

delay (4000);

;USB時(shí)鐘為48M

/* configure UPLL */

clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);

 

/* some delay between MPLL and UPLL */

delay (8000);

;設(shè)置GPIO

/* set up the I/O ports */

gpio->GPACON = 0x007FFFFF;

gpio->GPBCON = 0x00044555;

gpio->GPBUP = 0x000007FF;

gpio->GPCCON = 0xAAAAAAAA;

gpio->GPCUP = 0x0000FFFF;

gpio->GPDCON = 0xAAAAAAAA;

gpio->GPDUP = 0x0000FFFF;

gpio->GPECON = 0xAAAAAAAA;

gpio->GPEUP = 0x0000FFFF;

gpio->GPFCON = 0x000055AA;

gpio->GPFUP = 0x000000FF;

gpio->GPGCON = 0xFF95FFBA;

gpio->GPGUP = 0x0000FFFF;

gpio->GPHCON = 0x002AFAAA;

gpio->GPHUP = 0x000007FF;

;初始化bd結(jié)構(gòu)體中的bi_arch_numberbi_boot_params

/* arch number of SMDK2410-Board 平臺(tái)號(hào),定義在include/asm-arm/mach-types.h */

gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

 

/* adress of boot parameters,內(nèi)核啟動(dòng)時(shí),傳遞給內(nèi)核的參數(shù) */

gd->bd->bi_boot_params = 0x30000100;

;啟用指令和數(shù)據(jù)cache

;通過對(duì)協(xié)處理器的操作了實(shí)現(xiàn)cache的使能

icache_enable();

dcache_enable();

 

return 0;

} //end board_init

 

int timer_init(void)

{

;獲取計(jì)時(shí)控制寄存器

       struct s3c24x0_timers *timers = s3c24x0_get_base_timers();

       ulong tmr;

;使用PWM定時(shí)器

       /* use PWM Timer 4 because it has no output */

       /* prescaler for Timer 4 is 16 */

       writel(0x0f00, &timers->TCFG0);

       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 15625 @ 50 MHz

               */

              timer_load_val = get_PCLK() / (2 * 16 * 100);

              timer_clk = get_PCLK() / (2 * 16);

       }

       /* load value for 10 ms timeout */

       lastdec = timer_load_val;

       writel(timer_load_val, &timers->TCNTB4);

       /* auto load, manual update of Timer 4 */

       tmr = (readl(&timers->TCON) & ~0x0700000) | 0x0600000;

       writel(tmr, &timers->TCON);

       /* auto load, start Timer 4  啟用定時(shí)器4做為系統(tǒng)定時(shí)器 */

       tmr = (tmr & ~0x0700000) | 0x0500000;

       writel(tmr, &timers->TCON);

       timestamp = 0;

 

       return (0);

} //end timer_init

 

static int env_init (void)

{

//這個(gè)是自己修改的,和源碼有所不同

       if(pbootflag==1) //by lht 這種情況是從nor啟動(dòng)

       {

              env_name_spec = "NOR";

              env_ptr=(env_t *)CONFIG_ENV_ADDR;

//#define CONFIG_ENV_ADDR         (CONFIG_SYS_FLASH_BASE + 0x0F0000) /* addr of environment */

              return nor_env_init();

       }

       else // nand 啟動(dòng)

       {

#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_NAND_ENV_DST)

       int crc1_ok = 0, crc2_ok = 0;

       env_t *tmp_env1;

 

#ifdef CONFIG_ENV_OFFSET_REDUND

       env_t *tmp_env2;

 

       tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE);

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

#endif

 

       tmp_env1 = env_ptr;

 

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

 

       if (!crc1_ok && !crc2_ok) {

              gd->env_addr  = 0;

              gd->env_valid = 0;

 

              return 0;

       } else if (crc1_ok && !crc2_ok) {

              gd->env_valid = 1;

       }

#ifdef CONFIG_ENV_OFFSET_REDUND

       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 == 2)

              env_ptr = tmp_env2;

       else

#endif

       if (gd->env_valid == 1)

              env_ptr = tmp_env1;

 

       gd->env_addr = (ulong)env_ptr->data;

 

#else /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */

       gd->env_addr  = (ulong)&default_environment[0]; //使用默認(rèn)環(huán)境變量,定義在common/env_common.c

       gd->env_valid = 1;

#endif /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */

       }

       return (0);

}   //end env_init

 

 

//如果參數(shù)中設(shè)置了波特率則利用參數(shù)用設(shè)置的波特率,否則利用默認(rèn)的CONFIG_BAUDRATE(115200)

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

}  //end init_baudrate

 

//初始化ram信息,設(shè)置起始地址和大小,從include/configs/smdk2410.h中獲取這些信息

//,這里只是對(duì)gd中的 bi_dram結(jié)構(gòu)中的兩個(gè)成員賦值,
//
也即BANK的起始地址和大小
int dram_init (void)
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;

return 0;
} // end dram_init

 

 

//顯示ram信息,其中的宏也是從include/configs/smdk2410.h中讀取

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

}  //end display_dram_config

//以上都是一些初始化的函數(shù),可以看出以上這些函數(shù)都是為了初始化一個(gè)全局的結(jié)構(gòu)體變量gd而執(zhí)行的,

//該變量地址由寄存器r8指向,該結(jié)構(gòu)體定義了開發(fā)板的相關(guān)硬件配置,在include/asm-arm/global_data.h

//定義

typedef struct  global_data {

       bd_t        *bd;  板子數(shù)據(jù)指針

       unsigned long  flags; //指示標(biāo)志,如設(shè)備已經(jīng)初始化標(biāo)志等

       unsigned long  baudrate; /* 串口初始化標(biāo)志*/

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

       unsigned long  env_addr;      /* 環(huán)境變量的起始地址 */

       unsigned long  env_valid;       /* 校驗(yàn)環(huán)境變量有效性的標(biāo)志位 */

       unsigned long  fb_base;  /* base address of frame buffer   幀緩沖基地址*/

#ifdef CONFIG_VFD

       unsigned char vfd_type; /* display type   lcd顯示設(shè)備類型 */

#endif

#ifdef CONFIG_FSL_ESDHC

       unsigned long  sdhc_clk;

#endif

       void        **jt;        /* jump table */

} gd_t;

 

typedef struct bd_info {

    int                  bi_baudrate;    /* serial console baudrate */

    unsigned long  bi_ip_addr;     /* IP Address  IP地址*/

    struct environment_s            *bi_env;

    ulong              bi_arch_number;    /* unique id for this board  唯一的平臺(tái)號(hào) */

    ulong              bi_boot_params;     /* where this board expects params  啟動(dòng)參數(shù)的地址*/

    struct                           /* RAM configuration  ram配置:起始地址和大小*/

    {

       ulong start;

       ulong size;

    }                   bi_dram[CONFIG_NR_DRAM_BANKS];

} bd_t;

 

 

 

typedef   struct environment_s {

       uint32_t   crc;        /* CRC32 over data bytes 校驗(yàn)碼       */

#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT

       unsigned char flags;             /* active/obsolete flags 是否有效 標(biāo)志位*/

#endif

       unsigned char data[ENV_SIZE]; /* Environment data  */

/**

#define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE)

#define CONFIG_ENV_SIZE              0x10000  /* Total Size of Environment Sector */

#define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x030000) /* addr of

environment */

 

} env_t;

環(huán)境變量指針 env_t *env_ptr = (env_t *)(&environment[0]);(common/env_flash.c)
 
 env_ptr指向環(huán)境參數(shù)區(qū),系統(tǒng)啟動(dòng)時(shí)默認(rèn)的環(huán)境參數(shù)environment[],定義在common/environment.c中?!?/span>

 
 參數(shù)解釋:
    bootdelay
定義執(zhí)行自動(dòng)啟動(dòng)的等候秒數(shù)
    baudrate
定義串口控制臺(tái)的波特率
    netmask
定義以太網(wǎng)接口的掩碼
    ethaddr
定義以太網(wǎng)接口的MAC地址

    bootfile
定義缺省的下載文件

    bootargs
定義傳遞給Linux內(nèi)核的命令行參數(shù)

    bootcmd
定義自動(dòng)啟動(dòng)時(shí)執(zhí)行的幾條命令

    serverip
定義tftp服務(wù)器端的IP地址

    ipaddr
定義本地的IP地址
    stdin
定義標(biāo)準(zhǔn)輸入設(shè)備,一般是串口

    stdout
定義標(biāo)準(zhǔn)輸出設(shè)備,一般是串口

    stderr
定義標(biāo)準(zhǔn)出錯(cuò)信息輸出設(shè)備,一般是串口

 

}

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
uboot 分析之 啟動(dòng)流程
start_armboot分析
powerpc uboot啟動(dòng)流程分析
U-BOOT環(huán)境變量的獲取和保存的實(shí)現(xiàn)分析
【原】s3c2410 u
Warning - bad CRC or NAND, using default environment
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服