您的位置:首页 > 编程语言 > C语言/C++

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

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