U-Boot 2016.05 在S3C2440上的移植(1)——基本运行

相关环境:
系统版本:Ubuntu 16.04 64bit
U-boot 版本:2016.05
交叉编译链GCC版本为5.20,使用crosstool-ng自行制作。

基本运行的目标是能够顺利的编译通过,是之后移植修改的基础。

创建2440配置文件

复制2410的板子配置文件,以便在此基础上建立2440的配置文件。
涉及到的文件可在board/samsung/smdk2410/MAINTAINERS文件中找到。此文件实际上是一个代码维护说明,指出了这个板子的配置包含哪些文件,由谁维护等,其内容如下:

1
2
3
4
5
6
SMDK2410 BOARD
M: David Müller <d.mueller@elsoft.ch>
S: Maintained
F: board/samsung/smdk2410/
F: include/configs/smdk2410.h
F: configs/smdk2410_defconfig

从中可以看到,有三处需要复制:

1
2
3
4
5
6
cp -r board/samsung/smdk2410/ board/samsung/smdk2440/
mv board/samsung/smdk2440/smdk2410.c board/samsung/smdk2440/smdk2440.c

cp -r include/configs/smdk2410.h include/configs/smdk2440.h

cp -r configs/smdk2410_defconfig configs/smdk2440_defconfig

MAINTAINERS文件

修改board/samsung/smdk2440/MAINTAINERS文件,将其中2410的部分全部改为2440:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--- board/samsung/smdk2410/MAINTAINERS
+++ board/samsung/smdk2440/MAINTAINERS
@@ -1,6 +1,6 @@
-SMDK2410 BOARD
-M: David Müller <d.mueller@elsoft.ch>
+SMDK2440 BOARD
+M: Mingfei Gao <G199209@gmail.com>
S: Maintained
-F: board/samsung/smdk2410/
-F: include/configs/smdk2410.h
-F: configs/smdk2410_defconfig
+F: board/samsung/smdk2440/
+F: include/configs/smdk2440.h
+F: configs/smdk2440_defconfig

Kconfig文件

同理修改board/samsung/smdk2440/Kconfig文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--- board/samsung/smdk2410/Kconfig
+++ board/samsung/smdk2440/Kconfig
@@ -1,7 +1,7 @@
-if TARGET_SMDK2410
+if TARGET_SMDK2440

config SYS_BOARD
- default "smdk2410"
+ default "smdk2440"

config SYS_VENDOR
default "samsung"
@@ -10,6 +10,6 @@
default "s3c24x0"

config SYS_CONFIG_NAME
- default "smdk2410"
+ default "smdk2440"

endif

Makefile文件

同理修改board/samsung/smdk2440/Makefile文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
--- board/samsung/smdk2410/Makefile
+++ board/samsung/smdk2440/Makefile
@@ -4,6 +4,9 @@
#
# SPDX-License-Identifier: GPL-2.0+
#
+# Modified by Mingfei Gao
+# 2016.06.17
+#

-obj-y := smdk2410.o
+obj-y := smdk2440.o
obj-y += lowlevel_init.o

smdk2440.c文件

同理修改board/samsung/smdk2440/smdk2440.c文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--- board/samsung/smdk2410/smdk2410.c
+++ board/samsung/smdk2440/smdk2440.c
@@ -96,8 +96,8 @@

int board_init(void)
{
- /* arch number of SMDK2410-Board */
- gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
+ /* arch number of SMDK2440-Board */
+ gd->bd->bi_arch_number = MACH_TYPE_SMDK2440;

/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;

smdk2440_defconfig文件

修改configs/smdk2440_defconfig文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
--- configs/smdk2410_defconfig
+++ configs/smdk2440_defconfig
@@ -1,7 +1,7 @@
CONFIG_ARM=y
-CONFIG_TARGET_SMDK2410=y
+CONFIG_TARGET_SMDK2440=y
CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="SMDK2410 # "
+CONFIG_SYS_PROMPT="SMDK2440 # "
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_DHCP=y

arch/arm/Kconfig文件

因为前面修改了smdk2440_defconfig文件,将其中的配置项名称由CONFIG_TARGET_SMDK2410改成了CONFIG_TARGET_SMDK2440,故还需要修改arch/arm/Kconfig文件,在其中添加SMDK2440的板子配置才行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -96,6 +96,10 @@ config TARGET_SMDK2410
bool "Support smdk2410"
select CPU_ARM920T

+config TARGET_SMDK2440
+ bool "Support smdk2440"
+ select CPU_ARM920T
+
config TARGET_ASPENITE
bool "Support aspenite"
select CPU_ARM926EJS
@@ -854,6 +858,7 @@ source "board/phytec/pcm051/Kconfig"
source "board/phytec/pcm052/Kconfig"
source "board/ppcag/bg0900/Kconfig"
source "board/samsung/smdk2410/Kconfig"
+source "board/samsung/smdk2440/Kconfig"
source "board/sandisk/sansa_fuze_plus/Kconfig"
source "board/schulercontrol/sc_sps_1/Kconfig"
source "board/siemens/draco/Kconfig"

mach-types.h文件

smdk2440.c中将MACH_TYPE_SMDK2410改成了MACH_TYPE_SMDK2440,此时需要在arch/arm/include/asm/mach-types.h中添加对应的代码才行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--- a/arch/arm/include/asm/mach-types.h
+++ b/arch/arm/include/asm/mach-types.h
@@ -57,6 +57,7 @@ extern unsigned int __machine_arch_type;
#define MACH_TYPE_IQ80321 169
#define MACH_TYPE_KS8695 180
#define MACH_TYPE_SMDK2410 193
+#define MACH_TYPE_SMDK2440 1999
#define MACH_TYPE_CEIVA 200
#define MACH_TYPE_VOICEBLUE 218
#define MACH_TYPE_H5400 220
@@ -1648,6 +1649,19 @@ extern unsigned int __machine_arch_type;
# define machine_is_smdk2410() (0)
#endif

+#ifdef CONFIG_ARCH_SMDK2440
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_SMDK2440
+# endif
+# define machine_is_smdk2440() (machine_arch_type == MACH_TYPE_SMDK2440)
+#else
+# define machine_is_smdk2440() (0)
+#endif
+
+
#ifdef CONFIG_ARCH_CEIVA
# ifdef machine_arch_type
# undef machine_arch_type

此处MACH_TYPE的宏定义值是根据Linux kernel中的定义值来确定的,二者最好匹配起来,不过要是不同也没有关系,在引导内核的时候也可以通过环境变量来设置这个值。

smdk2440.h文件

修改include/configs/smdk2440.h文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
--- a/include/configs/smdk2440.h
+++ b/include/configs/smdk2440.h
@@ -18,8 +18,8 @@
* (easy to change)
*/
#define CONFIG_S3C24X0 /* This is a SAMSUNG S3C24x0-type SoC */
-#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
-#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
+#define CONFIG_S3C2440 /* specifically a SAMSUNG S3C2440 SoC */
+#define CONFIG_SMDK2440 /* on a SAMSUNG SMDK2440 Board */

#define CONFIG_SYS_TEXT_BASE 0x0

添加交叉编译链路径

最后,添加交叉编译链的路径,根据U-Boot README说明,可以不修改Makefile文件,而是使用环境变量CROSS_COMPILE来指定交叉编译链,不过这里还是采用了修改Makefile文件的方法。修改顶层Makefile文件,即Makefile

1
2
3
4
5
6
7
8
9
10
11
--- a/Makefile
+++ b/Makefile
@@ -246,6 +246,8 @@ ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif

+CROSS_COMPILE = "/home/gmf/uboot/toolchain/x-tools/arm-s3c2440-linux-gnueabi/bin/arm-s3c2440-linux-gnueabi-"
+
KCONFIG_CONFIG ?= .config
export KCONFIG_CONFIG

测试编译

至此,已成功创建2440的配置文件,使用以下命令进行配置和编译:

1
2
make smdk2440_defconfig
make all

顺利编译后就会在U-Boot根目录下生成所需的u-boot.bin文件。当然,此文件目前还是针对2410的,接下来需要针对2440进行修改移植。

Stage 1代码移植

第一阶段代码一般是汇编代码,用于初始化硬件,建立C语言运行环境等。从README文件中可以找到U-Boot初始化流程的说明,位于Board Initialisation Flow部分,其中提到最初执行的启动代码为start.S文件,对于2440来说,就是arch/arm/cpu/arm920t/start.S文件,下面针对2440来修改此文件。

修改屏蔽中断代码

修改屏蔽中断的代码:

1
2
3
4
5
6
7
8
9
10
11
@@ -78,6 +78,10 @@ copyex:
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
+# elif defined(CONFIG_S3C2440)
+ ldr r1, =0x7fff
+ ldr r0, =INTSUBMSK
+ str r1, [r0]
# endif

/* FCLK:HCLK:PCLK = 1:2:4 */

此处的设置参考2440数据手册中对INTSUBMSK寄存器的说明:

更改时钟设置

更改时钟设置,默认start.S中只有时钟分频设置,PLL的设置放在Stage 2中进行。对此进行下修改,在此完成所有时钟部分的初始化设置。一般都将2400配置为:FCLK=400M;HCLK=100M;PCLK=50M,需要将原来的:

1
2
3
4
5
/* FCLK:HCLK:PCLK = 1:2:4 */
/* defualt FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]

改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/* Initialize Clock */
# if defined(CONFIG_S3C2440)
#define MPLLCON 0x4C000004
#define UPLLCON 0x4C000008

#define S3C2440_MPLL_400M ((92 << 12) | (1 << 4) | (1))
#define S3C2440_UPLL_48M ((56 << 12) | (2 << 4) | (2))

/* FCLK:HCLK:PCLK = 1:4:8 */
ldr r0, =CLKDIVN
mov r1, #5
str r1, [r0]

/* MMU Set Async Bus Mode */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0xC0000000
mcr p15, 0, r0, c1, c0, 0

/* Set PLL */
ldr r0, =MPLLCON
ldr r1, =S3C2440_MPLL_400M
str r1, [r0]

/* Some delay between MPLL and UPLL */
mov r0, #(1 << 13)
mov r1, #0
1:
subs r0, r0, #1
cmp r0, r1
bne 1b

ldr r0, =UPLLCON
ldr r1, =S3C2440_UPLL_48M
str r1, [r0]

/* Some delay */
mov r0, #(1 << 14)
mov r1, #0
2:
subs r0, r0, #1
cmp r0, r1
bne 2b

# else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* defualt FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
# endif

修改SDRAM设置

start.S文件会跳转到board/samsung/smdk2440/lowlevel_init.S中继续执行,下面来修改此文件。

修改SDRAM刷新周期、预充电时间,根据SDRAM的数据手册刷新要求为8192/64ms,一般HCLK设置为100M,故需要将REFCNT的值改为1268;Trp根据数据手册为20ns,故选择3 clk即可;另外2440中没有Tchr寄存器,需要删掉:

1
2
3
4
5
6
7
8
9
10
11
@@ -105,8 +105,7 @@
/* REFRESH parameter */
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
-#define Trp 0x0 /* 2clk */
+#define Trp 0x1 /* 3clk */
#define Trc 0x3 /* 7clk */
-#define Tchr 0x2 /* 3clk */
-#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
+#define REFCNT 1268 /* period=7.81us, HCLK=100Mhz, (2048+1-7.81*100) */
/**************************************/

Stage 1中,start.S还会跳转去执行_main,不过这个是平台无关的代码,移植时不需要考虑。下面开始移植Stage 2代码。

Stage 2代码移植

因为在Stage 1中已经完成了PLL时钟的初始化,这里将Stage 2中的相关代码全部删掉。所在文件为board/samsung/smdk2440/smdk2440.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
--- a/board/samsung/smdk2440/smdk2440.c
+++ b/board/samsung/smdk2440/smdk2440.c
@@ -16,36 +16,6 @@

DECLARE_GLOBAL_DATA_PTR;

-#define FCLK_SPEED 1
-
-#if (FCLK_SPEED == 0) /* Fout = 203MHz, Fin = 12MHz for Audio */
-#define M_MDIV 0xC3
-#define M_PDIV 0x4
-#define M_SDIV 0x1
-#elif (FCLK_SPEED == 1) /* Fout = 202.8MHz */
-#define M_MDIV 0xA1
-#define M_PDIV 0x3
-#define M_SDIV 0x1
-#endif
-
-#define USB_CLOCK 1
-
-#if (USB_CLOCK == 0)
-#define U_M_MDIV 0xA1
-#define U_M_PDIV 0x3
-#define U_M_SDIV 0x1
-#elif (USB_CLOCK == 1)
-#define U_M_MDIV 0x48
-#define U_M_PDIV 0x3
-#define U_M_SDIV 0x2
-#endif
-
-static inline void pll_delay(unsigned long loops)
-{
- __asm__ volatile ("1:\n"
- "subs %0, %1, #1\n"
- "bne 1b" : "=r" (loops) : "0" (loops));
-}

/*
* Miscellaneous platform dependent initialisations
@@ -53,27 +23,8 @@ static inline void pll_delay(unsigned long loops)

int board_early_init_f(void)
{
- struct s3c24x0_clock_power * const clk_power =
- s3c24x0_get_base_clock_power();
struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();

- /* 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);
-
- /* some delay between MPLL and UPLL */
- pll_delay(8000);
-
/* set up the I/O ports */
writel(0x007FFFFF, &gpio->gpacon);
writel(0x00044555, &gpio->gpbcon);

编译运行

做完上面的修改后,编译UBoot:

1
2
make smdk2440_defconfig
make all

将生成的u-boot.bin文件通过JTAG烧写到板子的Nor Flash中,之后连上串口(Serial 0),波特率设置为115200,复位后即可看到串口有数据输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
U-Boot 2016.05-gf52ee9c-dirty (Jun 19 2016 - 16:45:57 +0800)

CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: 0 Bytes
NAND: 0 MiB
*** Warning - bad CRC, using default environment

In: serial
Out: serial
Err: serial
Net: CS8900-0
Error: CS8900-0 address not set.

SMDK2440 #

这说明U-Boot已经运行起来了,不过没有识别出Flash,而且网卡配置有误,故我们还需要继续进行修改。

移植好的U-Boot见我的Github项目

文章目录
  1. 1. 创建2440配置文件
    1. 1.1. MAINTAINERS文件
    2. 1.2. Kconfig文件
    3. 1.3. Makefile文件
    4. 1.4. smdk2440.c文件
    5. 1.5. smdk2440_defconfig文件
    6. 1.6. arch/arm/Kconfig文件
    7. 1.7. mach-types.h文件
    8. 1.8. smdk2440.h文件
    9. 1.9. 添加交叉编译链路径
    10. 1.10. 测试编译
  2. 2. Stage 1代码移植
    1. 2.1. 修改屏蔽中断代码
    2. 2.2. 更改时钟设置
    3. 2.3. 修改SDRAM设置
  3. 3. Stage 2代码移植
  4. 4. 编译运行