很多产品几乎采用u-boot引导,44B0X板当然也少不了跑个u-boot,网上很多攻略,可以参考,但是不建议直接基于上面修改,自己下载一份完整的源代码,自己完完全全修改对流程更清晰
调试的话,下面是两种方案调试对比 willger方案:ADS(armgcc)+HJTAG-RDI----gcc+gdb+ocdremot---------------速率5k-10k,很慢 J-link方案:ADS(armgcc)+jlink-RDI----------gcc+gdb+jlink-GDBSERVER---速率500k,很快
1. 修改u-boot
u-boot实际就是一个小应用了,和修改ucos一样,最基础的就是,IO口初始化,时钟,串口,中断
既然是应用了,SDRAM大小,FLASH大小及驱动,网卡的驱动程序都要跑起来
一般说来,u-boot都提供了类似的芯片的start.s,汇编代码改动很少,s3c44b0x和B2类似,这里选择B2的代码来修改,下面就按照一步步的需要做修改
SDRAM和FLASH的大小,网卡芯片的使能以及网卡CS片选的地址,默认配置参数放在EEPROM中,改为FLASH中,并设置好起址地址,在B2.h中先修改好,顺便把config.mk的TEXT_BASE修改为0x0C700000(SDRAM的最高处)
#define CONFIG_DRIVER_RTL8019
#define RTL8019_BASE 0x06000300 /* base address */
/*使能8019,按照CS选择起址地址 */
#define PHYS_SDRAM_1 0x0c000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x00800000 /* 8 MB */
/*按照硬件SDRAM大小修改 */
#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
#define PHYS_FLASH_SIZE 0x00200000 /* 2 MB */
/*按照硬件FLASH大小修改 */
#define CFG_ENV_IS_IN_FLASH 1 /* use FLASH for environment vars */
#define CFG_ENV_ADDR (PHYS_FLASH_1+0x40000)
#define CFG_ENV_OFFSET 0x40000
/*在FLASH中储存ENV信息,并规定起址地址 */
//#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */
/*默认是用EEPROM储存ENV信息 */
在B2.c中修改board_init,这个严格按照硬件电路图IO的功能,配合spec设置好,涉及到GPIO啊,串口啊,SDRAM、FLASH并行通信,网口接口以及中端口,我是从ucos中copy过来的
FCLK串口时钟
FLASH用的芯片同B2一样,不需要修改
8019也是一样的,唯一的修改是16B和8B的区别,8019的寄存器地址会有差别的
2. u-boot FLASH和SDRAM中分布
1,u-boot和应用烧入FLASH后的分布
|0x0020 0000
|
| 应用程序
|
|0x0008 0000
|
|
|
|0x0005 0000
|
| u-boot env
|
|0x0004 0000
|
| u-boot程序,44b0x的中断,指向u-boot的二级中断0x0c000000,可修改
|
|_start = 0x0000 0000
2,运行起来后SDRAM的分布
|0x0C80 0000
| ucos的代码会把二级中断向量表放这里的
|0xc7f ff00
|
| stack栈
|
|0xc7f f000堆heap end地址,紧跟的是stack栈
|
| 堆heap
|
|
|0x0C70 0000=0x0C80 0000-1MB
|
|
| rw段+bss
|
|0x0C50 0000:ucos rw段紧跟的是ZI段(BSS)
|
|
|
| ....把应用程序ucos加载到这里开始跑
|
|0x0C10 0000:ucos ro段
|
|
|0xc00 0000+1024
|
| u-boot指向的二级中断(可以修改为ucos的二级中断)
|
|0xc00 0000
.
.
.
|0x0020 0000
|
| 应用程序(ro+rw)
|
|0x0008 0000
|
|
|
|0x0005 0000
|
| u-boot env
|
|0x0004 0000
|
| u-boot程序,44b0x的中断,指向u-boot的二级中断0x0c000000,可修改
|
|_start = 0x0000 0000
3. j-link调试u-boot
直接Jlink加载u-boot后SDRAM的分布 |0x0C80 0000 | |0xc7f ff00 | | |0x0C71 fb70 _bbs_end | |0x0C71 b2b8 _bbs_start | |0x0C71 ad40 .u_boot_cmd | |0x0C71 a11c .data段 | |0x0C71 58e4 .rodata段 | | |0x0C70 0000=0x0C80 0000-1MB .text段,即是_armboot_start基址 | | | |0x0C6d 0000 经过env_relocate后env_addr基址 | | |CFG_MALLOC_LEN | #define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024 ) | |0x0C6c ffdc (gd_t)gd(全局变量表)基址 | gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); | |0x0C6c ffb8 (bt_t)bd(板卡信息表)基址 | gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); | | |IRQ FRQ栈 | IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; | FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; | | | | |0x0C10 0000 | |0xc00 0000+1024 | | u-boot指向的二级中断(可以修改为ucos的二级中断) | |0xc00 0000 RAM基址 . . . |0x0020 0000 | | | |0x0008 0000 | | | |0x0005 0000 | | u-boot env | |0x0004 0000 env_addr默认基址 | | u-boot程序,44b0x的中断,指向u-boot的二级中断0x0c000000,可修改 | |_start = 0x0000 0000
整个u-boot的思路很明确 -->cpu/s3c44b0/start.s(CONFIG_USE_IRQ 没有定义的,flash中时候,经过start,start_code,cpu_init_crit;拷贝code+data;拷贝0xc00 0008;stack_setup) -->lib_arm/board.c(start_armboot) -->board/.../flash.c -->board/.../lowlevel_init.s -->start_armboot -->init_fnc_ptr -->函数指针数组(1) init_fnc_t *init_sequence[] = { cpu_init, /* basic cpu dependent setup */ board_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 */ dram_init, /* configure available RAM banks */ display_dram_config, #if defined(CONFIG_VCMA9) checkboard, #endif NULL, }; board_init(board/...) env_init(common/env_eeprom.c) serial_init(cpu/s3c44b0/serial.c) console_init_f(common/console.c) display_banner(lia_arm/board.c) -->display_flash_config(lia_arm/board.c) -->env_relocate -->gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); -->main_loop(lia_arm/board.c) -->abortboot若没有键按下则run_command (s, 0)(s为默认的bootcmd,这个是事先设置好的env bootcmd=run jffsboot) do_bootm do_bootm_linux
gd和bd初始化结束后内存信息,NOTE:env_valid=0
函数指针数组初始化结束后,NOTE:增加串口波特率,RAM基址,RAM大小信息
(当env_valid=0的时候env_addr为0x0C71 A828,WHY???)
最后打印信息为 U-Boot 1.1.1 (Feb 1 2009 - 22:44:29)
U-Boot code: 0C700000 -> 0C71B2B8 BSS: -> 0C71FB70 RAM Configuration: Bank #0: 0c000000 8 MB Flash: 2 MB *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 ## Booting image at 00020000 ... Bad Magic Number =>
当我们配置env信息后 => setenv severip 10.0.7.216 => setenv ipaddr 10.0.7.174 => save Saving Environment to Flash... Un-Protected 1 sectors Erasing Flash... .................................................................. done Erased 1 sectors Writing to Flash... done Protected 1 sectors =>
重新加载U-boot
函数指针数组初始化结束后,NOTE:env_valid=1 env_addr=0x0004 0000(默认flash中的地址) env_relocate重载env_addr之后,NOTE:env_addr=0x0C6d 0000(重载到RAM中地址)
读取severip和ipaddr之后,NOTE:修改全局结构体中数据bi_ip_addr; /* IP Address */和bi_enetaddr[6]; /* Ethernet adress */ 打印信息如下 U-Boot 1.1.1 (Feb 1 2009 - 22:44:29)
U-Boot code: 0C700000 -> 0C71B2B8 BSS: -> 0C71FB70 RAM Configuration: Bank #0: 0c000000 8 MB Flash: 2 MB In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 ## Booting image at 00020000 ... Bad Magic Number =>
5. 小结
先把u-boot代码流程弄清楚,要不然都不知道在哪里改代码,最好是参考类似的板子操作,走了不少弯路,MCLK这个我搞糊涂了,MCLK到底是根据外部的晶振来判断的吗???