您的位置:首页 > 其它

决定从头开始分析u-boot-1.1.4源码(三)

2017-05-29 17:33 369 查看
init_fnc_t *init_sequence[] = {

 cpu_init,  

 board_init,  

 interrupt_init,  

 env_init,  

 init_baudrate,  

 serial_init,  

 console_init_f,  

 display_banner,  

 dram_init,  

 display_dram_config,

#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)  

 checkboard,

#endif

 NULL,

};

谭浩强的书上写着,一维指针数组的定义形式为: 类型名  * 数组名[数组长度];

可见,这里的init_sequence也是指针数组,数组名为init_sequence,数组的每一个元素都为指针类型,在这里每个元素是指向函数的指针。init_fnc_ptr即为指向init_sequence指针数组的指针,结合起这里来就可以理解了.

下面就跳到数组的第一个函数cpu_init去执行:

int cpu_init (void)

{

#ifdef CONFIG_USE_IRQ

 DECLARE_GLOBAL_DATA_PTR;

 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;

}

实际上这里只是什么都不干,因为在u-boot-1.1.4\include\configs\smdk2410.h里没有定义CONFIG_USE_IRQ

#undef CONFIG_USE_IRQ   

接下来是board_init函数,先贴出代码稍后再分析:

int board_init (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

 

 clk_power->LOCKTIME = 0xFFFFFF;

 

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

 

 delay (4000);

 

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

 

 delay (8000);

 

 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;

 

 gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

 

 gd->bd->bi_boot_params = 0x30000100;

 icache_enable();

 dcache_enable();

 return 0;

}

首先这里有S3C24X0_CLOCK_POWER结构体类型,搜索到它是在u-boot-1.1.4\include\s3c24x0.h中定义的

typedef struct {

 S3C24X0_REG32 LOCKTIME;

 S3C24X0_REG32 MPLLCON;

 S3C24X0_REG32 UPLLCON;

 S3C24X0_REG32 CLKCON;

 S3C24X0_REG32 CLKSLOW;

 S3C24X0_REG32 CLKDIVN;

} S3C24X0_CLOCK_POWER;

其中S3C24X0_REG32在同一个文件中有定义:

typedef volatile u32 S3C24X0_REG32;

S3C24X0_GetBase_CLOCK_POWER在u-boot-1.1.4\include\s3c2410.h中定义如下:

static inline S3C24X0_CLOCK_POWER * const S3C24X0_GetBase_CLOCK_POWER(void)

{

 return (S3C24X0_CLOCK_POWER * const)S3C24X0_CLOCK_POWER_BASE;

}

S3C24X0_CLOCK_POWER_BASE也在同一个文件中定义:

#define S3C24X0_CLOCK_POWER_BASE 0x4C000000

这里的意思是所有寄存器都通过结构体变量来存取,而不像我们裸机编程是各个寄存器一个个的定义。S3C24X0_GPIO结构体同S3C24X0_CLOCK_POWER,这里不再详述.

接着设置时钟频率,设置I/O口,接下来,

 

 gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

这里回到我们的bd_t中,那里有个成员:bi_arch_number;

定义是这样的的:ulong         bi_arch_number; 

这里给它赋值.在u-boot-1.1.4\include\asm-arm\mach-types.h中#define MACH_TYPE_SMDK2410            193

这里的MACH_TYPE_SMDK2410应该到时传递给内核以用来识别开发板类型的.

 

 gd->bd->bi_boot_params = 0x30000100;

bi_boot_params为传递给内核的参数的地址.

接着设置指令cache,数据cache:

 icache_enable();

 dcache_enable();

这两个函数定义在u-boot-1.1.4\cpu\arm920t\cpu.c中

void icache_enable (void)

{

 ulong reg;

 reg = read_p15_c1 ();  

 cp_delay ();

 write_p15_c1 (reg | C1_IC);

}

void dcache_enable (void)

{

 ulong reg;

 reg = read_p15_c1 ();

 cp_delay ();

 write_p15_c1 (reg | C1_DC);

}

其中read_p15_c1在同一个文件中定义,mrc指令用英文这样记:mov cp to reg,这里是把cp15的寄存器1读到%0(不太清楚这个内嵌语法).

static unsigned long read_p15_c1 (void)

{

 unsigned long value;

 __asm__ __volatile__(

  "mrc p15, 0, %0, c1, c0, 0   @ read control reg\n"

  : "=r" (value)

  :

  : "memory");

#ifdef MMU_DEBUG

 printf ("p15/c1 is = lx\n", value);

#endif

 return value;

}

write_p15_c1 (reg | C1_IC);是设置指令cache,其中C1_IC在同一文件中定义#define C1_IC  (1<<12)  

write_p15_c1 (reg | C1_DC);是设置数据c
4000
ache,其中C1_DC在同一文件中定义#define C1_DC  (1<<2)  

static void write_p15_c1 (unsigned long value)

