您的位置:首页 > 运维架构 > Linux

Linux-world-2012-January->14(移植uboot-1.3.4到mini2440-256M NAND)

2012-01-18 13:33 525 查看
一,配置环境

开发板:mini2440(256M nandflash)
bootloader:uboot1.3.4
交叉编译器:arm-linux-gcc4.3.2

二,移植过程

第1步:准备工作

1、U-boot源码下载地址:ftp://ftp.denx.de/pub/u-boot/或者http://download.csdn.net/detail/doublewei1/4026913
里边的u-boot-1.3.4.tar.bz2文件,放到你的开发目录里;
2、解压文件:tar -jxvf u-boot-1.3.4.tar.bz2;
3、下载交叉编译工具
使用友善之臂 http://www.arm9.net/download-arm-linux-gcc-4.3.2.asp 的arm-linux-gcc-4.3.2.tgz
4、建立交叉编译环境
解压4.3.2到合适的位置,设置环境变量。

第2步:初步编译uboot

1、在u-boot-1.3.4/board下找个与2410相似的开发板,这里smdk2410为例。
2、将u-boot-1.3.4/board/smdk2410目录复制到当前目录下,并改名为 mini2440。
3、把smdk2410.c改名为mini2440.c,修改Makefile中的 COBJS := mini2440.o flash.o,保存。
4、将u-boot-1.3.4/include/configs/smdk2410.h,复制到当前目录,并改名为mini2440.h。
5、在u-boot-1.3.4/Makefile中,大概2490多行找到
smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
在它下边添加
mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
(注意@$(MKCONFIG)前面必须是TAB键)
6、特别注意:在u-boot1.3.3及以上版本Makefile有一定的变化,使得对于24x0 处理器从nand启动的遇到问题。也就是网上有人说的:无法运行过lowlevel_init。其 实这个问题是由于编译器将我们自己添加的用于nandboot的子函数nand_read_ll放 到了4K之后造成的(到这不理解的话,请仔细看看24x0处理器nandboot原理)。
u-boot根本没有完成自我拷贝,你可以看uboot根目录下的System.map文件就可知 道原因。

解决办法其实很简单:
将278行的__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
改为__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst $(obj),,$(LIBS))
7、进入u-boot-1.3.4目录,先来个#make distclean,
然后# make mini2440_config
Configuring for mini2440 board...
8、之后就可以# make了,如正常编译通过,表明环境搭建好。
第3步:支持nandboot及2440相关修改(蓝色为修改部分)

1、修改/cpu/arm920t/start.S

1) 关闭AT91RM9200使用的LED代码。
#include <config.h>
#include <version.h>
#if defined(CONFIG_AT91RM9200DK)
#include
<status_led.h> /*这是针对AT91RM9200DK开发板的。*/

#endif
......
/*
* the actual start code
*/
start_code:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
#if defined(CONFIG_AT91RM9200DK)
bl coloured_LED_init
bl red_LED_on
#endif

2) 修改寄存器地址定义
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)||
defined(CONFIG_S3C2440)

/* turn off the watchdog */
#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 MDIV_200 0xa1 << 12
#define PSDIV_200 0x31

3) 修改中断禁止部分

#if defined(CONFIG_S3C2410)
ldr r1, =0x3ff /*根据2410芯片手册,INTSUBMSK有11位可用*/
ldr r0, =INTSUBMSK
str r1, [r0]
#endif
#if defined(CONFIG_S3C2440)
ldr r1, =0x7fff /*根据2440芯片手册,INTSUBMSK有15位可用*/
ldr r0, =INTSUBMSK
str r1, [r0]
#endif

4) 修改时钟设置(2440的主频为405MHz。)

# 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, #MDIV_405 /* mpll_405mhz */
add r2, r2, #PSDIV_405 /* mpll_405mhz */
str r2, [r1, #0x04] /* MPLLCON */
#else
/* FCLK:HCLK:PCLK = 1:2:4 */
ldr r0, =CLKDIVN
mov r1, #3
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 202.8 Mhz */
mov r1, #CLK_CTL_BASE /* */
mov r2, #MDIV_200 /* mpll_200mhz */
add r2, r2, #PSDIV_200 /* mpll_200mhz */
str r2, [r1, #0x04]
# endif
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */

5) 将从Nor Flash启动改成从NAND Flash启动。

在以下U-Boot的重定向语句段(作用是将u-boot的源代码从nor flash到sdram中):(我将红色部分删除了)

#ifndef CONFIG_AT91RM9200
#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 {r3-r10} /* copy from source address [r0] */
stmia {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
/************ NAND_BOOT************************************/
#ifdef CONFIG_S3C2440_NAND_BOOT
#define NAND_CTL_BASE 0x4E000000
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFSTAT 0x20
#define LENGTH_UBOOT 0x60000

@ 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, #LENGTH_UBOOT
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
#ifdef CONFIG_S3C2410_NAND_BOOT
#define NAND_CTL_BASE 0x4E000000
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFSTAT 0x10
#define LENGTH_UBOOT 0x40000
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #oNFCONF]
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, #0x1
beq nand2

ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]

@ 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, #LENGTH_UBOOT
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
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

在 “ _start_armboot: .word start_armboot ” 后加入:

#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

6),最后增加LED点亮的操作

作用是显示代码进度,对Debug有帮助。代码在跳转到第二阶段代码start_armboot函
数前会亮起一个LED灯。(还记得前面有调用C语言的nand_read_ll函数吧,初始化堆栈
的定义就在此)

clbss_l:str r2, [r0] /* clear loop... */

add r0, r0, #4
cmp r0, r1
ble clbss_l
ldr pc, _start_armboot

#if defined(CONFIG_MINI2440_LED)
#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
#define oGPIO_UP 0x8
/* R/W, Pull-up disable register */
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_B
ldr r2, =0x295551
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
ldr r2, =0x1c1
str r2, [r1, #oGPIO_DAT]
#endif
_start_armboot: .word start_armboot
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START:.word STACK_BASE+STACK_SIZE-4

2、在board/mini2440加入NAND Flash读取函数(start.S中需要的nand_read_ll函数)文件nand_read.c

==================================================================

/*
* nand_read.c: Simple NAND read functions for booting from NAND
*
* This is used by cpu/arm920/start.S assembler code,
* and the board-specific linker script must make sure this
* file is linked within the first 4kB of NAND flash.
*
* Taken from GPLv2 licensed vivi bootloader,
* Copyright (C) 2002 MIZI Research, Inc.
*
* Author: Hwang, Chideok <hwang@mizi.com>
* Date : $Date: 2004/02/04 10:37:37 $
*
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
* Author: Harald Welte <laforge@openmoko.org>
*/
#include <common.h>
#include <linux/mtd/nand.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGw(x) (*(volatile unsigned short *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#if defined(CONFIG_S3C2410)
#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 NFSTAT_BUSY 1
#define nand_select() (NFCONF &= ~0x800)
#define nand_deselect() (NFCONF |= 0x800)
#define nand_clear_RnB() do {} while (0)
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
#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 NFDATA16 __REGw(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT_BUSY 1
#define nand_select() (NFCONT &= ~(1 << 1))
#define nand_deselect() (NFCONT |= (1 << 1))
#define nand_clear_RnB() (NFSTAT |= (1 << 2))
#endif
static inline void nand_wait(void)
{
int i;
while (!(NFSTAT & NFSTAT_BUSY))
for (i=0; i<10; i++);
}
struct boot_nand_t {
int page_size;
int block_size;
int bad_block_offset;
// unsigned long size;
};

#if 0
#if defined(CONFIG_S3C2410) || defined(CONFIG_MINI2440)
/* configuration for 2410 with 512byte sized flash */
#define NAND_PAGE_SIZE 512
#define BAD_BLOCK_OFFSET 5
#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)

#define NAND_BLOCK_SIZE 0x4000
#else
/* configuration for 2440 with 2048byte sized flash */
#define NAND_5_ADDR_CYCLE
#define NAND_PAGE_SIZE 2048
#define BAD_BLOCK_OFFSET NAND_PAGE_SIZE
#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)
#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * 64)
#endif
/* compile time failure in case of an invalid configuration */
#if defined(CONFIG_S3C2410) && (NAND_PAGE_SIZE != 512)
#error "S3C2410 does not support nand page size != 512"
#endif
#endif
static int is_bad_block(struct boot_nand_t * nand, unsigned long i)
{
unsigned char data;
unsigned long page_num;
nand_clear_RnB();
if (nand->page_size == 512) {
NFCMD = NAND_CMD_READOOB; /* 0x50 */
NFADDR = nand->bad_block_offset & 0xf;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
} else if (nand->page_size == 2048) {
page_num = i >> 11; /* addr / 2048 */
NFCMD = NAND_CMD_READ0;
NFADDR = nand->bad_block_offset & 0xff;
NFADDR = (nand->bad_block_offset >> 8) & 0xff;
NFADDR = page_num & 0xff;
NFADDR = (page_num >> 8) & 0xff;
NFADDR = (page_num >> 16) & 0xff;
NFCMD = NAND_CMD_READSTART;
} else {
return -1;
}
nand_wait();

data = (NFDATA & 0xff);
if (data != 0xff)
return 1;
return 0;
}
static int nand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, unsigned long addr)
{
unsigned short *ptr16 = (unsigned short *)buf;
unsigned int i, page_num;
nand_clear_RnB();
NFCMD = NAND_CMD_READ0;
if (nand->page_size == 512) {
/* Write Address */
NFADDR = addr & 0xff;
NFADDR = (addr >> 9) & 0xff;
NFADDR = (addr >> 17) & 0xff;
NFADDR = (addr >> 25) & 0xff;
} else if (nand->page_size == 2048) {
page_num = addr >> 11; /* addr / 2048 */
/* Write Address */
NFADDR = 0;
NFADDR = 0;
NFADDR = page_num & 0xff;
NFADDR = (page_num >> 8) & 0xff;
NFADDR = (page_num >> 16) & 0xff;
NFCMD = NAND_CMD_READSTART;
} else {
return -1;
}
nand_wait();
#if defined(CONFIG_S3C2410)
for (i = 0; i < nand->page_size; i++) {
*buf = (NFDATA & 0xff);
buf++;
}
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
for (i = 0; i < (nand->page_size>>1); i++) {
*ptr16 = NFDATA16;
ptr16++;
}
#endif
return nand->page_size;
}
static unsigned short nand_read_id()
{
unsigned short res = 0;
NFCMD = NAND_CMD_READID;
NFADDR = 0;
res = NFDATA;
res = (res << 8) | NFDATA;
return res;
}
extern unsigned int dynpart_size[];
/* low level nand read function */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
unsigned short nand_id;
struct boot_nand_t nand;
/* chip Enable */
nand_select();
nand_clear_RnB();
for (i = 0; i < 10; i++)
;
nand_id = nand_read_id();
if (0) { /* dirty little hack to detect if nand id is misread */
unsigned short * nid = (unsigned short *)0x31fffff0;
*nid = nand_id;
}
if (nand_id == 0xec76 || /* Samsung K91208 */
nand_id == 0xad76 ) { /*Hynix HY27US08121A*/
nand.page_size = 512;
nand.block_size = 16 * 1024;
nand.bad_block_offset = 5;
// nand.size = 0x4000000;
} else if (nand_id == 0xecf1 || /* Samsung K9F1G08U0B */
nand_id == 0xecda || /* Samsung K9F2G08U0B */
nand_id == 0xecd3 ) { /* Samsung K9K8G08 */
nand.page_size = 2048;
nand.block_size = 128 * 1024;
nand.bad_block_offset = nand.page_size;
// nand.size = 0x8000000;
} else {
return -1; // hang
}
if ((start_addr & (nand.block_size-1)) || (size & ((nand.block_size-1))))
return -1; /* invalid alignment */
for (i=start_addr; i < (start_addr + size);) {
#ifdef CONFIG_S3C2410_NAND_SKIP_BAD
if (i & (nand.block_size-1)== 0) {
if (is_bad_block(&nand, i) ||
is_bad_block(&nand, i + nand.page_size)) {
/* Bad block */
i += nand.block_size;
size += nand.block_size;
continue;
}
}
#endif
j = nand_read_page_ll(&nand, buf, i);
i += j;
buf += j;
}
/* chip Disable */
nand_deselect();
return 0;
}

==============================================================

记得修改board/mini2440/Makefile文件,将nand_read.c编译进u-boot。

OBJS := mini2440.o nand_read.o
flash.o


3、修改board/mini2440/lowlevel_init.S文件

/* REFRESH parameter */
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
#define Trc 0x3 /* 7clk */
#define Tchr 0x2 /* 3clk */
#if defined(CONFIG_S3C2440)
#define Trp 0x2 /* 4clk */
#define REFCNT 1012
#else
#define Trp 0x0 /* 2clk */
#define REFCNT 0x0459
#endif

4、修改/board/mini2440/mini2440.c

修改其对GPIO和PLL的配置(请参阅开发板的硬件说明和芯片手册);并针对LCD显示部分和nand flash驱动添加相应的代码: ......
#include <common.h>
#include <s3c2410.h>
#include <video_fb.h>
#if defined(CONFIG_CMD_NAND)
#include <linux/mtd/nand.h>
#endif
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 */
#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
#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_SDIV 0x2
#endif
......
为连接LED和蜂鸣器的GPIO修改配置寄存器:

int board_init (void):
./* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
#if defined(CONFIG_MINI2440)
gpio->GPBCON = 0x00295551;
#else
gpio->GPBCON = 0x00044555;
#endif
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPCUP = 0xFFFFFFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPDUP = 0xFFFFFFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
为引导linux 内核,修改开发板的类型代码:

int board_init (void):
......
#if defined(CONFIG_S3C2410)
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
#endif
#if defined(CONFIG_S3C2440)
/* arch number of S3C2440-Board */
gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;
#endif

......为使int board_init (void)设置完成后,LED1和LED2同时亮起,蜂鸣器继续鸣叫,在int board_init (void)的最后添加: ......
icache_enable();
dcache_enable();
#if defined(CONFIG_MINI2440_LED)
gpio->GPBDAT = 0x00000181;
#endif
return 0;
}

5、最后,修改board/mini2440/u-boot.lds文件,在

cpu/arm920t/start.o (.text)
后加上
board/mini2440/lowlevel_init.o
(.text)

board/mini2440/nand_read.o (.text)

6,当我将生成的uboot.bin烧到nandflash时,启动开发板,串口不能输出启动信息,通过网上查找资料发现没有定义uboot的uboot_ram_base

在include/configs/mini2440.h的最后添加如下代码:
/*
* Nandflash Boot
*/
#define CONFIG_S3C2440_NAND_BOOT
1

#define UBOOT_RAM_BASE 0x33f80000

第4阶段修改适合S3C2440的程序

1、修改include/configs/mini2440.h将

#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */

改为:

#define CONFIG_S3C2440 1

2、将/include/common.h中的

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X)

改为:

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440)



3、修改/include/s3c24x0.h,将文件中所有的

#ifdef CONFIG_S3C2410

改为:

#if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

还有nand的处理:
/* NAND FLASH (see S3C2410 manual chapter 6) */

typedef struct {

S3C24X0_REG32 NFCONF;

#if defined(CONFIG_S3C2440) //modified for 2440

S3C24X0_REG32 NFCONT;

#endif

S3C24X0_REG32 NFCMD;

S3C24X0_REG32 NFADDR;

S3C24X0_REG32 NFDATA;

S3C24X0_REG32 NFSTAT;

S3C24X0_REG32 NFECC;

} /*__attribute__((__packed__))*/ S3C2410_NAND;


4、将/cpu/arm920t/s3c24x0/interrupts.c中的

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)

修改为:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)



#elif defined(CONFIG_S3C2410)

改为:

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

5、将/cpu/arm920t/s3c24x0/serial.c文件中的

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)

改为:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)



#elif defined(CONFIG_S3C2410)

改为:

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

将函数static int serial_init_dev(const int dev_index)中的

uart->UFCON = 0x07;

改为:

uart->UFCON = 0x00;

6、将/cpu/arm920t/s3c24x0/speed.c中的

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)

改为:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)



#elif defined(CONFIG_S3C2410)

改为:

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

在static ulong get_PLLCLK(int pllreg)中的

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 HCLK frequency */

ulong get_HCLK(void)

{

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

}

改为:


/* 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());

}

7、/cpu/arm920t/s3c24x0/usb_ohci.c中的

#elif defined(CONFIG_S3C2410)

改为:

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)



8、将drivers/rtc/s3c24x0_rtc.c中的

#elif defined(CONFIG_S3C2410)

改为:

#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

9、需要在/include/s3c24x0.h文件中添加CAMDIVN定义,将

/* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */

/* (see S3C2410 manual chapter 7) */

typedef struct {

S3C24X0_REG32 LOCKTIME;

S3C24X0_REG32 MPLLCON;

S3C24X0_REG32 UPLLCON;

S3C24X0_REG32 CLKCON;

S3C24X0_REG32 CLKSLOW;

S3C24X0_REG32 CLKDIVN;

} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;

改为:

/* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */

/* (see S3C2410 manual chapter 7) */

typedef struct {

S3C24X0_REG32 LOCKTIME;

S3C24X0_REG32 MPLLCON;

S3C24X0_REG32 UPLLCON;

S3C24X0_REG32 CLKCON;

S3C24X0_REG32 CLKSLOW;

S3C24X0_REG32 CLKDIVN;

#if defined (CONFIG_S3C2440)

S3C24X0_REG32 CAMDIVN;

#endif

} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;


10,修改lib_arm/board.c文件
#include <nand.h>
#include <onenand_uboot.h>
#include <mmc.h>
#include <s3c2410.h>

#if 0
/************************************************************************
* Coloured LED functionality
************************************************************************
* May be supplied by boards if desired
*/
void inline __coloured_LED_init (void) {}
void inline coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init")));
void inline __red_LED_on (void) {}
void inline red_LED_on (void) __attribute__((weak, alias("__red_LED_on")));
void inline __red_LED_off(void) {}
void inline red_LED_off(void) __attribute__((weak, alias("__red_LED_off")));
void inline __green_LED_on(void) {}
void inline green_LED_on(void) __attribute__((weak, alias("__green_LED_on")));
void inline __green_LED_off(void) {}
void inline green_LED_off(void)__attribute__((weak, alias("__green_LED_off")));
void inline __yellow_LED_on(void) {}
void inline yellow_LED_on(void)__attribute__((weak, alias("__yellow_LED_on")));
void inline __yellow_LED_off(void) {}
void inline yellow_LED_off(void)__attribute__((weak, alias("__yellow_LED_off")));
#endif
static int display_banner (void)
{
printf ("\n\n%s\n\n", version_string);
// #if defined(CONFIG_MINI2440_LED)
// struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
// gpio->GPBDAT = 0x101;
// #endif
printf (" modified by Cyclone!\n");
printf (" Love Linux forever!!\n\n");

debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
_armboot_start, _bss_start, _bss_end);
#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);
}

到这里,make一下,把u-boot.bin烧到nand
flash,重新启动,在串口工具上应该可以看到熟悉的

U-Boot 1.3.4 (Oct 9 2009 - 07:34:33)


DRAM: 64 MB
FLASH:

一样操作,成功编译后,minicom出来的是乱码。。。,不过我有个万能nand启动u-boot,成功移植,显示正常,源代码也有,会继续探究的

第5步
修改nand和支持网口芯片DM9000的驱动


1、对cpu\arm920t\s3c24x0里的nand.c进行如下修改:
#include <common.h>
#if 0

#define DEBUGN printf

#else

#define DEBUGN(x, args ...) {}

#endif

#if defined(CONFIG_CMD_NAND)

#if !defined(CFG_NAND_LEGACY)

#include <nand.h>

#include <s3c2410.h>

#define __REGb(x) (*(volatile unsigned char *)(x))

#define __REGi(x) (*(volatile unsigned int *)(x))

#define NF_BASE 0x4e000000

#if defined(CONFIG_S3C2410)

#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)

#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)

#elif defined(CONFIG_S3C2440)
#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


static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd)

{

struct nand_chip *chip = mtd->priv;

DEBUGN("hwcontrol(): 0x%02x: ", cmd);

#if defined(CONFIG_S3C2410)

switch (cmd) {

case NAND_CTL_SETNCE:

NFCONF &= ~S3C2410_NFCONF_nFCE;

DEBUGN("NFCONF=0x%08x\n", NFCONF);

break;

case NAND_CTL_CLRNCE:

NFCONF |= S3C2410_NFCONF_nFCE;

DEBUGN("NFCONF=0x%08x\n", NFCONF);

break;

case NAND_CTL_SETALE:

chip->IO_ADDR_W = NF_BASE + 0x8;

DEBUGN("SETALE\n");

break;

case NAND_CTL_SETCLE:

chip->IO_ADDR_W = NF_BASE + 0x4;

DEBUGN("SETCLE\n");

break;

default:

chip->IO_ADDR_W = NF_BASE + 0xc;

break;

}


#elif defined(CONFIG_S3C2440)

switch (cmd) {

case NAND_CTL_SETNCE:

NFCONF &= ~S3C2440_NFCONT_nCE;

DEBUGN("NFCONF=0x%08x\n", NFCONF);

break;

case NAND_CTL_CLRNCE:

NFCONF |= S3C2440_NFCONT_nCE;

DEBUGN("NFCONF=0x%08x\n", NFCONF);

break;

case NAND_CTL_SETALE:

chip->IO_ADDR_W = NF_BASE + S3C2440_ADDR_NALE;

DEBUGN("SETALE\n");

break;

case NAND_CTL_SETCLE:

chip->IO_ADDR_W = NF_BASE + S3C2440_ADDR_NCLE;

DEBUGN("SETCLE\n");

break;

default:

chip->IO_ADDR_W = NF_BASE + 0x10; //
注意是0x10

break;

}

#endif


return;

}


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)

/* 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 = 0x4e00000c;

/* read_buf and write_buf are default */

/* read_byte and write_byte are default */

/* hwcontrol always must be implemented */

nand->hwcontrol = s3c2410_hwcontrol;

nand->dev_ready = s3c2410_dev_ready;
#ifdef CONFIG_S3C2410_NAND_HWECC

nand->enable_hwecc = s3c2410_nand_enable_hwecc;

nand->calculate_ecc = s3c2410_nand_calculate_ecc;

nand->correct_data = s3c2410_nand_correct_data;

nand->eccmode = NAND_ECC_HW3_512;

#else

//nand->eccmode = NAND_ECC_SOFT;

nand->eccmode = NAND_ECC_NONE; /*这个ECC先去掉,否则你使用nand
write命令和nand read会boot不起内核
*/

#endif

#ifdef
CONFIG_S3C2410_NAND_BBT

nand->options = NAND_USE_FLASH_BBT;

#else

nand->options = 0;

#endif


#elif defined(CONFIG_S3C2440)

twrph0 = 6; twrph1 = 2; tacls = 0;

cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);

NFCONF = cfg;

cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);

NFCONT = cfg;

/* initialize nand_chip data structure */

nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;

/* read_buf and write_buf are default */

/* read_byte and write_byte are default */

/* hwcontrol always must be implemented */

nand->hwcontrol = s3c2410_hwcontrol;

nand->dev_ready = s3c2410_dev_ready;

#ifdef CONFIG_S3C2440_NAND_HWECC

nand->enable_hwecc = s3c2410_nand_enable_hwecc;

nand->calculate_ecc = s3c2410_nand_calculate_ecc;

nand->correct_data = s3c2410_nand_correct_data;

nand->eccmode = NAND_ECC_HW3_512;

#else


//nand->eccmode = NAND_ECC_SOFT;
nand->eccmode = NAND_ECC_NONE; /*这个ECC先去掉,否则你使用nand
write命令和nand read会boot不起内核
*/

#endif

#ifdef CONFIG_S3C2440_NAND_BBT

nand->options = NAND_USE_FLASH_BBT;

#else

nand->options = 0;

#endif

#endif

DEBUGN("end of nand_init\n");
return 0;

}

#else

#error "U-Boot legacy NAND support not available for S3C2410"

#endif

#endif


2、对include\configs\mini2440.h进行如下修改:

增加

