目标:串口成功打印信息。
前提条件:
1、uboot版本:u-boot-2012.04.01.tar.bz2;
2、交叉编译器:arm-linux-gcc-4.3.2.tar(如何更换交叉编译器参考https://blog.csdn.net/WangHuiShou/article/details/102092801)
3、部署uboot(代码利用官方的)
1.解压源码
tar xjf u-boot-2012.04.01.tar.bz2
2.清除源码中的配置文件和目标文件,上一次编译的结果
make distclean
3.针对具体的CPU和开发板进行配置源码
make smdk2410_config //smdk2410_config 配置选项来自 Makefile
4.make//编译,结果u-boot.bin
5.烧写(JTAG,USB,SD,UART)
6.涉及代码的修改:重点关注一个头文件:
include/configs/smdk2410.h //全是开发板的硬件配置信息
一、boot启动过程:
初始化硬件(关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH等)——>加载完整uboot到SDRAM——>跳转到第二阶段入口开始执行(把内核从NAND FLASH读到SDRAM——>设置"要传给内核的参数"——>跳转执行内核),整个过程最重要的两个文件:
/arch/arm/cpu/arm920t/start.S,涉及到特定硬件设备的读写寄存器操作以及特定体系结构的汇编语言(中断、时钟等)。
board/samsung/smdk2440/lowlevel_init.S,完成底层的初始化(内存控制器等)。
具体流程如下:
1 set the cpu to SVC32 mode
2 turn off the watchdog
3 mask all IRQs by setting all bits in the INTMR
4 设置时钟比例
5 设置内存控制器
6 设置栈,调用C函数board_init_f
7 调用函数数组init_sequence里的各个函数
7.1 board_early_init_f : 设置系统时钟、设置GPIO
......
8 重定位代码:
8.1 从NOR FLASH把代码复制到SDRAM
8.2 程序的链接地址是0,访问全局变量、静态变量、调用函数时是使"基于0地址编译得到的地址"
现在把程序复制到了SDRAM
需要修改代码,把"基于0地址编译得到的地址"改为新地址
8.3 程序里有些地址在链接时不能确定,要到运行前才能确定:fixabs
9 clear_bss
10 调用C函数board_init_r:第2阶段的代码
二、新建板级(完成串口信息的打印)
- 编译:make smdk2410_config && make
- 源码修改,移植到JZ2440开发板:
1、新建单板(根据类似单板进行新建)
1.1、拷贝文件
cp -rf board/samsung/smdk2410 board/samsung/smdk2440
cp include/configs/smdk2410.h include/configs/smdk2440.h
1.2、修改boards.cfg ,仿照2410增加: (较新版的u-boot源码已经去掉boadrs.cfg,而是使用make menuconfig配置,config文件在configs目录下)
仿照
smdk2410 arm arm920t - samsung s3c24x0
添加:
smdk2440 arm arm920t - samsung s3c24x0
1.3、重新编译烧录文件make smdk2440_config ==》make,没有打印信息
阅读代码发现不足:UBOOT里先以60MHZ的时钟计算参数来设置内存控制器(lowlevel_init函数的SDRAM),但是MPLL还未设置,导致设置初始化SDRAM时不成功
处理措施: 把MPLL的设置放到start.S里(设置),取消SDRAM前设置时钟,board_early_init_f里对MPLL的设置,修改如下:
修改start.s(arch/arm/cpu/arm920t/):
#if 0
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#else
/*设置时钟 */
ldr r0, =0x4c000014
// mov r1, #0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0]
/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
/*MPLL(FCLK) = (2*m*fin) / (p * 2^s)*/
/*m = MDIV + 8, p = PDIV + 2, s = SDIV, fin = 12MHz*/
/*MPLL寄存器,[19:12]MDIV,[9:4]PDIV,[1:0]SDIV*/
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
/* 启动ICACHE */
mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 @ write it back
#endif
内存值替换成我们的:lowlevel_init(board/samsung/smdk2440/)
SMRDATA:
#if 0
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0x32
.word 0x30
.word 0x30
#else
.long 0x22011110 //BWSCON
.long 0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
.long 0x00018005 //BANKCON6
.long 0x00018005 //BANKCON7
.long 0x008C04F4 // REFRESH
.long 0x000000B1 //BANKSIZE
.long 0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
#endif
删除board_init_f==>board_early_init_f(arch/arm/lib/board.c)对MPLL的设置:
#if 0
/* to reduce PLL lock time, adjust the LOCKTIME register */
writel(0xFFFFFF, &clk_power->locktime);
/* configure MPLL */
writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
&clk_power->mpllcon);
/* some delay between MPLL and UPLL */
pll_delay(4000);
/* configure UPLL */
writel((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV,
&clk_power->upllcon);
#endif
重新编译少些程序,通过usb烧写(将正常使用boot烧录到norflash后使用dnw烧写),烧写命令如下:
usb 1 30000000
protect off all
erase 0 7ffff
cp.b 30000000 0 80000
烧录完成后打印信息为乱码,分析应该是串口波特率设置问题
通过串口初始化发现(serial_init->serial_init_dev->_serial_setbrg->get_PCLK->get_HCLK):
get_HCLK发现没有定义CONFIG_S3C2440,它用2410的那套,那么在include/configs3c2440.h中去掉#define CONFIG_S3C2410改成#define CONFIG_S3C2440。编译make,编译后发现出现一下错误。
错误出自于nandflash,到s3c2410_nand.c的72行分析得知,结构体s3c2410_nand只有在宏CONFIG_S3C2410定义时有效,CONFIG_S3C2410和CONFIG_S3C2440不能同时定义。
解决方案:暂时去除nandflash的编译。include/configs3c2440.h中删除//#define CONFIG_CMD_NAND。
再次编译make,编译成功,烧录查看打印信息。
到此,2440单板成功打印正常。
下一节介绍如何从nandflash启动并从nandflash重定位到SDRAM