{

#ifdef MMU_DEBUG

 printf ("write lx to p15/c1\n", value);

#endif

 __asm__ __volatile__(

  "mcr p15, 0, %0, c1, c0, 0   @ write it back\n"

  :

  : "r" (value)

  : "memory");

 read_p15_c1 ();            

}

board_init函数到这里就分析完了,实际上就是设置了一些寄存器,如时钟,IO口,串口,机器类型,启动参数,指令cache,数据cache.

然后到interrupt_init了,

int interrupt_init (void)

{

 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();

 

 

 timers->TCFG0 = 0x0f00;

 if (timer_load_val == 0)

 {

  

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

 }

 

 lastdec = timers->TCNTB4 = timer_load_val;

 

 timers->TCON = (timers->TCON & ~0x0700000) | 0x600000;

 

 timers->TCON = (timers->TCON & ~0x0700000) | 0x500000;

 timestamp = 0;

 return (0);

}

结构体S3C24X0_TIMERS同前面的S3C24X0_CLOCK_POWER一样,也在u-boot-1.1.4\include\s3c24x0.h中定义

typedef struct {

 S3C24X0_REG32 TCFG0;

 S3C24X0_REG32 TCFG1;

 S3C24X0_REG32 TCON;

 S3C24X0_TIMER ch[4];

 S3C24X0_REG32 TCNTB4;

 S3C24X0_REG32 TCNTO4;

} S3C24X0_TIMERS;

这里的寄存器没什么,对照2410数据手册就知道怎么设置了.其中的S3C24X0_GetBase_TIMERS函数在u-boot-1.1.4\include\s3c2410.h中定义

static inline S3C24X0_TIMERS * const S3C24X0_GetBase_TIMERS(void)

{

 return (S3C24X0_TIMERS * const)S3C24X0_TIMER_BASE;

}

S3C24X0_TIMER_BASE也在同一个文件中定义:

#define S3C24X0_TIMER_BASE  0x51000000

timers->TCFG0 = 0x0f00; 这里用到timer4,只用到预分频器1,这里设置TCFG0[15:8]=0x0f,[7:0]=0(没用到).

在u-boot-1.1.4\cpu\arm920t\s3c24x0\interrupts.c中定义了int timer_load_val = 0;

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

get_PCLK这个函数在u-boot-1.1.4\cpu\arm920t\s3c24x0\speed.c中:

ulong get_PCLK(void)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

    return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());

}

这里又从PCLK根据分频设置又从get_HCLK()/2或get_HCLK()中得到:

ulong get_HCLK(void)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

    return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

}

而这里HCLK又根据分频设置get_FCLK/2或get_FCLK中得到:

ulong get_FCLK(void)

{

    return(get_PLLCLK(MPLL));

}

static ulong get_PLLCLK(int pllreg)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

    ulong r, m, p, s;

    if (pllreg == MPLL)

 r = clk_power->MPLLCON;

    else if (pllreg == UPLL)

 r = clk_power->UPLLCON;

    else

 hang();

    m = ((r & 0xFF000) >> 12) + 8;

    p = ((r & 0x003F0) >> 4) + 2;

    s = r & 0x3;

    return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

}

在u-boot-1.1.4\include\configs\smdk2410.h中定义有:

#define CONFIG_SYS_CLK_FREQ 12000000

我们的板子也是这个频率,所以很多和时钟有关的参数都不用修改.

接着设置timer4定时器的计数值,手动加载,设置自动重载,开启定时器,具体设置就不详细分析了.

 

 lastdec = timers->TCNTB4 = timer_load_val;

 

 timers->TCON = (timers->TCON & ~0x0700000) | 0x600000;

 

 timers->TCON = (timers->TCON & ~0x0700000) | 0x500000;

到这里interrupt_init分析结束

下面到env_init函数,搜索到u-boot有很多个env_init,在u-boot-1.1.4\common\env_flash.c中有这么一句:

#if defined(CFG_ENV_IS_IN_FLASH)

正是因为在u-boot-1.1.4\include\configs\smdk2410.h中定义了CFG_ENV_IS_IN_FLASH,而其他的CFG_ENV_IS_IN_NAND等没有被定义,所以只有env_flash.c被编译

#define CFG_ENV_IS_IN_FLASH 1

下面就跳到env_flash.c中的env_init去分析,这个文件里也有两个env_init函数,第一个是在CFG_ENV_ADDR_REDUND有定义的情况才去编译的,而u-boot-1.1.4\include\configs\smdk2410.h没有定义这个宏,所以只有第二个env_init会实际被执行:

int  env_init(void)

{

 DECLARE_GLOBAL_DATA_PTR;

#ifdef CONFIG_OMAP2420H4

 int flash_probe(void);

 if(flash_probe() == 0)

  goto bad_flash;

#endif

 if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {

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

  gd->env_valid = 1;

  return(0);

 }

#ifdef CONFIG_OMAP2420H4

bad_flash:

#endif

 gd->env_addr  = (ulong)&default_environment[0];

 gd->env_valid = 0;

 return (0);

}

对于smdk2410开发板,CONFIG_OMAP2420H4这个宏没有被定义,所以中间那段跳过.

这里是设置了gd_t类型的指针变量gd,这里是用env_addr变量来存放default_environment数组的地址.

env_valid为CRD校验标志,这里设置为无效.default_environment在u-boot-1.1.4\common\env_common.c中定义:

uchar default_environment[] = {

#ifdef CONFIG_BOOTARGS   

 "bootargs=" CONFIG_BOOTARGS   "\0"

#endif

#ifdef CONFIG_BOOTCOMMAND  

 "bootcmd=" CONFIG_BOOTCOMMAND  "\0"

#endif

#ifdef CONFIG_RAMBOOTCOMMAND  

 "ramboot=" CONFIG_RAMBOOTCOMMAND  "\0"

#endif

#ifdef CONFIG_NFSBOOTCOMMAND  

 "nfsboot=" CONFIG_NFSBOOTCOMMAND  "\0"

#endif

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

 "bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0"

#endif         

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

 "baudrate=" MK_STR(CONFIG_BAUDRATE)  "\0"

#endif     

#ifdef CONFIG_LOADS_ECHO

 "loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0"

#endif

#ifdef CONFIG_ETHADDR   

 "ethaddr=" MK_STR(CONFIG_ETHADDR)  "\0"

#endif

#ifdef CONFIG_ETH1ADDR   

 "eth1addr=" MK_STR(CONFIG_ETH1ADDR)  "\0"

#endif

#ifdef CONFIG_ETH2ADDR   

 "eth2addr=" MK_STR(CONFIG_ETH2ADDR)  "\0"

#endif

#ifdef CONFIG_ETH3ADDR   

 "eth3addr=" MK_STR(CONFIG_ETH3ADDR)  "\0"

#endif

#ifdef CONFIG_IPADDR       

 "ipaddr=" MK_STR(CONFIG_IPADDR)  "\0"

#endif

#ifdef CONFIG_SERVERIP       

 "serverip=" MK_STR(CONFIG_SERVERIP)  "\0"

#endif

#ifdef CFG_AUTOLOAD   

 "\0"

#endif

#ifdef CONFIG_PREBOOT   

 "preboot=" CONFIG_PREBOOT   "\0"

#endif

#ifdef CONFIG_ROOTPATH   

 "rootpath=" MK_STR(CONFIG_ROOTPATH)  "\0"

#endif

#ifdef CONFIG_GATEWAYIP  

 "gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0"

#endif

#ifdef CONFIG_NETMASK       

 "netmask=" MK_STR(CONFIG_NETMASK)  "\0"

#endif

#ifdef CONFIG_HOSTNAME   

 "hostname=" MK_STR(CONFIG_HOSTNAME)  "\0"

#endif

#ifdef CONFIG_BOOTFILE   

 "bootfile=" MK_STR(CONFIG_BOOTFILE)  "\0"

#endif

#ifdef CONFIG_LOADADDR   

 "loadaddr=" MK_STR(CONFIG_LOADADDR)  "\0"

#endif

#ifdef  CONFIG_CLOCKS_IN_MHZ  

 "clocks_in_mhz=1\0"

#endif     

#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)

 "pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0"

#endif

#ifdef  CONFIG_EXTRA_ENV_SETTINGS

 CONFIG_EXTRA_ENV_SETTINGS

#endif

 "\0"

};

MK_STR宏的作用是将一个字符串转化为一个值,这个宏在其他文件中也有定义,但ENV_IS_EMBEDDED没有被定义,所以Environment.c中MK_STR宏也就没有定义.只有在u-boot-1.1.4\common\env_common.c里定义了.

env_init分析完,接下来到init_baudrate了:

static int init_baudrate (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 uchar tmp[64]; 

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

}

getenv_r在u-boot-1.1.4\common\cmd_nvedit.c里面,这个函数有一点点复杂,大概意思是取出和name匹配的参数的值,存放到tmp里去

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;

  

  n = 0;

  while ((len > n++) && (*buf++ = env_get_char(val++)) != '\0') 

   ;

  if (len == n)

   *buf = '\0';

  return (n);

 }

 return (-1);

}

env_get_char在u-boot-1.1.4\common\env_common.c中定义如下:

uchar (*env_get_char)(int) = env_get_char_init;

继续搜索env_get_char_init,也在同一文件中:

static uchar env_get_char_init (int index)

{

 DECLARE_GLOBAL_DATA_PTR;

 uchar c;

 

 if (gd->env_valid)     

 {

  c = env_get_char_spec(index);

 } else {

  c = default_environment[index];

 }

 return (c);

}

envmatch((uchar *)name, i)在u-boot-1.1.4\common\cmd_nvedit.c中定义,表示从i位置开始查找和name匹配的字符串

static int envmatch (uchar *s1, int i2)

{

 while (*s1 == env_get_char(i2++))

  if (*s1++ == '=')    

   return(i2);

 if (*s1 == '\0' && env_get_char(i2-1) == '=')  

  return(i2);

 return(-1);

}

继续执行init_baudrate,这里如果参数值不为0则设置为对应值,为0则采用默认值.

 gd->bd->bi_baudrate = gd->baudrate = (i > 0)

   ? (int) simple_strtoul (tmp, NULL, 10)

   : CONFIG_BAUDRATE;

simple_strtoul 这个函数在u-boot-1.1.4\lib_generic\vsprintf.c下面定义,从字面上看,这个函数的意思是str to ul(unsigned long),但它的实现有点复杂,就不去分析了.

接下来到u-boot-1.1.4\cpu\arm920t\s3c24x0\serial.c看下serial_init,这个函数很简单,就是调用了serial_setbrg();

int serial_init (void)

{

 serial_setbrg ();

 return (0);

}

在同一个文件中定义了serial_setbrg,主要是设置串口控制寄存器,模块时钟,波特率等

void serial_setbrg (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);

 int i;

 unsigned int reg = 0;

 

 reg = get_PCLK() / (16 * gd->baudrate) - 1;

 

 uart->UFCON = 0x07;

 uart->UMCON = 0x0;

 

 uart->ULCON = 0x3;

 

 uart->UCON = 0x245;

 uart->UBRDIV = reg;

#ifdef CONFIG_HWFLOW

 uart->UMCON = 0x1;

#endif

 for (i = 0; i < 100; i++);

}

接下来分析console_init_f,这个函数也比较简单

int console_init_f (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 gd->have_console = 1;    

#ifdef CONFIG_SILENT_CONSOLE    

 if (getenv("silent") != NULL)

  gd->flags |= GD_FLG_SILENT;

#endif

 return (0);

}

接下来继续看display_banner这个函数,printf不是从标准C库里调用的,这里是重复定义了这个函数,它的调用顺序是printf->vsprintf->puts->serial_puts.最后是把一些信息直接输出到串口上.

static int display_banner (void)

{

 printf ("\n\n%s\n\n", version_string);

 printf ("U-Boot code: lX -> lX  BSS: -> lX\n",

  _armboot_start, _bss_start, _bss_end);

#ifdef CONFIG_MODEM_SUPPORT    

 puts ("Modem Support enabled\n");

#endif

#ifdef CONFIG_USE_IRQ     

 printf ("IRQ Stack: lx\n", IRQ_STACK_START);

 printf ("FIQ Stack: lx\n", FIQ_STACK_START);

#endif

 return (0);

}

搜索到version_string的定义,其中U_BOOT_VERSION定义为"U-Boot 1.1.4",即把这个字符串打印到串口上.

const char version_string[] =

 U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"CONFIG_IDENT_STRING;

然后输出_armboot_start, _bss_start, _bss_end等地址信息.

按照顺序下来,下面是dram_init,这个函数比较简单,就是初始化板子的sdram起始地址及容量大小.

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;

 return 0;

}

在smdk2410.h中定义了下面两个宏

#define PHYS_SDRAM_1  0x30000000

#define PHYS_SDRAM_1_SIZE 0x04000000

回到之前的bd_t结构体里,其成员里有个bi_dram结构体数组,其中CONFIG_NR_DRAM_BANKS表示板子的dram的数目,这里我们只用到了一个sdram,所以只初始化了bi_dram[0].

struct    

    {

 ulong start;

 ulong size;

    }    bi_dram[CONFIG_NR_DRAM_BANKS];

初始化完dram,下面就打印dram有关的信息:

static int display_dram_config (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 int i;

 puts ("RAM Configuration:\n");

 for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {

  printf ("Bank #%d: lx ", i, gd->bd->bi_dram[i].start);

  print_size (gd->bd->bi_dram[i].size, "\n");

 }

 return (0);

}

回到之前的循环,执行完之后继续运行下去,下面是flash_init().

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

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

   hang ();

  }

 }

 

 size = flash_init ();

 display_flash_config (size);

这里的flash_init是在u-boot-1.1.4\board\smdk2410\flash.c里面的,对于smdk2410,它只实现了AMD_LV400/AMD_LV800的flash操作,对于我们板子的SST39VF1601,在移植的时候这个需要改写,这里先分析smdk2410是怎么实现的.

ulong flash_init (void)

{

 int i, j;

 ulong size = 0;

 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {

  ulong flashbase = 0;    

  flash_info[i].flash_id =

#if defined(CONFIG_AMD_LV400)

   (AMD_MANUFACT & FLASH_VENDMASK) |

   (AMD_ID_LV400B & FLASH_TYPEMASK);

#elif defined(CONFIG_AMD_LV800)

   (AMD_MANUFACT & FLASH_VENDMASK) |

   (AMD_ID_LV800B & FLASH_TYPEMASK);

#else

#error "Unknown flash configured"

#endif

   flash_info[i].size = FLASH_BANK_SIZE;  

  flash_info[i].sector_count = CFG_MAX_FLASH_SECT; 

  memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); 

  if (i == 0)

   flashbase = PHYS_FLASH_1;

  else

   panic ("configured too many flash banks!\n");

  for (j = 0; j < flash_info[i].sector_count; j++) {

   if (j <= 3) {

    

    if (j == 0) {

     flash_info[i].start[j] = 

      flashbase + 0;

    }

    

    if ((j == 1) || (j == 2)) {

     flash_info[i].start[j] =

      flashbase + 0x4000 + (j -

              1) *

      0x2000;

    }

    

    if (j == 3) {

     flash_info[i].start[j] =

      flashbase + 0x8000;

    }

   } else {

    flash_info[i].start[j] =

     flashbase + (j - 3) * MAIN_SECT_SIZE;

   }

  }

  size += flash_info[i].size;

 }

 flash_protect (FLAG_PROTECT_SET,   

         CFG_FLASH_BASE,

         CFG_FLASH_BASE + monitor_flash_len - 1,

         &flash_info[0]);

 flash_protect (FLAG_PROTECT_SET,

         CFG_ENV_ADDR,

         CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);

 return size;

}

这里有个FLASH Info,搜索到它的定义在u-boot-1.1.4\include\flash.h中

 * FLASH Info: contains chip specific data, per FLASH bank

 */

typedef struct {

 ulong size;   

 ushort sector_count;  

 ulong flash_id;  

 ulong start[CFG_MAX_FLASH_SECT];  

 uchar protect[CFG_MAX_FLASH_SECT];

#ifdef CFG_FLASH_CFI

 uchar portwidth;  

 uchar chipwidth;  

 ushort buffer_size;  

 ulong erase_blk_tout;  

 ulong write_tout;  

 ulong buffer_write_tout; 

 ushort vendor;   

 ushort cmd_reset;  

 ushort interface;  

#endif

} flash_info_t;

而在smdk2410.h中有如下定义:

flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   

#define FLASH_BANK_SIZE PHYS_FLASH_SIZE

PHYS_FLASH_SIZE在u-boot-1.1.4\include\configs\smdk2410.h中定义了为512K大小.而SST39VF1601为2M大小的,CFG_MAX_FLASH_SECT为flash的总扇区数,

#define PHYS_FLASH_SIZE  0x00080000

#define CFG_MAX_FLASH_SECT (11) 

对于SST39VF1601,可以采用sector的方法也可以采用block的方法,其中

1 sector=2k word=4k byte,

1 block=32k word=64k byte,

所以共有2048k/64k个block,即32个block,这些移植的时候需要修改.

上面flash_init()里面有个flash_protect(),把它找出来了,看看它都干了些什么

void flash_protect (int flag, ulong from, ulong to, flash_info_t *info)

{

 ulong b_end = info->start[0] + info->size - 1; 

 short s_end = info->sector_count - 1; 

 int i;

 debug ("flash_protect %s: from 0xlX to 0xlX\n",

  (flag & FLAG_PROTECT_SET) ? "ON" :

   (flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???",

  from, to);

 

 if (info->sector_count == 0 || info->size == 0 || to < from) {

  return;

 }

 

 if (info->flash_id == FLASH_UNKNOWN ||

     to < info->start[0] || from > b_end) {

  return;

 }

 for (i=0; i<info->sector_count; ++i) {

  ulong end;  

  end = (i == s_end) ? b_end : info->start[i + 1] - 1;

  

  if (from <= end && to >= info->start[i]) {

   if (flag & FLAG_PROTECT_CLEAR) {

#if defined(CFG_FLASH_PROTECTION)     

    flash_real_protect(info, i, 0);

#else

    info->protect[i] = 0;

#endif 

    debug ("protect off %d\n", i);

   }

   else if (flag & FLAG_PROTECT_SET) {

#if defined(CFG_FLASH_PROTECTION)     

    flash_real_protect(info, i, 1);

#else

    info->protect[i] = 1;

#endif 

    debug ("protect on %d\n", i);

   }

  }

 }

}

原来实际上在smdk2410中它等于什么都不干,看来白费我工夫了.

继续分析flash_init后面的display_flash_config,size为所有flash的总大小,这里只有一个flash,所以size=flash_info[0]

static void display_flash_config (ulong size)

{

 puts ("Flash: ");

 print_size (size, "\n");

}

继续回到start_armboot(),

#ifdef CONFIG_VFD

# ifndef PAGE_SIZE

#   define PAGE_SIZE 4096

# endif

 

 

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

 size = vfd_setmem (addr);

 gd->fb_base = addr;

#endif

#ifdef CONFIG_LCD

# ifndef PAGE_SIZE

#   define PAGE_SIZE 4096

# endif

 

 

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

 size = lcd_setmem (addr);

 gd->fb_base = addr;

#endif

这两段没有被定义,跳过.

 

 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);   

其中mem_malloc_init的定义如下,主要是清除内存区域.

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

}

接着继续回到start_armboot(),

#if (CONFIG_COMMANDS & CFG_CMD_NAND)

 puts ("NAND:");

 nand_init();  

#endif

从下面可以看到,u-boot-1.1.4\include\configs\smdk2410.h中没有定义CFG_CMD_NAND,所以这段也跳过