#define CONFIG_CMD_NAND /* NAND support*/
#define CFG_ENV_IS_IN_NAND 1 /* */

#define CFG_ENV_OFFSET 0X40000

/* u-boot:0x00000--0x40000,param:0x40000--0x60000,kernel:0x60000--0x260000 128K block*/

#define CFG_ENV_SIZE 0x10000/* Total Size of Environment Sector */


//#define CONFIG_SETUP_MEMORY_TAGS 1

//#define CONFIG_CMDLINE_TAG 1

/*nand flash define*/

#if defined(CONFIG_CMD_NAND)

#define CFG_MAX_NAND_DEVICE 1 //just one nand flash chip on board

#define CFG_NAND_BASE 0x4e000000 //nand flash base address

#define SECTORSIZE 2048

/* one page size*/

#define NAND_SECTOR_SIZE SECTORSIZE

#define NAND_BLOCK_MASK (SECTORSIZE - 1)

#endif


3、增加对网口芯片的支持:

同在include/configs/mini2440.h里,修改Hardware
drivers的定义:

/*

* 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+4)

#define CONFIG_DM9000_USE_16BIT


并确保#define CONFIG_CMD_NET /*
bootp, tftpboot, rarpboot*/打开,设置相关TFTP操作的定义,如下:


#define CONFIG_BOOTDELAY 3

#define CONFIG_ETHADDR 08:00:3e:26:0a:5b

#define CONFIG_NETMASK 255.255.255.0

#define CONFIG_IPADDR 192.168.1.250

#define CONFIG_SERVERIP 192.168.1.100

#define CONFIG_BOOTFILE "zImage.img"

#define CONFIG_BOOTCOMMAND "tftp 0x30008000 0x60000 0x21733c\; bootm 30008000"

//我把内核放在nandflash偏移为60000的位置



2、修改lib_arm/board.c
添加:
#ifdef CONFIG_DRIVER_DM9000

extern int eth_init(bd_t * bd);

#endif

#ifdef CONFIG_DRIVER_DM9000

eth_init(gd->bd);

#endif



在移植完u-boot支持nand之后,我开始了引导内核,我的内核版本是2.6.37.2,

1,制作uboot支持的内核镜像,用u-boot/tools/mkimage这个工具为你的内核加上u-boot引导所需要的文件头,具体做法如下:

./mkimage -n 'linux-2.6.37' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage zImage.img

2,通过mini2440的norflash中的suppervivi,选择a,烧写u-boot,到nandflash。

3,使用suppervivi,将zImage.img烧写到nandflash的0x60000偏移处,大小为0x21733c,烧写到nand的位置可以通过vivi下的part show命令查看。

4,烧写制作好的yaffs2文件系统。

5,进入u-boot,运行nand read 0x30008000 0x60000 0x21733c,这样就把nand中偏移为0x60000,大写为0x21733c的内容读取到内存0x30008000的地址中去。

6,运行bootm 0x30008000命令,就会解压引导内核了。

当然还可以使用tftp的方式烧写引导内核,详细的内容在转载的文章:U-BOOT下使用bootm引导内核方法。

7,过程中遇到的错误总结:

当烧写完内核引导时出现arch_number内核与u-boot不匹配,用bdinfo命令查看u-boot端的ID :

[u-boot@MINI2440]# bdinfo

arch_number = 0x0000016A

基本上可以确定从U-boot得到的ID为 362 (0x0000016a), 内核中的 Machine ID 为:


linux-2.6.37.2/arch/arm/tools/mach-types

#define MACH_TYPE_MINI2440 1999

在U-boot中添加:

u-boot-1.3.4/include/asm-arm/mach-types.h


#define MACH_TYPE_MINI2440 1999



再查找一下ID为362的Machine是 MACH_TYPE_S3C2440,看来是u-boot没有传递正确的ID。grep一下MACH_TYPE_S3C2440,在如下位置找到原因:

u-boot-1.3.4/board/mini2440/mini2440.c

#if defined(CONFIG_S3C2440)

/* arch number of S3C2440-Board */

gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;

#endif



把这里的MACH_TYPE_S3C2440改为MACH_TYPE_MINI2440就OK了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: