http://www.eetop.cn/blog/html/70/261970-16817.html
移植过程并非那么顺利,但是坚持下去,一切都会明朗
--------------------------------step1-----------------------------------
1 为smdk2440建立编译项
打开uboot根目录下的Makefile,添加以下项
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/gedit Makefile
smdk2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2440 NULL s3c24x0
说明:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录
smdk2440: 开发板的型号(BOARD),对应于board/smdk2440/目录
NULL: 开发者/或经销商(vender)
s3c24x0: 片上系统(SOC)
2 设置交叉编译环境变量
ifeq ($(ARCH),arm)
CROSS_COMPILE =/usr/local/arm/3.3.2/bin/arm-linux-
endif
3 在/board子目录中建立自己的开发板smdk2440目录 并复制smdk2410目录下的所有文件到smdk2440目录
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board# mkdir smdk2440
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board# cp -arf smdk2410/* smdk2440
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board# cd smdk2440
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# ls
config.mk flash.c lowlevel_init.S Makefile smdk2410.c u-boot.lds
将smdk2410.c替换成smdk2440.c
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# mv smdk2410.c smdk2440.c
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# ls
config.mk flash.c lowlevel_init.S Makefile smdk2440.c u-boot.lds
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440#
修改该目录下的Makefile文件,加入smdk2440.c的编译项
COBJS := smdk2440.o flash.o
4 在include/configs/中建立配置头文件
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/include/configs# cp smdk2410.h smdk2440.h
测试编译是否成功
硬件浮点和软件浮点的问题
如果编译环境和u-boot的版本搭配不合适的话会出现以下错误:
arm-linux-ld: ERROR: /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_udivdi3.oS) uses hardware FP, whereas u-boot uses software FP
文件格式无法识别: failed to merge target specific data of file /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_udivdi3.oS)
arm-linux-ld: ERROR: /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_clz.oS) uses hardware FP, whereas u-boot uses software FP
文件格式无法识别: failed to merge target specific data of file /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_clz.oS)
make: *** [u-boot] 错误 1
原因是u-boot使用的是软浮点,而交叉编译arm-linux-gcc是硬件浮点。
uboot的1.1.6版本的cpu\arm920t\config.mk中:
uboot的2009.11版本的cpu\arm920t\config.mk中:
解决办法:去掉"cpu/arm920t/config.mk"文件中的 -msoft-float
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6# make smdk2440_config
Configuring for smdk2440 board...
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6# make
完成之后,如果没有错误会在该目录下生成 u-boot u-boot.srec u-boot u-boot.bin
如果希望生成u-boot的反汇编文件,那么在根目录下打开Makefileh查找u-boot.bin
在239行ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
修改为: ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)u-boot.dis $(obj)System.map $(U_BOOT_NAND)
-------------------------------step2---------------------------------------
-------------------------------step2---------------------------------------
5 清除编译生成的文件
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6# make distclean
6 修改/cpu/arm920t/start.S
找到程序的入口点,reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
在下面添加开发板的LED测试代码,以方便观看u-boot的运行
//测试开发板的LED
#if 1
//LED分别由S3C2440的PB5、6、7、8口来控制
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
#define GPBUP 0x56000018
//以下对寄存器的操作参照S3C2440的DataSheet进行操作
ldr r0, =GPBUP
ldr r1, =0x7FF //即:二进制11111111111,关闭PB口上拉
str r1, [r0]
ldr r0, =GPBCON //配置PB5、6、7、8为输出口,对应PBCON寄存器的第10-17位
ldr r1, =0x154FD //即:二进制010101010011111101
str r1, [r0]
ldr r0, =GPBDAT
ldr r1, =0x1C0 //即:二进制111000000,PB5设为低电平,6、7、8为高电平
str r1, [r0] ////点亮开发板上的LED1,
#endif
接下来要关闭看门狗、初始化系统时钟
代码修改如下:
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
#endif
#define CLK_CTL_BASE 0x4C000000
#define MDIV_405 0x7f << 12
#define PSDIV_405 0x21
#define UPLL_MDIV_48 0x38 << 12
#define UPLL_PSDIV_48 0x22
#define MDIV_200 0xa1 << 12
#define PSDIV_200 0x31
ldr r0, =pWTCON
str r1, [r0]
/*mask all IRQs by setting all bits in the INTMR – default*/
mov r1, #0xffffffff
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x7ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
#if defined(CONFIG_S3C2440)
ldr r1, =0x7fff /*根据2440芯片手册,INTSUBMSK有15位可用*/
ldr r0, =INTSUBMSK
str r1, [r0]
#endif
#if defined(CONFIG_S3C2440)
/* FCLK:HCLK:PCLK = 1:4:8 */
ldr r0, =CLKDIVN
mov r1, #5
str r1, [r0]
mrc p15, 0, r1, c1, c0, 0 /*read ctrl register */
orr r1, r1, #0xc0000000 /*Asynchronous */
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register */
/*now, CPU clock is 405.00 Mhz */
mov r1, #CLK_CTL_BASE
mov r2, #UPLL_MDIV_48 /*UPLL */
add r2, r2, #UPLL_PSDIV_48
str r2, [r1, #0x08] /*write UPLL first,48MHz */
mov r2, #MDIV_405 /* mpll_405mhz */
add r2, r2, #PSDIV_405 /* mpll_405mhz h*/
str r2, [r1, #0x04] /* MPLLCON hugerat */
#else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
mrc p15, 0, r1, c1, c0, 0
orr r1, r1, #0xc0000000
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register */
mov r1, #CLK_CTL_BASE
mov r2, #MDIV_200
add r2, r2, #PSDIV_200
str r2, [r1, #0x04]
#endif
#endif /*CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440*/
-----------------------------------------------------------------
接下来为了观看u-boot的运行,添加一段LED的程序,此时点亮LED2,关闭其它LED
//点亮LED2
ldr r0, =GPBDAT
ldr r1, =0x1A0 //即:二进制110100000,PB6设为低电平,5、7、8为高电平
str r1, [r0] //点亮开发板上的LED2,8 时钟部分还需要在board/smdk2440/smdk2440.c中和cpu/arm920t/s3c24x0/speed.c中修改
首先 在smdk2440.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 */
#if defined(CONFIG_S3C2410)
/* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#endif
#if defined(CONFIG_S3C2440)
/* Fout = 405MHz */
#define M_MDIV 0x7f
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
/*#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
#if defined(CONFIG_S3C2410)
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#endif
#if defined(CONFIG_S3C2440)
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#endif
/*#define U_M_MDIV 0x48
#define U_M_PDIV 0x3*/
#define U_M_SDIV 0x2
#endif
在speed.c中作如下更改
static ulong get_PLLCLK(int pllreg)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
ulong r, m, p, s;
if (pllreg == MPLL)
r = clk_power->MPLLCON;
else if (pllreg == UPLL)
r = clk_power->UPLLCON;
else
hang();
m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
#if defined(CONFIG_S3C2440) //依据手册
if (pllreg == MPLL)
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
else if (pllreg == UPLL)
#endif
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
}
并修改
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
#if defined(CONFIG_S3C2440)//依据手册
if (clk_power->CLKDIVN & 0x6)
{
if ((clk_power->CLKDIVN & 0x6)==2) return(get_FCLK()/2);
if ((clk_power->CLKDIVN & 0x6)==6) return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);
if ((clk_power->CLKDIVN & 0x6)==4) return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);
return(get_FCLK());
}
else return(get_FCLK());
#else
return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
#endif
}
-------------------------------------------------
编译,保证无错误再往下进行
------------------------------------------------
9 还是回到start.S
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
以上代码使程序跳转到cpu_init_crit在cpu_init_crit中程序还要跳转到
lowlevel_init 执行,该函数在board/smdk2440/lowlevel_init.S中,用于对SDRAM的初始化,在该文件中需要修改SDRAM的刷新参数
#define B1_BWSCON (DW16)
#define B3_BWSCON (DW16)
#define B4_BWSCON (DW16 + WAIT + UBLB)
#define B3_Tcos 0x0
#define B3_Tcoh 0x0
#define B3_Tacp 0x0
#define B4_Tcos 0x3
#define B4_Tcoh 0x1
#define B4_Tah 0x3
#define B4_Tacp 0x3
#define B6_Trcd 0x2
#define B7_Trcd 0x2
#define REFCNT 1259
SDRAM初始化完成后再加一段LED测试的程序,以方便观察u-boot的运行打开start.S
在#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
后面加:
//点亮LED3
ldr r0, =GPBDAT
ldr r1, =0x160 //即:二进制101100000,PB7设为低电平,5、6、8为高电平
str r1, [r0] //点亮开发板上的LED3,
10 继续,加入NANDFLASH启动代码
需要屏蔽掉以下代码搬移部分
#if 0
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
添加以下代码:
/***************** NAND_BOOT *************************************************/
#define LENGTH_UBOOT 0x40000
#define NAND_CTL_BASE 0x4E000000
#ifdef CONFIG_S3C2440
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFSTAT 0x20
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
str r2, [r1, #oNFCONT]
ldr r2, [r1, #oNFCONT]
ldr r2, =(0x6) @ RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x4
beq nand2
ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2 @ Flash Memory Chip Disable
str r2, [r1, #oNFCONT]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
/***************** NAND_FLASH_PAGE_SIZE_2K ***********************************/
nand_page_2k:
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #LENGTH_UBOOT
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read_2k:
mov r0, #0x60
bl test_led_on
loop2k:
b loop2k @ infinite loop
ok_nand_read:
@ verify
mov r0, #0
ldr r1, =TEXT_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq stack_setup
bne go_next
notmatch:
mov r0, #0x20
bl test_led_on
loop3:
b loop3 @ infinite loop
#endif
在ldr pc, _start_armboot后添加 定义堆栈地址和宽度
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
在_start_armboot: .word start_armboot后面添加
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
11 NANDFLASH启动代码有了,但还没有实现里面所调用的相关 nand_read_ll操作函数,因此需要在board/smdk2440/目录下建立nand_read.c文件,以实现nand_read_ll函数
进入到board/smdk2440/目录下,root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# gedit nand_read.c
输入以下代码并保存
#include <config.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#if defined(CONFIG_S3C2440)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xC)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))
#define NAND_CHIP_DISABLE (NFCONT |= (1<<1))
#define NAND_CLEAR_RB (NFSTAT |= (1<<2))
#define NAND_DETECT_RB { while(! (NFSTAT&(1<<2)));}
#define NAND_SECTOR_SIZE_2K 2048
#define NAND_BLOCK_MASK_2K (NAND_SECTOR_SIZE_2K - 1)
/* low level nand read function */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
if ((start_addr & NAND_BLOCK_MASK_2K) || (size & NAND_BLOCK_MASK_2K)) {
return -1; /* invalid alignment */
}
NAND_CHIP_ENABLE;
for(i=start_addr; i < (start_addr + size); i += NAND_SECTOR_SIZE_2K) {
/* READ0 */
NAND_CLEAR_RB;
NFCMD = 0;
/* Write Address */
NFADDR = 0;
NFADDR = 0;
NFADDR = (i >> 11) & 0xff;
NFADDR = (i >> 19) & 0xff;
NFADDR = (i >> 27) & 0xff;
NFCMD = 0x30;
NAND_DETECT_RB;
for(j=0; j < NAND_SECTOR_SIZE_2K; j++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
NAND_CHIP_DISABLE;
return 0;
}
#endif
并在该目录下的Makefile文件中加入nand_read.c的编译项,COBJS := smdk2440.o flash.o nand_read.o
打开该目录下的u-boot.lds,添加以下代码,防止编译器将nand_read编译到4K之后
.text :
{
cpu/arm920t/start.o (.text)
board/smdk2440/lowlevel_init.o (.text)
board/smdk2440/nand_read.o (.text)
*(.text)
}
12 接下来添加nandflash的有关操作支持
在cpu/arm920t/s3c24x0中建立文件s3c2440_nand.c
并添加如下代码:
#include <common.h>
#if 0
#define DEBUGN printf
#else
#define DEBUGN(x, args ...) {}
#endif
#if defined(CONFIG_CMD_NAND)
#if !defined(CONFIG_NAND_LEGACY)
#include <nand.h>
#include <s3c2410.h>
#include <asm/io.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#if defined(CONFIG_S3C2410)
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
#define NFECC0 __REGb(NF_BASE + 0x14)
#define NFECC1 __REGb(NF_BASE + 0x15)
#define NFECC2 __REGb(NF_BASE + 0x16)
#else
#if defined(CONFIG_S3C2440)
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xc)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFMECCD0 __REGi(NF_BASE + 0x14)
#define NFMECCD1 __REGi(NF_BASE + 0x18)
#define NFSECCD __REGi(NF_BASE + 0x1C)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT0 __REGi(NF_BASE + 0x24)
#define NFSTAT1 __REGi(NF_BASE + 0x28)
#define NFMECC0 __REGi(NF_BASE + 0x2C)
#define NFMECC1 __REGi(NF_BASE + 0x30)
#define NFSECC __REGi(NF_BASE + 0x34)
#define NFSBLK __REGi(NF_BASE + 0x38)
#define NFEBLK __REGi(NF_BASE + 0x3c)
#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08
#endif
#endif
#define S3C2410_NFCONF_EN (1<<15)
#define S3C2410_NFCONF_512BYTE (1<<14)
#define S3C2410_NFCONF_4STEP (1<<13)
#define S3C2410_NFCONF_INITECC (1<<12)
#define S3C2410_NFCONF_nFCE (1<<11)
#define S3C2410_NFCONF_TACLS(x) ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
#define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8
ulong IO_ADDR_W = NF_BASE; //by hugerat,phase3
static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
#if defined(CONFIG_S3C2410)
if (ctrl & NAND_CTRL_CHANGE) {
//ulong IO_ADDR_W = NF_BASE; by hugerat.phase3
IO_ADDR_W = NF_BASE;
if (!(ctrl & NAND_CLE))
IO_ADDR_W |= S3C2410_ADDR_NCLE;
if (!(ctrl & NAND_ALE))
IO_ADDR_W |= S3C2410_ADDR_NALE;
//chip->IO_ADDR_W = (void *)IO_ADDR_W; //by hugerat,phase3
if (ctrl & NAND_NCE)
NFCONF &= ~S3C2410_NFCONF_nFCE;
else
NFCONF |= S3C2410_NFCONF_nFCE;
}
if (cmd != NAND_CMD_NONE)
//writeb(cmd, chip->IO_ADDR_W);
writeb(cmd,(void *)IO_ADDR_W);
#endif
#if defined(CONFIG_S3C2440)
if (ctrl & NAND_CTRL_CHANGE) {
IO_ADDR_W = NF_BASE; //by hugerat,phase3
if (!(ctrl & NAND_CLE))
{
IO_ADDR_W |= S3C2440_ADDR_NALE;}
if (!(ctrl & NAND_ALE))
{
IO_ADDR_W |= S3C2440_ADDR_NCLE;}
//chip->IO_ADDR_W = (void *)IO_ADDR_W;
if (ctrl & NAND_NCE)
{NFCONT &= ~S3C2440_NFCONT_nCE;
//DEBUGN("NFCONT is 0x%x ",NFCONT);
//DEBUGN("nand Enable ");
}
else
{NFCONT |= S3C2440_NFCONT_nCE;
//DEBUGN("nand disable ");
}
}
if (cmd != NAND_CMD_NONE)
writeb(cmd,(void *)IO_ADDR_W);
//writeb(cmd, chip->IO_ADDR_W);
#endif
}
static int s3c2410_dev_ready(struct mtd_info *mtd)
{
DEBUGN("dev_ready\n");
return (NFSTAT & 0x01);
}
#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
NFCONF |= S3C2410_NFCONF_INITECC;
}
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
ecc_code[0] = NFECC0;
ecc_code[1] = NFECC1;
ecc_code[2] = NFECC2;
DEBUGN("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
return 0;
}
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
if (read_ecc[0] == calc_ecc[0] &&
read_ecc[1] == calc_ecc[1] &&
read_ecc[2] == calc_ecc[2])
return 0;
printf("s3c2410_nand_correct_data: not implemented\n");
return -1;
}
#endif
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
DEBUGN("board_nand_init()\n");
clk_power->CLKCON |= (1 << 4);
#if defined(CONFIG_S3C2410)
DEBUGN("CONFIG_S3C2410\n");
/* initialize hardware */
twrph0 = 3; twrph1 = 0; tacls = 0;
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
NFCONF = cfg;
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;
nand->cmd_ctrl = s3c2410_hwcontrol;
nand->dev_ready = s3c2410_dev_ready;
#else
#if defined(CONFIG_S3C2440)
DEBUGN("CONFIG_S3C2440\n");
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
DEBUGN("cfg is %x\n",cfg);
DEBUGN("NFCONF is %lx\n",NFCONF);
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
DEBUGN("cfg is %lx\n",cfg);
DEBUGN("NFCONT is %x\n",NFCONT);
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
nand->cmd_ctrl = s3c2410_hwcontrol;
nand->dev_ready = s3c2410_dev_ready;
#endif
#endif
#ifdef CONFIG_S3C2410_NAND_HWECC
nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
nand->ecc.calculate = s3c2410_nand_calculate_ecc;
nand->ecc.correct = s3c2410_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW3_512;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif
#ifdef CONFIG_S3C2410_NAND_BBT
nand->options = NAND_USE_FLASH_BBT;
#else
nand->options = 0;
#endif
DEBUGN("end of nand_init\n");
return 0;
}
#else
#error "U-Boot legacy NAND support not available for S3C2410"
#endif
#endif
并在该目录下的Makefile文件中添加s3c2440_nand.c的编译项
COBJS = i2c.o interrupts.o serial.o speed.o \
usb_ohci.o s3c2440_nand.o
-------------------------
13 最后需要加入CONFIG_S3C2440的宏定义,以便修改的代码能编译进去
在include/configs/smdk2440.h文件中
修改
//#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
//#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_smdk2440 1 /* on a SAMSUNG SMDK2410 Board *
屏蔽掉CS8900的网卡驱动,2440板卡上的是DM9000,
//#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
//#define CS8900_BASE 0x19000300
//#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
添加DM9000的驱动
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_USE_16BIT 1
#define CONFIG_DM9000_BASE 0x20000300
#define DM9000_IO 0x20000300
#define DM9000_DATA 0x20000304
添加
# if defined(CONFIG_S3C2440)
#define CONFIG_S3C2440_NAND_BOOT 1
#endif
修改
#define CFG_PROMPT "SMDK2440 # " /* Monitor Command Prompt */
修改include/common.h 449行
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440)
修改include/s3c24x0.h
将里面所有的#ifdef CONFIG_S3C2410
修改为:
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
将cpu/arm920t/s3c24x0/interrupt.c中添加 defined (CONFIG_S3C2440)的项
#elif defined(CONFIG_SBC2410X) || \
defined(CONFIG_SMDK2410) || \
defined(CONFIG_VCMA9) || \
defined(CONFIG_smdk2440)
在cpu/arm920t/s3c24x0/serial.c中 添加defined (CONFIG_S3C2440)的项
在cpu/arm920t/s3c24x0/speed.c中添加defined (CONFIG_S3C2440)的项
在rtc/s3c24x0_rtc.c中添加defined (CONFIG_S3C2440)的项
测试编译,将u-boot.bin烧录到NANDFLASH,成功!!!!
串口输出信息:
U-Boot 1.1.6 (Jan 12 2010 - 21:28:15)
DRAM: 64 MB
Flash: 512 kB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
SMDK2440 #
一开始出现乱码,是时钟设置有误,后来在speed.c添加了代码
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
#if defined(CONFIG_S3C2440)
if (clk_power->CLKDIVN & 0x6)
{
if ((clk_power->CLKDIVN & 0x6)==2) return(get_FCLK()/2);
if ((clk_power->CLKDIVN & 0x6)==6) return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);
if ((clk_power->CLKDIVN & 0x6)==4) return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);
return(get_FCLK());
}
else return(get_FCLK());
#else
return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
#endif
}
输出一切正常
u-boot第一阶段的移植到此,总结一下,继续前行