#define CONFIG_COMMANDS \

   (CONFIG_CMD_DFL  | \

   CFG_CMD_CACHE  | \

    \

    \

    \

    \

   CFG_CMD_REGINFO  | \

   CFG_CMD_DATE  | \

   CFG_CMD_ELF)

#ifdef CONFIG_HAS_DATAFLASH    

 AT91F_DataflashInit();

 dataflash_print_info();

#endif

 

 env_relocate ();

看看这个env_relocate:

void env_relocate (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,

  gd->reloc_off);

#ifdef CONFIG_AMIGAONEG3SE    

 enable_nvram();

#endif

#ifdef ENV_IS_EMBEDDED     

 

 env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);

 DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);

#else

 

 env_ptr = (env_t *)malloc (CFG_ENV_SIZE); 

 DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);

#endif

 

 env_get_char = env_get_char_memory;

 if (gd->env_valid == 0) {

#if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE)   

  puts ("Using default environment\n\n");

#else

  puts ("*** Warning - bad CRC, using default environment\n\n");   

  SHOW_BOOT_PROGRESS (-1); 

#endif

  if (sizeof(default_environment) > ENV_SIZE)

  {

   puts ("*** Error - default environment is too large\n\n");

   return;

  }

  memset (env_ptr, 0, sizeof(env_t)); 

  memcpy (env_ptr->data,   

   default_environment,

   sizeof(default_environment));

#ifdef CFG_REDUNDAND_ENVIRONMENT   

  env_ptr->flags = 0xFF;

#endif

  env_crc_update ();   

  gd->env_valid = 1;   

 }

 else {

  env_relocate_spec ();

 }

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

#ifdef CONFIG_AMIGAONEG3SE

 disable_nvram();

#endif

}

env_ptr = (env_t *)malloc (CFG_ENV_SIZE);这里有个env_t,它在include\environment.h中定义:

typedef struct environment_s {

 unsigned long crc;  

#ifdef CFG_REDUNDAND_ENVIRONMENT   

 unsigned char flags;  

#endif

 unsigned char data[ENV_SIZE];

} env_t;

#define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE)

#define CFG_ENV_SIZE  0x10000 

# define ENV_HEADER_SIZE (sizeof(unsigned long))

所以ENV_SIZE=64k-(sizeof(unsigned long))

uchar env_get_char_memory (int index)

{

 DECLARE_GLOBAL_DATA_PTR;

 if (gd->env_valid) {

  return ( *((uchar *)(gd->env_addr + index)) );

 } else {

  return ( default_environment[index] );

 }

}

void env_crc_update (void)

{

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

}

void env_relocate_spec (void)

{

#if !defined(ENV_IS_EMBEDDED) || defined(CFG_ENV_ADDR_REDUND)

#ifdef CFG_ENV_ADDR_REDUND     

 DECLARE_GLOBAL_DATA_PTR;

 if (gd->env_addr != (ulong)&(flash_addr->data)) {

  env_t * etmp = flash_addr;

  ulong ltmp = end_addr;

  flash_addr = flash_addr_new;

  flash_addr_new = etmp;

  end_addr = end_addr_new;

  end_addr_new = ltmp;

 }

 if (flash_addr_new->flags != OBSOLETE_FLAG &&

     crc32(0, flash_addr_new->data, ENV_SIZE) ==

     flash_addr_new->crc) {

  char flag = OBSOLETE_FLAG;

  gd->env_valid = 2;

  flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new);

  flash_write(&flag,

       (ulong)&(flash_addr_new->flags),

       sizeof(flash_addr_new->flags));

  flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);

 }

 if (flash_addr->flags != ACTIVE_FLAG &&

     (flash_addr->flags & ACTIVE_FLAG) == ACTIVE_FLAG) {

  char flag = ACTIVE_FLAG;

  gd->env_valid = 2;

  flash_sect_protect (0, (ulong)flash_addr, end_addr);

  flash_write(&flag,

       (ulong)&(flash_addr->flags),

       sizeof(flash_addr->flags));

  flash_sect_protect (1, (ulong)flash_addr, end_addr);

 }

 if (gd->env_valid == 2)

  puts ("*** Warning - some problems detected "

        "reading environment; recovered successfully\n\n");

#endif

 memcpy (env_ptr, (void*)flash_addr, CFG_ENV_SIZE);   

#endif

}

这里flash_addr其实就是CFG_ENV_ADDR,也就是在0x0F0000处.

static env_t *flash_addr = (env_t *)CFG_ENV_ADDR;

#define CFG_ENV_ADDR  (CFG_FLASH_BASE + 0x0F0000)

到这里为止,我们了解了env操作的流程大概是这样的,第一次启动是分配一段内存来存放env的信息,然后把内存的指针赋给env_ptr,第二次启动的时候就把存放在flash上的env的地址赋给了env_ptr.

继续回到start_armboot()中:

#ifdef CONFIG_VFD

 

 drv_vfd_init();

#endif

 

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

 

 {

  int i;

  ulong reg;

  char *s, *e;

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

  }

 }

这里有几层调用,

IPaddr_t getenv_IPaddr (char *var)

{

 return (string_to_ip(getenv(var)));    

}

IPaddr_t string_to_ip(char *s)

{

 IPaddr_t addr;

 char *e;

 int i;

 if (s == NULL)

  return(0);

 for (addr=0, i=0; i<4; ++i) {

  ulong val = s ? simple_strtoul(s, &e, 10) : 0;

  addr <<= 8;

  addr |= (val & 0xFF);

  if (s) {

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

  }

 }

 return (htonl(addr));

}

继续分析start_armboot(),

int devices_init (void)

{

#ifndef CONFIG_ARM    

 DECLARE_GLOBAL_DATA_PTR;

 ulong relocation_offset = gd->reloc_off;   

 int i;

 

 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {

  stdio_names[i] = (char *) (((ulong) stdio_names[i]) +

      relocation_offset);

 }

#endif

 

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

}

下面列出这里会调用到的结构体和函数:

typedef struct {

 int flags;   

 int ext;   

 char name[16];  

list_t ListCreate (int elementSize)

{

 list_t list;

 list = (list_t) (NewHandle (sizeof (ListStruct))); 

 if (list) {

  (*list)->signature = LIST_SIGNATURE;

  (*list)->numItems = 0;

  (*list)->listSize = 0;

  (*list)->itemSize = elementSize;

  (*list)->percentIncrease = kDefaultAllocationPercentIncrease; 

  (*list)->minNumItemsIncrease =

    kDefaultAllocationminNumItemsIncrease;  

 }

 return list;

}

Handle NewHandle (unsigned int numBytes)

{

 void *memPtr;

 HandleRecord *hanPtr;

 memPtr = calloc (numBytes, 1);

 hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1);

 if (hanPtr && (memPtr || numBytes == 0)) {

  hanPtr->ptr = memPtr;

  hanPtr->size = numBytes;

  return (Handle) hanPtr;

 } else {

  free (memPtr);

  free (hanPtr);

  return NULL;

 }

}

typedef struct ListStructTag

    {

    int signature;             

    int percentIncrease;       

    int minNumItemsIncrease;   

    int listSize;              

    int itemSize;              

    int numItems;              

    unsigned char itemList[1]; 

    } ListStruct;

#ifdef CONFIG_CMC_PU2   

 load_sernum_ethaddr ();

#endif

 jumptable_init ();

void jumptable_init (void)  

{

 DECLARE_GLOBAL_DATA_PTR;

 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_get_timer] = (void *)get_timer;

 gd->jt[XF_udelay] = (void *)udelay;

#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 

#if (CONFIG_COMMANDS & CFG_CMD_I2C)

 gd->jt[XF_i2c_write] = (void *) i2c_write;

 gd->jt[XF_i2c_read] = (void *) i2c_read;

#endif 

}

 console_init_r (); 

int console_init_r (void)

{

 DECLARE_GLOBAL_DATA_PTR;

 device_t *inputdev = NULL, *outputdev = NULL;

 int i, items = ListNumItems (devlist);

#ifdef CONFIG_SPLASH_SCREEN

 

 if (getenv("splashimage") != NULL)

  outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev");

#endif

#ifdef CONFIG_SILENT_CONSOLE

 

 if (gd->flags & GD_FLG_SILENT)

  outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev");

#endif

 

 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;

  }

 }

 

 if (outputdev != NULL) {

  console_setfile (stdout, outputdev);

  console_setfile (stderr, outputdev);

 }

 

 if (inputdev != NULL) {

  console_setfile (stdin, inputdev);

 }

 gd->flags |= GD_FLG_DEVINIT; 

#ifndef CFG_CONSOLE_INFO_QUIET

 

 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

 

 for (i = 0; i < 3; i++) {

  setenv (stdio_names[i], stdio_devices[i]->name);

 }

#if 0

 

 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))

  return (0);

#endif

 return (0);

}

console_init_r ();后期控制台初始化

     主要过程:查看环境参数stdin,stdout,stderr中对标准IO的指定的设备名称,再按照环境指定的名称搜索devlist,将搜到的设备指针赋给标准IO数组stdio_devices[]。置gd->flag标志GD_FLG_DEVINIT。这个标志影响putc,getc函数的实现,未定义此标志时直接由串口serial_getc和serial_putc实现,定义以后通过标准设备数组stdio_devices[]中的putc和getc来实现IO。

 下面是相关代码:

    void putc (const char c)

         {

         #ifdef CONFIG_SILENT_CONSOLE

          if (gd->flags & GD_FLG_SILENT)//GD_FLG_SILENT无输出标志

           return;

         #endif

          if (gd->flags & GD_FLG_DEVINIT) {//设备list已经初始化

          

           fputc (stdout, c);

          } else {

          

           serial_putc (c);//未初始化时直接从串口输出。

          }

         }

       void fputc (int file, const char c)

        {

         if (file < MAX_FILES)

          stdio_devices[file]->putc (c);

        }

为什么要使用devlist,std_device[]?

为了更灵活地实现标准IO重定向,任何可以作为标准IO的设备,如USB键盘,LCD屏,串口等都可以对应一个device_t的结构体变量,只需要实现getc和putc等函数,就能加入到devlist列表中去,也就可以被assign为标准IO设备std_device中去。如函数

int console_assign (int file, char *devname);

这个函数功能就是把名为devname的设备重定向为标准IO文件file(stdin,stdout,stderr)。其执行过程是在devlist中查找devname的设备,返回这个设备的device_t指针,并把指针值赋给std_device[file]。

#if defined(CONFIG_MISC_INIT_R)  

 

 misc_init_r ();

#endif

 

 enable_interrupts ();

#ifdef CONFIG_USE_IRQ   

void enable_interrupts (void)

{

 unsigned long temp;

 __asm__ __volatile__("mrs %0, cpsr\n"

        "bic %0, %0, #0x80\n"

        "msr cpsr_c, %0"

        : "=r" (temp)

        :

        : "memory");

}

 

#ifdef CONFIG_DRIVER_CS8900

 cs8900_get_enetaddr (gd->bd->bi_enetaddr);

#endif

网络部分不懂,暂时不看,等看完cs8900的datasheet再看

void cs8900_get_enetaddr (uchar * addr)

{

 int i;

 unsigned char env_enetaddr[6];

 char *tmp = getenv ("ethaddr");

 char *end;

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

  env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;

  if (tmp)

   tmp = (*end) ? end+1 : end;

 }

 

 if (get_reg_init_bus (PP_ChipID) != 0x630e)

  return;

 eth_reset ();

 if ((get_reg (PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==

   (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) {

  

  for (i = 0; i < 6 / 2; i++) {

   unsigned int Addr;

   Addr = get_reg (PP_IA + i * 2);

   addr[i * 2] = Addr & 0xFF;

   addr[i * 2 + 1] = Addr >> 8;

  }

  if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 &&

      memcmp(env_enetaddr, addr, 6) != 0) {

   printf ("\nWarning: MAC addresses don't match:\n");

   printf ("\tHW MAC address:  "

    "X:X:X:X:X:X\n",

    addr[0], addr[1],

    addr[2], addr[3],

    addr[4], addr[5] );

   printf ("\t"ethaddr" value: "

    "X:X:X:X:X:X\n",

    env_enetaddr[0], env_enetaddr[1],

    env_enetaddr[2], env_enetaddr[3],

    env_enetaddr[4], env_enetaddr[5]) ;

   debug ("### Set MAC addr from environment\n");

   memcpy (addr, env_enetaddr, 6);

  }

  if (!tmp) {

   char ethaddr[20];

   sprintf (ethaddr, "X:X:X:X:X:X",

     addr[0], addr[1],

     addr[2], addr[3],

     addr[4], addr[5]) ;

   debug ("### Set environment from HW MAC addr = "%s"\n",    ethaddr);

   setenv ("ethaddr", ethaddr);

  }

 }

}

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

 if (getenv ("ethaddr")) {

  smc_set_mac_addr(gd->bd->bi_enetaddr);

 }

#endif

 

 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 

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

eth_initialize()有两个,第二个没有被编译,只用到第一个

#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)

 int eth_initialize(bd_t *bis)

#elif (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI)

 int eth_initialize(bd_t *bis)

终于到main_loop了,真是开心

 

 for (;;) {

  main_loop ();

 }

 

}

这个函数也非常长,这里讲有效代码贴出来:

void main_loop (void)

{

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

 char *s;

 int bootdelay;

#endif

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

 s = getenv ("bootdelay");

 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

 debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);

  s = getenv ("bootcmd");

 debug ("### main_loop: bootcmd="%s"\n", s ? s : "<UNDEFINED>");

 if (bootdelay >= 0 && s && !abortboot (bootdelay)) {

 

  parse_string_outer(s, FLAG_PARSE_SEMICOLON |

        FLAG_EXIT_FROM_LOOP);

 }

#endif 

 

#ifdef CFG_HUSH_PARSER

 parse_file_outer();

 

 for (;;);

#else

 for (;;) {

#ifdef CONFIG_BOOT_RETRY_TIME

  if (rc >= 0) {

   

   reset_cmd_timeout();

  }

#endif

  len = readline (CFG_PROMPT);

  flag = 0; 

  if (len > 0)

   strcpy (lastcommand, console_buffer);

  else if (len == 0)

   flag |= CMD_FLAG_REPEAT;

#ifdef CONFIG_BOOT_RETRY_TIME

  else if (len == -2) {

   

   puts ("\nTimed out waiting for command\n");

# ifdef CONFIG_RESET_TO_RETRY

   

   do_reset (NULL, 0, 0, NULL);

# else

   return;  

# endif

  }

#endif

  if (len == -1)

   puts ("<INTERRUPT>\n");

  else

   rc = run_command (lastcommand, flag);

  if (rc <= 0) {

   

   lastcommand[0] = 0;

  }

 }

#endif

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: