C语言启动代码board.c分析
2011-08-23 11:53
666 查看
237 init_fnc_t *init_sequence[] = { 238 #if defined(CONFIG_ARCH_CPU_INIT) 239 240 /* 基本的处理器相关配置 -- cpu/arm920t/cpu.c */ 241 arch_cpu_init, /* basic arch cpu dependent setup */ 242 #endif 243 244 /* 基本的板级相关配置 -- board/smdk2410/smdk2410.c */ 245 /* 是初始化与硬件平台有关的函数。它的工作很明显:时 246 *钟的设置,引脚 IO 口的设置,并且在这里把数据 cache 和指令 cache 也打开 247 *了。以上工作的完成,标志着板子已经准备好工作了。当然,考虑到可能系统会 248 * 因此 u-boot发生意外中断,所以我们还需要初始化中断, 让中断也准备好工作, 249 *代码中下一步就开始了中断的初始化。 */ 250 board_init, /* basic board dependent setup */ 251 252 #if defined(CONFIG_USE_IRQ) 253 /* 初始化中断处理 -- cpu/arm920t/s3c24x0/interrupt.c */ 254 interrupt_init, /* set up exceptions */ 255 #endif 256 timer_init, /* initialize timer */ 257 env_init, /* initialize environment */ 258 init_baudrate, /* initialze baudrate settings */ 259 serial_init, /* serial communications setup */ 260 261 /* 控制台初始化阶段1 -- common/console.c */ 262 /* 这个函数的功能只有一个,就是指出我们目前是使 263 用串口的,因此有此句:gd->have_console = 1;然后直接返回 0。 */ 264 console_init_f, /* stage 1 init of console */ 265 266 /* 打印u-boot信息 -- lib_arm/board.c */ 267 display_banner, /* say that we are here */ 268 #if defined(CONFIG_DISPLAY_CPUINFO) 269 print_cpuinfo, /* display cpu info (and speed) */ 270 #endif 271 #if defined(CONFIG_DISPLAY_BOARDINFO) 272 checkboard, /* display board info */ 273 #endif 274 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) 275 init_func_i2c, 276 #endif 277 /* 配置可用的RAM -- board/smdk2410/smdk2410.c */ 278 dram_init, /* configure available RAM banks */ 279 #if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI) 280 arm_pci_init, 281 #endif 282 /* 显示RAM的配置大小 -- lib_arm/board.c */ 283 display_dram_config, 284 NULL, 285 }; 286 // C语言入口函数 287 void start_armboot (void) 288 { 289 init_fnc_t **init_fnc_ptr; 290 char *s; 291 #if defined(CONFIG_VFD) || defined(CONFIG_LCD) 292 unsigned long addr; 293 #endif 294 295 /* 296 *如同使用变量之前,需要声明定义一样,这里使用全局变量 gd 和 bd 之前, 297 *我们需要先设置它的地址,并用 memset 函数为它分配合适的空间。u-boot 298 *的注释告知我们,gd 和 bd 是一个可写的指针,实际上不过是一个地址而已。 299 *代码中的这句话:__asm__ __volatile__("": : :"memory");目的就是 300 *告诉编译器内存被修改过了。 301 */ 302 /* Pointer is writable since we allocated a register for it */ 303 gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); 304 /* compiler optimization barrier needed for GCC >= 3.4 */ 305 __asm__ __volatile__("": : :"memory"); 306 307 memset ((void*)gd, 0, sizeof (gd_t)); 308 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); 309 memset (gd->bd, 0, sizeof (bd_t)); 310 311 gd->flags |= GD_FLG_RELOC; 312 313 monitor_flash_len = _bss_start - _armboot_start; 314 315 /* 316 *(函数指针) 指向的是 init_fnc_t指针数组的每个成员都对应着一个函数名 , 317 *类型的函数。For 语句每次都会判断当前的函数是不是 NULL,如果是,则跳出 318 *for 语句,完成当前的板子初始化列表函数的功能。 319 * 可能大家都注意到了一个类型:init_fnc_t,它表示什么意思呢?我们看到 320 *了在初始化列表函数之前,有一个新的数据类型,它是个 typedef 语句: 321 * typedef int (init_fnc_t) (void); 322 *可能有的同学对此不太理解,为啥非得用一个 typedef 呢?笔者认为,可以不 323 *用 typedef,但是用了 init_fnc_t 后,团队中别的成员来看代码的时候,会很 324 *轻松地知道,这是一个初始化(init)的函数(fnc),增加了代码的可读性。 325 */ 326 // init_sequence[]数组保存着基本的初始化函数指针。 327 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { 328 if ((*init_fnc_ptr)() != 0) { 329 hang (); 330 } 331 } 332 333 /*初始化内存分配函数 _armboot_start 在u-boot.lds链接脚本中定义 */ 334 /* armboot_start is defined in the board-specific linker script*/ 335 /* mem_malloc_init 函数,这是非常关键的一步,请大家引起注意。我们必须配 336 置好内存的起始地址和结束地址,然后把这块区域清零,以便后续来使用它。 */ 337 mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, 338 CONFIG_SYS_MALLOC_LEN); 339 340 #ifndef CONFIG_SYS_NO_FLASH 341 /* configure available FLASH banks */ 342 display_flash_config (flash_init ()); 343 #endif /* CONFIG_SYS_NO_FLASH */ 344 345 #ifdef CONFIG_VFD 346 # ifndef PAGE_SIZE 347 # define PAGE_SIZE 4096 348 # endif 349 /* 350 * reserve memory for VFD display (always full pages) 351 */ 352 /* bss_end is defined in the board-specific linker script */ 353 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); 354 vfd_setmem (addr); 355 gd->fb_base = addr; 356 #endif /* CONFIG_VFD */ 357 358 #ifdef CONFIG_LCD 359 /* board init may have inited fb_base */ 360 if (!gd->fb_base) { 361 # ifndef PAGE_SIZE 362 # define PAGE_SIZE 4096 363 # endif 364 /* 365 * reserve memory for LCD display (always full pages) 366 */ 367 /* bss_end is defined in the board-specific linker script */ 368 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); 369 lcd_setmem (addr); 370 gd->fb_base = addr; 371 } 372 #endif /* CONFIG_LCD */ 373 374 #if defined(CONFIG_CMD_NAND) 375 puts ("NAND: "); 376 nand_init(); /* go init the NAND */ 377 #endif 378 379 #if defined(CONFIG_CMD_ONENAND) 380 onenand_init(); 381 #endif 382 383 #ifdef CONFIG_HAS_DATAFLASH 384 AT91F_DataflashInit(); 385 dataflash_print_info(); 386 #endif 387 /* 配置环境变量*/ 388 /* initialize environment */ 389 env_relocate (); 390 391 #ifdef CONFIG_VFD 392 /* must do this after the framebuffer is allocated */ 393 drv_vfd_init(); 394 #endif /* CONFIG_VFD */ 395 396 #ifdef CONFIG_SERIAL_MULTI 397 serial_initialize(); 398 #endif 399 /* 从环境变量中获取IP地址 */ 400 /* IP Address */ 401 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); 402 403 stdio_init (); /* get the devices list going. */ 404 405 jumptable_init (); 406 407 #if defined(CONFIG_API) 408 /* Initialize API */ 409 api_init (); 410 #endif 411 412 /* 完整地初始化控制台设备 */ 413 console_init_r (); /* fully init console as a device */ 414 415 #if defined(CONFIG_ARCH_MISC_INIT) 416 /* miscellaneous arch dependent initialisations */ 417 arch_misc_init (); 418 #endif 419 #if defined(CONFIG_MISC_INIT_R) 420 /* miscellaneous platform dependent initialisations */ 421 misc_init_r (); 422 #endif 423 424 /* enable exceptions */ 425 enable_interrupts (); /* 使能中断处理 */ 426 427 /* Perform network card initialisation if necessary */ 427 /* Perform network card initialisation if necessary */ 428 #ifdef CONFIG_DRIVER_TI_EMAC 429 /* XXX: this needs to be moved to board init */ 430 extern void davinci_eth_set_mac_addr (const u_int8_t *addr); 431 /* 通过环境变量初始化 */ 432 if (getenv ("ethaddr")) { 433 uchar enetaddr[6]; 434 eth_getenv_enetaddr("ethaddr", enetaddr); 435 davinci_eth_set_mac_addr(enetaddr); 436 } 437 #endif |
相关文章推荐
- (三)u-boot启动流程分析(C语言部分board_f.c)
- (四)u-boot启动流程分析(C语言部分board_r.c)
- Linux启动过程的C语言代码分析
- VxWorks启动代码rominit.s分析
- Hadoop 2.0 Yarn代码:NodeManager端代码分析_NM端各服务模块的启动
- Linux内核启动代码分析二之开发板相关驱动程序加载分析
- S3C2410软件调试总结和启动代码分析
- mini2440启动代码分析之第九篇
- Openstack Cinder 服务启动代码分析
- STM32F10x 启动代码分析
- s3c2410 bootloader 第一部分启动代码分析
- (二)启动代码分析 02
- u-boot启动代码分析
- eboot启动代码分析及内核启动代码分析
- TQ2440启动代码分析笔记
- linux非解压代码的启动过程分析 unicore head.S vmlinux解压后的代码运行 临时MMU的建立
- u-boot_smdkv210 分析二:启动代码start.s分析
- ucOS_II移植:Stm32启动代码分析
- 基于visual c++之windows核心编程代码分析(52)使用WMI 获取进程启动参数
- u-boot启动流程分析(2)_板级(board)部分