本文详细介绍了新版本的u-boot-2014_04在tq2440平台上的移植过程,期间参考了网上的其他移植文档,还有韦东山的移植uboot视频,讲的很好。下面是共享链接,欢迎下载,一同学习。其中有移植文档和patch。
http://pan.baidu.com/s/1jGxEYQq
到官网http://ftp.denx.de/pub/u-boot/下载u-boot-2014.04.tar.bz2
解压后在board/samsung/目录下仍然没有2440,虽然没有直接支持2440开发板,但其代码已经支持,只需添加相关配置即可。
一、 首先建立自己的开发板
拷贝board/samsung/smdk2410/目录到board/tq2440
pengdl@debian:~/work/tq2440/u-boot-2014.04$ cp -a board/samsung/smdk2410/ board/tq2440
进入board/tq2440目录修改
pengdl@debian:~/work/tq2440/u-boot-2014.04/board/tq2440$ mv smdk2410.c tq2440.c
修改该目录下的Makefile
obj-y := tq2440.o
拷贝配置文件(使用相似的smdk2410开发板的配置文件)
pengdl@debian:~/work/tq2440/u-boot-2014.04$ cp include/configs/smdk2410.h include/configs/tq2440.h
增加开发板配置选项
在顶层目录下的Makefile中搜索不到smdk2410
在顶层目录执行如下命令
pengdl@debian:~/work/tq2440/u-boot-2014.04$ grep "smdk2410" * -nR
./boards.cfg:74:
smdk2410 arm arm920t - samsung s3c24x0
./MAINTAINERS:774: smdk2410 ARM920T
./board/samsung/smdk2410/Makefile:28:COBJS := smdk2410.o
./board/tq2440/Makefile:28:COBJS := smdk2410.o
./arch/arm/include/asm/mach-types.h:1646:# define machine_is_smdk2410() (machine_arch_type == MACH_TYPE_SMDK2410)
./arch/arm/include/asm/mach-types.h:1648:# define machine_is_smdk2410() (0)
从这里知道在顶层目录下的boards.cfg文件中定义了smdk2410开发板的配置选项,仿照它定义TQ2440开发板的配置选项
# # Status, Arch, CPU:SPLCPU, SoC, Vendor, Board name, Target, Options, Maintainers
###########################################################################################################
Active arm arm920t s3c24x0 - tq2440 tq2440 - -
由于我在board目录下创建开发板目录,所以Vendor指定为空
二、 配置时钟
先大致看一下配置文件include/configs/tq2440.h
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_ARM920T /* This is an ARM920T Core */
#define CONFIG_S3C24X0 /* in a SAMSUNG S3C24x0-type SoC */
#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
这里是高级别的一些配置,配置了S3C2410 SoC和SMDK2410 Board,跟我使用的开发板不一致
根据我自己的开发板tq2440进行如下配置
//#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_S3C2440
//#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_AUTO_COMPLETE //开启命令自动补全
#define CONFIG_SYS_PROMPT "TQ2440 # " // 命令提示符
屏蔽一些暂时不用的支持,用的时候再加上
#if 0
#define CONFIG_CS8900 /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#endif
#if 0
#define CONFIG_USB_OHCI
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION
#endif
//#define CONFIG_CMD_DHCP
//#define CONFIG_CMD_NAND
//#define CONFIG_CMD_PING
//#define CONFIG_CMD_REGINFO
//#define CONFIG_CMD_USB
#if 0
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE
#endif
看下链接脚本arch/arm/cpu/u-boot.lds
CPUDIR/start.o (.text*)
从这里可以知道u-boot执行的第一个文件是arch/arm/cpu/arm920t/start.S
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
上面几行代码是针对S3C2410的
添加时钟初始化代码如下
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
# if defined(CONFIG_S3C2440)
ldr r1, =0x7fff
ldr r0, =INTSUBMSK // 屏蔽子中断
str r1, [r0]
# endif /* CONFIG_S3C2440 */
# if defined(CONFIG_S3C2440)
# define MPLLCON 0x4C000004 //系统主频配置寄存器
# define UPLLCON 0x4C000008 //USB频率配置寄存器
# define CAMDIVN 0x4C000018 //照相机时钟分频寄存器
ldr r0, =CAMDIVN
mov r1, #0
str r1, [r0]
ldr r0, =CLKDIVN
mov r1, #0x05
str r1, [r0]
/*如果HDIVN不等于0,CPU必须设置为异步总线模式*/
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
ldr r0, =UPLLCON
ldr r1, =0x38022 // USB时钟48MHZ
str r1, [r0]
/*
**When you set MPLL&UPLL values, you have to set the UPLL
**value first and then the MPLL value. (Needs intervals
**approximately 7 NOP)
*/
nop
nop
nop
nop
nop
nop
nop
ldr r0, =MPLLCON
ldr r1, =0x5c011 //CPU时钟400MHZ
str r1, [r0]
# else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2440 */
#endif /* CONFIG_S3C24X0 */
board/tq2440/tq2440.c中board_early_init_f()函数也初始化了时钟,因为我在start.S中已初始化了时钟,所以屏蔽掉board_early_init_f()中对时钟的初始化代码
// struct s3c24x0_clock_power * const clk_power =
// s3c24x0_get_base_clock_power();
struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
#if 0
/* to reduce PLL lock time, adjust the LOCKTIME register */
writel(0xFFFFFF, &clk_power->locktime);
/* configure MPLL */
writel((M_MDIV < &clk_power->mpllcon);
/* some delay between MPLL and UPLL */
pll_delay(4000);
/* configure UPLL */
writel((U_M_MDIV < &clk_power->upllcon);
/* some delay between MPLL and UPLL */
pll_delay(8000);
#endif
可以先配置u-boot支持直接烧写进内存SDRAM运行
修改配置文件tq2440.h
#define CONFIG_SYS_TEXT_BASE 0x32000000
CONFIG_SYS_TEXT_BASE指定了代码的加载地址,待会编译好后生成可执行二进制文件u—boot.bin,就要把u-boot.bin下载到该地址
我们现在需要直接烧写进内存运行,而底层初始化代码还没移植,所以我们需要跳过底层初始化
查看arch/arm/cpu/arm920t/start.S
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
如果没有定义CONFIG_SKIP_LOWLEVEL_INIT就跳转 cpu_init_crit函数执行,该函数进行了一些底层的初始化,比如内存。因为下面我们直接将u-boot下载到内存中运行,如果在内存中运行的同时再初始化内存,那么内存中的数据代码会遭到破坏。
所以我们在配置文件tq2440.h中定义该宏
#define CONFIG_SKIP_LOWLEVEL_INIT
修改一下顶层Makefile:
202 CROSS_COMPILE ?= arm-linux-
ARCH就不用我们手动配置了,因为在执行make tq2440_config时,会解析boards.cfg文件,得到ARCH的值。
pengdl@debian:~/work/tq2440/u-boot-2014.04$ make tq2440_config
编译完成生成可执行二进制文件u—boot.bin,开发板启动原有好的u-boot
将u-boot.bin下载到SDRAM的0x32000000地址,然后go 0x32000000运行
EmbedSky> tftp 0x32000000 u-boot.bin
(注意:在新版本的u-boot中,进行代码重定位relocate之前就已经在board_init_f中调用了全局性的代码,这些全局性的代码并不是位置无关的,所以这里需要将u-boot直接下载到它的链接地址处,防止程序跑飞)
dm9000 i/o: 0x20000300, id: 0x90000a46
MAC: 0a:1b:2c:3d:4e:5f
TFTP from server 192.168.1.8; our IP address is 192.168.1.6
Filename 'u-boot.bin'.
Load address: 0x32000000
Loading: checksum bad
checksum bad
checksum bad
checksum bad
checksum bad
checksum bad
T ###########
done
Bytes transferred = 153844 (258f4 hex)
EmbedSky> go 0x32000000
(注意:必须与刚才tftp下载到的地址相同)
## Starting application at 0x32000000 ...¡ø
U-Boot 2014.04 (Jun 28 2014 - 23:11:32)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz