TQ2440移植u-boot2016.11-单板建立并启动
移植说明
u-boot2016.11是S3C2440最后一版的uboot支持,所以选择了此版本进行移植,交叉编译器使用的是天嵌官方的交叉编译器,版本为4.4.3,使用的ubuntu1404系统。
(一)新建TQ2440单板
编辑u-boot顶层Makefile文件
gedit Makefile
定位到:
# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif
在下方插入:
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
这两句的作用为指定编译熟悉和交叉编译工具链。
将以下两句屏蔽掉,如果不屏蔽掉,后续会修改配置头文件中的默认宏定义而导致配置检查无法通过。
新建tq2440单板:
-
创建tq2440单板:
cp -a board/samsung/smdk2410 board/samsung/tq2440
mv board/samsung/tq2440/smdk2410.c board/samsung/tq2440/tq2440.c
-
拷贝头文件:
cp include/configs/smdk2410.h include/configs/tq2440.h
-
拷贝配置文件:
cp configs/smdk2410_defconfig configs/tq2440_defconfig
修改board/samsung/tq2440/目录下的文件:
-
修改Kconfig文件:
gedit board/samsung/tq2440/Kconfig
-
修改板卡支持维护信息文件MAINTAINERS:
gedit board/samsung/tq2440/MAINTAINERS
-
修改Makefile:
gedit board/samsung/tq2440/Makefile
-
修改configs/tq2440_defconfig文件:
gedit configs/tq2440_defconfig
-
修改arch/arm/Kconfig文件:
-
定位到:
config TARGET_SMDK2410
bool "Support smdk2410"
select CPU_ARM920T
下方添加:
config TARGET_TQ2440
bool "Support tq2440"
select CPU_ARM920T
-
定位到:
source "board/samsung/smdk2410/Kconfig
在下一行添加:
source "board/samsung/tq2440/Kconfig
~
修改内核引导机器码信息:
arch/arm/include/asm/mach-types.h
~~~~~~~~
TQ2440官方linux系统内核的机器码为168,所以我们需要修改u-boot的机器识别码,否则在启动引导内核时无法识别。
定位到:
#define MACH_TYPE_SMDK2410 193
在下方插入一行:
#define MACH_TYPE_TQ2440 168
定位到:
#ifdef CONFIG_ARCH_SMDK2410
# ifdef machine_arch_type
# undef machine_arch_type
# define machine_arch_type __machine_arch_type
# else
# define machine_arch_type MACH_TYPE_SMDK2410
# endif
# define machine_is_smdk2410() (machine_arch_type == MACH_TYPE_SMDK2410)
#else
# define machine_is_smdk2410() (0)
#endif
在下方添加:
#ifdef CONFIG_ARCH_TQ2440
# ifdef machine_arch_type
# undef machine_arch_type
# define machine_arch_type __machine_arch_type
# else
# define machine_arch_type MACH_TYPE_TQ2440
# endif
# define machine_is_tq2440() (machine_arch_type == MACH_TYPE_TQ2440)
#else
# define machine_is_tq2440() (0)
#endif
到此单板建立完成,编译一下看看是否成功:
make distclean
make tq2440_defconfig
-
make
OK,没问题,到此第一阶段的单板建立完成,后续开始移植修改代码。
(二)初始化代码修改
修改汇编启动文件arch/arm/cpu/arm920t/start.S
,将其中的代码替换为以下:
/*
* armboot - Startup Code for ARM920 CPU-core
*
* Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
* Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm-offsets.h>
#include <common.h>
#include <config.h>
/*
*************************************************************************
*
* Startup Code (called from the ARM reset exception vector)
*
* do important init only if we don't start from memory!
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************
*/
.globl reset
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr, r0
#define pWTCON 0x53000000
#define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */
#define INTSUBMSK 0x4A00001C
#define CLKDIVN 0x4C000014 /* clock divisor register */
#define MPLLCON 0x4C000004
#define UPLLCON 0x4C000008
/* turn off the watchdog */
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
/* mask all IRQs by setting all bits in the INTMR - default */
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
ldr r1, =0x7ff
ldr r0, =INTSUBMSK
str r1, [r0]
/* FCLK:HCLK:PCLK = 1:4:8 */
/* default FCLK is 405 MHz ! */
ldr r0, =CLKDIVN
mov r1, #5
str r1, [r0]
/* set asynchronous bus mod */
mrc p15, 0, r1, c1, c0, 0
orr r1, r1, #0xc0000000
mcr p15, 0, r1, c1, c0, 0
/* When you set MPLL&UPLL values, you have
* to set the UPLL value first and then the MPLL value.
* (Needs intervals approximately 7 NOP)
*/
/* set upllcon is 48MHz */
ldr r0, =UPLLCON
ldr r1, =((0x38 << 12) | (0x2 << 4) | (0x2 << 0))
str r1, [r0]
/* delay 7 nop */
nop
nop
nop
nop
nop
nop
nop
/* set mpllcon is 405MHz */
ldr r0, =MPLLCON
ldr r1, =((0x7F << 12) | (0x2 << 4) | (0x1 << 0))
str r1, [r0]
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
bl _main
/*------------------------------------------------------------------------------*/
.globl c_runtime_cpu_setup
c_runtime_cpu_setup:
mov pc, lr
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 1 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
*/
mov ip, lr
bl lowlevel_init
mov lr, ip
#endif
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
注意:这里我在这个汇编文件中设置了UPLLCON寄存器,目的是因为后续移植linux内核后,当使用USB鼠标或者U盘时,由于未先
设置UPLLCON寄存器导致在linux内核启动配置USB时钟时会设置失败,错误信息大概为usb 1-1: device descriptor read/64, error -110
的字样,这个错误是USB鼠标或U盘插入后能显示有设备插入但是无法枚举,也就是USB时钟没有配置为48M导致的,所以在此将USB的时钟设置为了48M,UPLLCON和MPLLCON寄存器是有设置顺序的,要先设置UPLLCON然后延时7个时钟在设置MPLLCON,这在S3C2440芯片数据手册中有说明:
修改SDRAM初始化代码文件board/samsung/tq2440/lowlevel_init.S
:
定位到:
SMRDATA:
.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
替换为:
SMRDATA:
.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 0x008C07A3 @ REFRESH
.long 0x000000B1 @ BANKSIZE,1的二进制为001,表示内存为64M,具体请看BANKSIZE寄存器
.long 0x00000030 @ MRSRB6
.long 0x00000030 @ MRSRB7
修改板卡初始化代码文件board/samsung/tq2440/tq2440.c
:
定位到:
#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
替换为:
#define FCLK_SPEED 2
#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
#elif (FCLK_SPEED == 2) /* Fout = 405MHz */
#define M_MDIV 0x7f
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
#define USB_CLOCK 2
#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
#elif (USB_CLOCK == 2)
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#endif
修改IO口,点亮LED灯:
~~~~~~~~
TQ2440板载4个LED灯接到了GPB8-GPB5,蜂鸣器接到了GPB0,GPB共有11个引脚,由高到低依次为GPB10-GPB0,由GPBCON、GPBUP和GPBDAT三个寄存器控制。
- GPBCON(0x56000010):每两位控制一个引脚,为00时表示输入引脚,为01时表示输出引脚,
为10时表示复用功能;
- GPBDAT(0x56000014):每一位表示一个引脚的输入或输出状态;
- GPBUP(0x56000018):每一位控制一个引脚,为0时表示使用上拉电阻,为1表示禁用上拉电
阻。
找到board_early_init_f
函数,定位到writel(0x00044555, &gpio->gpbcon)
,代码将0x00044555
写入到了GPBCON
寄存器,二进制为1000100010101010101
,也就是说将GPB10、GPB8、GPB6配置为了输入,其他配置为了输出;我们需要将GPB8-GPB5和GPB0配置为输出模式,其他引脚配置为复用模式,用计算器计算一下为:
所以将0x00044555
改为0x002956A9
即可。
原本的代码将0x000007FF
写入到了GPBUP
寄存器,0x7FF就是控制了11位,也就是将GPB的11个IO全部禁止使用上拉电阻,此处无需更改。
找到board_init
函数,修改为:
注意gd->bd->bi_boot_params = 0x30000100
这行代码,这里指定了在SDRAM中运行时的环境变量保存位置,暂时不修改,后面移植过程中在研究。
~
修改板卡初始化代码头文件:
gedit include/configs/tq2440.h
- 将
S3C2410
替换为S3C2440
- 将
SMDK2410
替换为TQ2440
创建NAND Flash 驱动
-
cp drivers/mtd/nand/s3c2410_nand.c drivers/mtd/nand/s3c2440_nand.c
-
gedit drivers/mtd/nand/s3c2440_nand.c
,将文件中的S3C2410
替换为S3C2440
-
gedit drivers/mtd/nand/Makefile
定位到: obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
在下一行加入: obj-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
设置从SDRAM启动代码
gedit arch/arm/cpu/arm920t/start.S
- 在开头定义一个宏
CONFIG_SKIP_LOWLEVEL_INIT
,目的是在arch/arm/cpu/arm920t/start.S
中跳过SDRAM的初始化,否则我们将程序通过tftp下载到内存处时,就会将SDRAM重新初始化破坏掉代码。
-
修改宏
CONFIG_SYS_TEXT_BASE
的值为0x30008000
,一会我们使用tftp将u-boot.bin下载到这个地址。
编译一下无误后使用天嵌自带的u-boot将刚编译出来u-boot.bin下载到内存0x30008000地址处,然后运行:
tftp 0x30008000 uboot.bin
-
go 0x30008000
成功启动!