文档时间:2018-08-09
交叉编译器:arm-linux-gcc-4.3.2
Ubuntu版本:16.04
uboot版本:2013.10
1、创建jz2440单板
由于uboot-2013-10没有对2440单板的支持,所以需要我们自己创建,由于jz2440与smdk2410有相似之处,所以我们以smdk2410单板为模板进行2440单板的创建
cd work/u-boot/u-boot-2013.10/ //进入到u-boot目录 cp board/samsung/smdk2410 board/samsung/jz2440 -rf //把smdk2410目录下的所有文件拷贝到jz2440目录下 ls board/samsung/jz2440/ //查看jz2440目录下的内容
如果创建成功的话,会有如下显示:
将smdk2410.c改为jz2440.c
mv board/samsung/jz2440/smdk2410.c board/samsung/jz2440/jz2440.c
修改board/samsung/jz2440目录下的Makefile文件,将smdk2410.o改为jz2440.o,见下图:
(PS:简单修改在Ubuntu里,用vim或者gedit,其他修改则在Windows下,用SI(source insight))
在include/configs目录下添加单板配套的.h文件,命名为jz2440.h(仿照smdk2410.h)
cp include/configs/smdk2410.h include/configs/jz2440.
然后把修改的文件上传到Windows中,添加到SI工程中,以便后面修改。
输入make jz2440_config进行编译,出现如下错误:
说明在uboot中没有jz2440单板对应的配置项,参考smdk2410
输入命令 grep smdk2410 * -nR 得到如下结果
打开boards.cfg,仿照smdk2410增加jz2440配置项,如下,红色部分为增加代码:
Active arm arm920t s3c24x0 samsung - smdk2410 - David Müller <d.mueller@elsoft.ch>
Active arm arm920t s3c24x0 samsung - jz2440 - David Müller <d.mueller@elsoft.ch>
继续执行make jz24440_config,成功,输入 make 生成u-boot.bin
将生成的u-boot.bin烧写到jz2440开发板上,串口无输出,分析并修改start.S
2,修改start.S让串口有输出
从上到下一路分析到设置时钟分频处,发现默认FCLK为120M,而我们所用开发板时钟为400M,参考以前裸机程序修改代码,红色为添加代码,蓝色为删去代码:
/* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #define JZ2440_400MHZ (92<<12)|(1<<4)|(1<<0) //设置MPLL,FCLK:HCLK:PCLK=400M:100M:50M //LOCKTIME(0x4C000000) = 0xFFFFFFFF ldr r0, =0x4C000000 ldr r1, =0xFFFFFFFF str r1, [r0] //CLKDIVN(0x4C000014)=0x5,tFCLK:tHCLK:tPCLK=1:4:8 ldr r0, =0x4C000014 ldr r1, =0x5 str r1, [r0] //设置CPU工作于异步模式 mrc p15,0,r0,c1,c0,0 orr r0,r0,#0xC0000000 //R1_nF:OR:R1_iA mcr p15,0,r0,c1,c0,0 //设置MPLLCON(0x4C000004)=(92<<12)|(1<<4)|(1<<0) //m=MDIV+8=92+8=100 //p=PDIV+2=1+2=3 //s=SDIV=1 //FCLK=2*m*Fin/(p*2^s)=2*100*12/(3*2^1)=400M ldr r0, =0x4C000004 ldr r1, =JZ2440_400MHZ str r1, [r0]
接着往下分析,到bl cpu_init_crit 处,在 cpu_init_crit 里跳入 lowlevel_init,打开lowlevel_init.S(/board/samsung/jz2440) 文件,分析得知,该文件里实现的是对bank的设置,
修改代码,使其能够支持SDRAM:红色为修改后的代码
1 SMRDATA: 2 .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) 3 .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) 4 .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) 5 .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) 6 .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) 7 .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) 8 .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) 9 .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) 10 .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) 11 .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) 12 .word 0x32 13 .word 0x30 14 .word 0x30 15 16 改为: 17 SMRDATA: 18 .word 0x22000000 //BWSCON 19 .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) 20 .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) 21 .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) 22 .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) 23 .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) 24 .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) 25 .word 0x00018005 //BANKCON6 26 .word 0x00018005 //BANKCON7 27 .word 0x008C04F4 //REFRESH 28 .word 0x000000B1 //BANKSIZE 29 .word 0x30 //MRSRB6 30 .word 0x30 //MRSRB7
接着分析start.S,到 bl _main ,搜索文档发现 _main 的入口在 arch/arm/lib/crt0.S 文件中定义:如下图:
分析 crt0.S 文件 一路往下看,发现会跳到一个c函数中:
进入到 board_init_f() 函数中 (/arch/arm/lib目录下),进行分析:
从名字可以看出,init_sequence里存放的应该是一些初始化函数,进入到 init_sequence 中,包含以下函数:
然后进入 board_early_init_f()函数中(/board/samsung/jz2440/jz2440.c里),分析发现,此函数主要功能是设置时钟,初始化io口,由于前面我们在 start.S 中已经设置了时钟,
这里把时钟设置相关的代码屏蔽:如下,红色部分为修改的代码:
/* 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);
接着分析 crt0.S ,发现后面就是代码重定位和跳转到第二阶段,与我们当前要解决的问题没什么关联,暂且不管
到这里,代码基本上已经修改完毕,输入以下命令编译:
1 make jz2440_config 2 make
编译成功,生成u-boot.bin,烧写到板子上,串口有输出,但是是乱码:
说明SDRAM设置成功,但是串口波特率未设置成功,归根结底是时钟获取不正确。
3、修改代码使串口正常输出
输入命令 grep "get_HCLK" * -nR 进行搜索,然后通过搜索结果进入到arch/arm/cpu/arm920t/s3c24xx/ 目录下,
打开 speed.c 文件,定位到get_HCLK 函数
很明显,由于没有配置 CONFIG_S3C2440,因此不能获得正确的时钟,使用的是CONFIG_S3C2410配置下的时钟,
搜索CONFIG_S3C2410 找到位于 jz2440.h 中,打开include/configs/jz2440.h 修改代码,红色部分为修改后的代码:
//#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_S3C2440
然后编译测试,make 时出现一些错误:
通过命令 find -name s3c2410_nand.c 找到所在位置
打开 s3c2410_nand.c 文件,定位到59行:
发现 nand 结构由 s3c2410_nand 所定义,该结构体内容如下:
从上图中可以看出,要想使用 s3c2410_nand 必须配置CONFIG_S3C2410,而在 jz2440.h 中,我们已经将CONFIG_S3C2410 屏蔽,新增的是 CONFIG_S3C2440
由于本章我们用不到 nand 相关的东西,所以暂且将此文件设置成不编译
进入到 drivers/mtd/nand 目录下,打开 Makefile 文件:
要想不编译 s3c2410_nand.c 必须去掉CONFIG_NAND_S3C2410 这个宏
搜索 CONFIG_NAND_S3C2410 ,发现位于 jz2440.h 文件中,打开 jz2440.h 文件,定位到 CONFIG_NAND_S3C2410
如上图所示,只需将CONFIG_CMD_NAND 屏蔽即可,定位到 CONFIG_CMD_NAND , 修改代码:
#define CONFIG_CMD_ELF //#define CONFIG_CMD_NAND #define CONFIG_CMD_PING
修改完之后,编译,出现如下错误:
输入命令 find -name yaffs_uboot_glue.c 得到如下结果:
./fs/yaffs2/yaffs_uboot_glue.c
进入到目录 fs/yaffs2 下,打开 Makefile 文件:
我们不想让出错的文件参与编译,因此需要屏蔽 CONFIG_YAFFS2 这个宏,打开 jz2440.h 文件,定位到 CONFIG_YAFFS2 这个宏,修改代码:
#define CONFIG_MTD_PARTITIONS //#define CONFIG_YAFFS2 #define CONFIG_RBTREE
修改完成后,编译,重新烧写u-boot.bin
出现上图所示界面,表示NOR启动成功。