您的位置:首页 > 其它

U-BOOT1.2.0移植S3C2440成功

2011-07-04 00:00 381 查看
主要参考
http://blog.chinaunix.net/u1/34474/showart.php?id=397315文章,tekkamna写的很详细,我就直接搬过来,记录如下:(本人在他的基础上修改了DM9000x的驱动,SDRAM的刷新参数,和网络控制芯片的基地址)交叉编译器用的是3.3.2版本。

首先,U-Boot1.2.0还没有支持s3c2440,这次移植是用2410的文件稍作修改而成的。其实2440和2410的区别主要是2440的主频更高,增加了摄像头接口和AC‘97音频接口;寄存器方面,除了新增模块的寄存器外,
移植所要注意的是NAND FlASH控制器的寄存器有较大的变化、芯片的时钟频率控制寄存器(芯片PLL的寄存器)有一定的变化。其他寄存器基本是兼容的。

一、在U-Boot中建立自己的开发板类型,并测试编译。
我为开发板取名叫: hongge2440

0 在工作目录下解压U-Boot。
$tar zxvf u-boot.git.tar.gz

1 进入U-Boot目录,修改Makefile
$cd u-boot.git/
$vi Makefile
#为hongge2440建立编译项

sbc2410x_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0

hongge2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t hongge2440 hongge s3c24x0
各项的意思如下:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
hongge2440: 开发板的型号(BOARD),对应于board/hongge/hongge2440目录。
hongge: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。

2 在/board子目录中建立自己的开发板hongge2440目录

由于我在上一步板子的开发者/或经销商(vender)中填了 hongge ,所以开发板hongge2440目录一定要建在/board子目录中的hongge目录下 ,否则编译会出错。

$cd board
$mkdir hongge hongge/hongge2440
$cp -arf sbc2410x/* hongge/hongge2440/
$cd hongge/hongge2440
$mv sbc2410x.c hongge.c

还要记得修改自己的开发板hongge2440目录下的Makefile文件,不然编译时会出错:
COBJS := hongge2440.o flash.o
$vi Makefile

3 在include/configs/中建立配置头文件
$cd ../../..
$cp include/configs/sbc2410x.h include/configs/hongge2440.h

4 测试编译能否成功
$make hongge2440_config
Configuring for hongge2440 board...
(如果出现:
$ make hongge2440_config
Makefile:1927: *** 遗漏分隔符 。 停止。
请在U-boot的根目录下的Makefile的
@$(MKCONFIG) $(@:_config=) arm arm920t hongge2440 hongge)
前加上“Tab”键)
$make

我到这一步测试交叉编译成功!!





























































二、修改U-Boot中的文件,以匹配自己的板子。
1 修改/cpu/arm920t/start.S

(0)修改寄存器地址定义
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(CONFIG_S3C2410)|| defined(CONFIG_S3C2440)
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
#endif

(1)修改中断禁止部分

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
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]
# if defined(CONFIG_S3C2410)
ldr r1, =0x7ff //根据2410芯片手册,INTSUBMSK有11位可用,
//vivi也是0x7ff,不知为什么U-Boot一直没改过来。
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
# if defined(CONFIG_S3C2440)
ldr r1, =0x7fff //根据2440芯片手册,INTSUBMSK有15位可用
ldr r0, =INTSUBMSK
str r1, [r0]
# endif

(2)修改时钟设置(2440的主频可达533MHz,但是我设到533MHz时系统很不稳定,不知是不是SDRAM和总线配置的影响,所以现在先设到405MHz,以后在改进。)

/* 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 tekkaman*/
orr r1, r1, #0xc0000000 /*Asynchronous tekkaman*/
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register tekkaman*/

#if defined(CONFIG_S3C2440)
/*now, CPU clock is 405.00 Mhz tekkaman*/
mov r1, #CLK_CTL_BASE /* tekkaman*/
mov r2, #MDIV_405 /* mpll_405mhz tekkaman*/
add r2, r2, #PSDIV_405 /* mpll_405mhz tekkaman*/
str r2, [r1, #0x04] /* MPLLCON tekkaman */
#endif
#if defined(CONFIG_S3C2410)
/*now, CPU clock is 202.8 Mhz tekkaman*/
mov r1, #CLK_CTL_BASE /* tekkaman*/
mov r2, #MDIV_200 /* mpll_200mhz tekkaman*/
add r2, r2, #PSDIV_200 /* mpll_200mhz tekkaman*/
str r2, [r1, #0x04] /* MPLLCON tekkaman */
#endif
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */

红色部分是我添加的,利用vivi的代码,将其设为405.00MHz 并在前面加上:

#elif defined(CONFIG_S3C2410)
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
#define CLK_CTL_BASE 0x4C000000 /* tekkaman */
#if defined(CONFIG_S3C2440)
#define MDIV_405 0x7f << 12 /* tekkaman */
#define PSDIV_405 0x21 /* tekkaman */
#endif
#if defined(CONFIG_S3C2410)
#define MDIV_200 0xa1 << 12 /* tekkaman */
#define PSDIV_200 0x31 /* tekkaman */
#endif
#endif

(3)将从Flash启动改成从NAND Flash启动。(特别注意:这和2410的程序有不同,不可混用!!!是拷贝vivi的代码。)
将以下U-Boot的重定向语句段:
#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 */
替换成:

#ifdef CONFIG_S3C2440_NAND_BOOT @tekkaman@@@@@@@@@@@@@@@@SSSSSSSSSSSSS
@ 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

@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #0x20000
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read

bad_nand_read:
loop2: b loop2 @ 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:
loop3: b loop3 @ infinite loop

#endif @ CONFIG_S3C2440_NAND_BOOT @tekkaman@@@@@@@@@@@@@@@@@@EEEEEEEEE

在“ldr pc, _start_armboot”之前加入:

@ LED1 on u-boot stage 1 is ok!
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_B
ldr r2,=0x155aa
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
mov r2, #0x1c0
str r2, [r1, #oGPIO_DAT]

修改目的:如果看到只有LED1亮了,说明U-Boot的第一阶段已完成!
灯亮这段程序根据个人的板子不通要做相应的修改,不知道怎么修改就不

添加也行。
在 “ _start_armboot: .word start_armboot ” 后加入:
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

2 在board/hongge/hongge2440加入NAND Flash读函数文件,拷贝vivi中的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)
#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 GPDAT __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT)

#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 BUSY 4
inline void wait_idle(void) {
while(!(NFSTAT & BUSY));
NFSTAT |= BUSY;
}

#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 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) || (size & NAND_BLOCK_MASK)) {
return -1; /* invalid alignment */
}

NAND_CHIP_ENABLE;

for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
NAND_CLEAR_RB;
NFCMD = 0;

/* Write Address */
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;

NAND_DETECT_RB;

for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
NAND_CHIP_DISABLE;
return 0;
} 注意:s3c2410与s3c2440的Nand Flash控制器寄存器不同,不能混用!! 3 修改board/hongge/hongge2440/Makefile文件
......
OBJS := hongge2440.o nand_read.o flash.o
...... 4 修改include/configs/hongge.h文件,添加如下内容(注意:s3c2410与s3c2440的Nand Flash控制器寄存器不同,不能混用!!):
......
/*
* Nandflash Boot
*/
#define CONFIG_S3C2440_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
//#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFADDR 0x0c
#define oNFDATA 0x10
#define oNFSTAT 0x20
#define oNFECC 0x2c /* GPIO */
#define GPIO_CTL_BASE 0x56000000
#define oGPIO_B 0x10
#define oGPIO_CON 0x0 /* R/W, Configures the pins of the port */
#define oGPIO_DAT 0x4 /* R/W, Data register for port */
#define oGPIO_UP 0x8 /* R/W, Pull-up disable register */
#endif /* __CONFIG_H */ 5 修改board/tekkaman/hongge2440/lowlevel_init.S文件
依照开发板的内存区的配置情况, 修改board/hongge/hongge2440/lowlevel_init.S文件,我利用vivi源码里的信息做了如下更改:
......
/* REFRESH parameter */
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
#define Trp 0x0
#define Trc 0x3 /* 7clk */
#define Tchr 0x2 /* 3clk */
#define REFCNT 1268 /*period=7.8125us,HCLK=100Mhz (2048+1-7.8125*100)*/
...... 6 修改/board/hongge/hongge2440/hongge2440.c
因为友善之臂SBC2440和smdk2410的GPIO连接有所不同,修改其对GPIO和PLL的配置(请参阅友善之臂SBC2440的硬件说明和2440芯片手册):
...... #elif FCLK_SPEED==1 /* Fout = 405MHz */
//#define M_MDIV 0x5c
//#define M_PDIV 0x4
//#define M_SDIV 0x0
#define M_MDIV 0x7f
#define M_PDIV 0x2
#define M_SDIV 0x1
......
#elif USB_CLOCK==1
//#define U_M_MDIV 0x48
//#define U_M_PDIV 0x3
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2 ...... /* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
//gpio->GPBCON = 0x00044556;
gpio->GPBCON = 0x00055556; ......
/* arch number of S3C2440 -Board */
gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ; /* adress of boot parameters */ gd->bd->bi_boot_params = 0x30000100; icache_enable(); dcache_enable(); gpio->GPBDAT = 0x180; //tekkamanninja //int board_init (void)设置完成后,LED1和LED2会亮起! return 0; } 上面这段是直接搬tekkaman的,本人移植是没有修改这段,写上来是给大家需要的做个参考 7 为了实现NAND Flash的读写,再次修改/include/configs/hongge2440.h
(请格外注意:如果编译时报错,在Linux下用KWrite等有高亮显示的文本编辑器看看文件的注释是不是为注释应有的颜色(KWrite中为灰色),如果不是,则将注释删除。因为#define后面的注释被认为是程序的一部分。建议注释和#define分行写)
......
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */ //#define CONFIG_S3C2410 1 //#define CONFIG_SBC2410X 1
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
#define CONFIG_hongge2440 1 /* on a SAMSUNG hongge2440 Board */
......
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_NAND | \
CFG_CMD_NET | \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
/*CFG_CMD_USB |*/ \
CFG_CMD_PING | \
CFG_CMD_ENV | \
CFG_CMD_REGINFO | \
CFG_CMD_DATE | \
CFG_CMD_DHCP | \
CFG_CMD_ELF)

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#define CFG_LONGHELP
/* undef to save memory */ #define CFG_PROMPT "[HongGe2440]#"
/*Monitor Command Prompt */
#define CFG_CBSIZE 256
/* Console I/O Buffer Size */
......
#define CFG_LOAD_ADDR 0x30008000
/* default load address */

......
/* Timeout for Flash Write */

#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0X20000
//#define ENV_IS_EMBEDDED 1
#define CFG_NAND_LEGACY

#define CFG_ENV_SIZE 0x10000
/* Total Size of Environment Sector */
/*----------------------------------------------------------------------
* NAND flash settings
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000
/* NandFlash控制器在SFR区起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
/* 支持的最在Nand Flash数据 */
#define SECTORSIZE 512
/* 1页的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK 511
/* 页掩码 */
#define ADDR_COLUMN 1
/* 一个字节的Column地址 */ #define ADDR_PAGE 3
/* 3字节的页块地址!!!!!*/
#define ADDR_COLUMN_PAGE 4
/* 总共4字节的页块地址!!!!! */
#define NAND_ChipID_UNKNOWN 0x00
/* 未知芯片的ID号 */
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* Nand Flash命令层底层接口函数 */
#define WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}
#define WRITE_NAND_ADDRESS(d, adr) {rNFADDR = d;}
#define WRITE_NAND(d, adr) {rNFDATA = d;}
#define READ_NAND(adr) (rNFDATA)
#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}
#define NAND_DISABLE_CE(nand) {rNFCONT |= (1<<1);}
#define NAND_ENABLE_CE(nand) {rNFCONT &= ~(1<<1);}

#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)

/* the following functions are NOP's because S3C24X0 handles this in hardware */

#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/* 允许Nand Flash写校验 */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
......
#define rNFCONF (*(volatile unsigned int *)0x4e000000)
#define rNFCONT (*(volatile unsigned int *)0x4e000004)
#define rNFCMD (*(volatile unsigned char *)0x4e000008)
#define rNFADDR (*(volatile unsigned char *)0x4e00000c)
#define rNFDATA (*(volatile unsigned char *)0x4e000010)
#define rNFSTAT (*(volatile unsigned int *)0x4e000020)
#define rNFECC (*(volatile unsigned int *)0x4e00002c)
#endif /* __CONFIG_H */
8、在个文件中添加“CONFIG_S3C2440”,使得原来s3c2410的代码可以编译进来。 (1)/include/common.h文件的第454行: #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440) (2)/include/s3c24x0.h文件的第85、95、99、110、148、404行: #if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) (3)/cpu/arm920t/s3c24x0/interrupts.c文件的第33行: #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440) 第38行:#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) (4)/cpu/arm920t/s3c24x0/serial.c文件的第22行: #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440) 第26行:#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) void serial_setbrg (void) { S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR); int i; unsigned int reg = 0; /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ reg = get_PCLK() / (16 * gd->baudrate) - 1; /* FIFO enable, Tx/Rx FIFO clear */ uart->UFCON = 0x00; uart->UMCON = 0x0; /* Normal,No parity,1 stop,8 bit */ uart->ULCON = 0x3; ...... } (5)/cpu/arm920t/s3c24x0/speed.c文件的第33行: #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440) 第37行:#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) 顺便修改源代码,以匹配s3c2440: static ulong get_PLLCLK(int pllreg)
{
......

m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
//tekkaman
#if defined(CONFIG_S3C2440)
if (pllreg == MPLL)
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
else if (pllreg == UPLL)
#endif
//tekkaman
return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
} ...... /* return FCLK frequency */ ulong get_FCLK(void) { return(get_PLLCLK(MPLL)); } /* return HCLK frequency */ ulong get_HCLK(void) { S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); 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()); } } ...... (6)/cpu/arm920t/s3c24x0/usb_ohci.c文件的第45行: #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) (i2c的文件还没修改,因为没用到) (7)/rtc/s3c24x0_rtc.c文件的第35行: #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) 在个文件中添加“defined(CONFIG_hongge2440)”,使得原来SBC2410X的代码可以编译进来。 (1)/cpu/arm920t/s3c24x0/interrupts.c文件的第181行: defined(CONFIG_VCMA9) || defined(CONFIG_hongge2440)

9、在 include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入 static struct nand_flash_dev nand_flash_ids[] = { ......
{"Samsung KM29N16000",NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000, 0},
{"Samsung K9F1208U0B", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0},
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000, 0},
...... };

10、修改/lib_arm中的board.c。 ...... #include <common.h>
#include <command.h>
#include <malloc.h>
#include <devices.h>
#include <version.h>
#include <net.h>
#include <s3c2410.h> ...... static int display_banner (void)
{ S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); gpio->GPBDAT = 0x100; //tekkamanninja //在串口初始化和console初始化完成,串口输出信息之前,LED1、LED2、LED3会亮起! printf ("\n\n%s\n\n", version_string);
debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
_armboot_start, _bss_start, _bss_end);
printf ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", //tekkaman
_armboot_start, _bss_start, _bss_end); //tekkaman
#ifdef CONFIG_MODEM_SUPPORT
debug ("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif

return (0);
} ...... void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; #ifndef CFG_NO_FLASH ulong size; #endif #if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long addr; #endif S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); ...... gpio->GPBDAT = 0x0; //tekkamanninja //在进入命令提示符之前,四个LED会同时亮起! /* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) { main_loop (); } /* NOTREACHED - no way out of command loop except booting */ } 上面这段是本人移植的时候只加了个头文件也没有修改,搬过来是给需要的朋友做参考。

11、 修改common/env_nand.c

......
#ifdef CONFIG_INFERNO
#error CONFIG_INFERNO not supported yet
#endif

int nand_legacy_rw (struct nand_chip* nand, int cmd,
size_t start, size_t len,
size_t * retlen, u_char * buf);
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, size_t len, int clean);

/* info for NAND chips, defined in drivers/nand/nand.c */
extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE];

......

#else /* ! CFG_ENV_OFFSET_REDUND */
int saveenv(void)
{
ulong total;
int ret = 0;

puts ("Erasing Nand...");
//if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE))

if (nand_legacy_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0))
return 1;

puts ("Writing to Nand... ");
total = CFG_ENV_SIZE;
//ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);

ret = nand_legacy_rw(nand_dev_desc + 0, 0x00 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE, &total, (u_char*)env_ptr);

if (ret || total != CFG_ENV_SIZE)
return 1;

puts ("done\n");
return ret;
......
#else /* ! CFG_ENV_OFFSET_REDUND */
/*
* The legacy NAND code saved the environment in the first NAND device i.e.,
* nand_dev_desc + 0. This is also the behaviour using the new NAND code.
*/
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
ulong total;
int ret;

total = CFG_ENV_SIZE;
//ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
ret = nand_legacy_rw(nand_dev_desc + 0, 0x01 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE, &total, (u_char*)env_ptr);

......

12、 在/board/tekkaman/hongge2440/hongge2440.c文件的末尾添加对Nand Flash 的初始化函数(在后面Nand Flash的操作都要用到)
u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nand/nand.c中的nand_init();否则调用自己在board/hongge/hongge2440/hongge2440.c中的nand_init()函数。这里我选择第二种方式。 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE; static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONF = conf;
} static inline void NF_Cont(u16 cont)
{ S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONT = cont; } static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCMD = cmd;
} static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
} static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFADDR = addr;
} static inline void NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); switch (s) {
case NFCE_LOW:
nand->NFCONT &= ~(1<<1);
break; case NFCE_HIGH:
nand->NFCONT |= (1<<1);
break;
}
} static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); while (!(nand->NFSTAT & (1<<0)));
} static inline void NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFDATA = data;
} static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); return(nand->NFDATA);
} static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONT |= (1<<4);
} static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); return(nand->NFECC);
} #endif
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i; NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif NF_Conf((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)); NF_Cont((1<<6)|(1<<4)|(1<<1)|(1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */ NF_Reset();
} void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
#endif
printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
}
#endif 12 在/include/s3c24x0.h中加入2440 的NAND FLASH 寄存器定义和CAMDIVN定义: ...... typedef struct { S3C24X0_REG32 LOCKTIME; S3C24X0_REG32 MPLLCON; S3C24X0_REG32 UPLLCON; S3C24X0_REG32 CLKCON; S3C24X0_REG32 CLKSLOW; S3C24X0_REG32 CLKDIVN; S3C24X0_REG32 CAMDIVN; } /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER; ...... #if defined(CONFIG_S3C2410) /* NAND FLASH (see S3C2410 manual chapter 6) */ typedef struct { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFECC; } /*__attribute__((__packed__))*/ S3C2410_NAND; #endif #if defined (CONFIG_S3C2440) /* NAND FLASH (see S3C2440 manual chapter 6) */ typedef struct { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCONT; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFMECC0; S3C24X0_REG32 NFMECC1; S3C24X0_REG32 NFSECC; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFESTAT0; S3C24X0_REG32 NFESTAT1; S3C24X0_REG32 NFECC; } /*__attribute__((__packed__))*/ S3C2410_NAND; #endif

三、交叉编译U-Boot。
在U-Boot的根目录下
$make
一阵English飘过~~~~~~~~~~~~~~~~~~~~~~~ 本人按照上面的做了一遍,可以成功!! 四 网卡移植。 本人的板子使用的是DM9000A,下面的修改是这款芯片。如果使用DM9000请参考

DM9000网卡移植请看:http://blog.chinaunix.net/u1/34474/showart.php?id=401078 按照这边文章的内容接着继续下去即可。

由于UBOOT自带的dm9000x网卡驱动对dm9000a的支持有点小问题,所以本人把修改好的dm9000x驱动程序附上。(见附件)替换原来的驱动后,

在/include/configs/hongge2440.h文件中修改添加对DM9000A的支持,屏蔽CS8900:

/*
* Hardware drivers
*/
//#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 */

#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x20000300
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+16)
#define CONFIG_DM9000_USE_16BIT

在这里
#define CONFIG_DM9000_BASE
的定义最为重要。不同的板子只要修改这个参数即可。DM9000在BANK4上所以定义为“
0x20000300
”。DM9000A在BANK4上所以定义为“0x20000000”。有的板子是在BANK1上,就为“
0x08000000
”。就是说DM9000A不用添加300的偏移,具体看网卡芯片的手册。DM9000_DATA 的地址如果CMD使用A2就是CONFIG_DM9000_BASE+4,我的板子是A4所以CONFIG_DM9000_BASE+16,一般的开发板都是A2,具体请看板子的电路图。

这样定义完之后,就可以“make”,然后下载到板上运行。ping和tftp都可以实现。但是有些问题:

(1)网卡的MAC地址与你设置的不一样
(2)会有“could not establish link” 的提示,而且在显示MAC地址后很久后才响应。

这两个问题我认为是U-Boot的DM9000源码的BUG。追踪源码可以知道:这些都是发生在int eth_init(bd_t * bd)初始化时的错误。

修正BUG(修改/drivers/dm9000x.c文件)

(1)
网卡MAC地址错误的解决方法:

/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
......

/* Set Node address */
/* for (i = 0; i < 6; i++)
((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
*/
//tekkamanninja
char *tmp = getenv ("ethaddr");
char *end;

for (i=0; i<6; i++) {
bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
if (tmp)
tmp = (*end) ? end+1 : end;
}
//tekkamanninja
printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
bd->bi_enetaddr[4], bd->bi_enetaddr[5]);

......

红色的字符是要做的修改:功能是屏蔽原有获取MAC地址的语句,替换成从U-Boot的参数区读取数据并存到
bd->bi_enetaddr[i]中。

(2)“could not establish link” 提示和慢响应的解决方法:

/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
......

DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */
DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */

#if 0
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 10000) {
printf("could not establish link\n");
return 0;
}
printf(" link=%d\n",i);
}
#endif

#if 0
/* see what we've got */
lnk = phy_read(17) >> 12;
printf("operating at ");
switch (lnk) {
case 1:
printf("10M half duplex ");
break;
case 2:
printf("10M full duplex ");
break;
case 4:
printf("100M half duplex ");
break;
case 8:
printf("100M full duplex ");
break;
default:
printf("unknown: %d ", lnk);
break;
}
printf("mode\n");
#endif

printf("operating at 100M full duplex mode\n");
return 0;
}


文件:dm9000x.rar
大小:5KB
下载:下载
红色的字符是要做的修改:功能是屏蔽无用的语句。
其实被屏蔽的语句是MII接口用的,放在这显然是错误的,无端的浪费了10秒钟。

至此,U-Boot的2440移植结束了,两张网卡要用哪张随你便。只要重新编译一下就好了。GOOD LUCK!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: