"); //-->
作者: 武汉华嵌高级讲师 周老师
一、移植环境
256MSDROM : (0x5000 0000- 0x5f00 0000, 0x6000 0000 – 0x6f00 0000)
2GMLC nandflash: 型号K9GAG08U0D , page size: 4K, block size: 512K
以太网卡:DM9000, 片选Xm0CSn[1] (基址0x1800 0000)
该版本的u-boot仍然不支持S3C6410处理器,且不支持nand flash启动,故我们移植的目的是该版本u-boot支持S3C6410的nand flash启动。我们可以以smdk6400为原型,在此基础上,进行我们的移植工作。
二、建立开发板目录并测试编译环境
1、新建一个开发板目录和相应文件
cd board/samsung
cp –rf smdk6400 smdk6410
cd smdk6410
mv smdk6400.c smdk6410.c
modify Makefile = COBJS-y := smdk6410.o
2、在目录include/configs下创建smdk6410.h
cd include/configs
cp smdk6400.h smdk6410.h
3、修改顶层Makefile, 增加下面两行(after Line 2244)
smdk6410_config : unconfig
echo "RAM_TEXT = 0x57e00000" $(obj)board/samsung/smdk6410/config.tmp;
@$(MKCONFIG) smdk6410 arm arm1176 smdk6410 samsung s3c64xx
说明:arm :CPU的架构(ARCH)
arm1176:CPU的类型
smdk6410 :对应在board目录下建立新的开发板项目的目录
samsung:新开发板项目目录的上级目录,如直接在board下建立新的开发板项目的目录,则这里就为NULL
s3c64xx:SOC型号系列
注意:编译选项格式的第二行要用Tab键开始,否则编译会出错,
4、进入顶层目录,验证环境
(在make之前需要把交叉编译器的路径给export 出来,如:
# export PATH=/opt/EmbedSky/4.3.3/bin:$PATH)
# make smdk6410_config
echo "RAM_TEXT = 0x57e00000" board/samsung/smdk6410/config.tmp;
Configuring for smdk6410 board...
# make
Generating include/autoconf.mk
Generating include/autoconf.mk.dep
……
到此,就已经建立了自己的目录,还有测试了编译的环境,如果都正确的话,就可以进行下面的移植工作了。
三、修改u-boot-2010.09中的文件,以支持smdk6410
1、修改start.S(arch/arm/cpu/arm1176/start.S),增加nand flash拷贝代码
⑴在stack_setup:之前,增加如下内容:
/****** NAND_BOOT ********/
#define LENGTH_UBOOT 0x100000
#define NAND_CTL_BASE 0x70200000
#ifdef CONFIG_S3C6410
/* Offset */
#define oNFCONF 0x0
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFSTAT 0x28
@ reset NAND
@mov r1, #NAND_CTL_BASE
ldr r1, =NAND_CTL_BASE
ldr r2, =( (7
str r2, [r1, #oNFCONF]
ldr r2, =( (1
str r2, [r1, #oNFCONT
ldr r2, =(0x16) @ RnB Clear
str r2, [r1, #oNFSTAT]
movr2, #0xff@ RESET command
strb r2, [r1, #oNFCMD]
movr3, #0 @ wait
nand1:
add r3, r3, #0x1
cmpr3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x10
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
movfp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
movr1, #0x0
movr2, #LENGTH_UBOOT
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
beq stack_setup
bad_nand_read:
loop2:
b loop2 @ infinite loop
ok_nand_read:
@ verify
@mov r0, #0 @s3c6410 nand map address is 0c00 0000 , zhoulong
ldr r0, =0x0c000000
ldr r1, =TEXT_BASE
movr2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subsr2, r2, #4
beq stack_setup
bne go_next
notmatch:
loop3:
b loop3 @ infinite loop
#endif
⑵在#ifdef CONFIG_ENABLE_MMU
_mmu_table_base:
.word mmu_table
#endif 之前增加:
#define STACK_BASE 0x53f00000
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
2、在目录board/samsung/smdk6410下创建nand_cp.c, 文件内容如下:
#include
#include
#define __REGb(x)(*(volatile unsigned char *)(x))
#define __REGw(x) (*(volatile unsigned short *)(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 NFSTAT_BUSY1
#define nand_select() (NFCONF &= ~0x800)
#define nand_deselect() (NFCONF |= 0x800)
#define nand_clear_RnB() do {} while (0)
#elif 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 NFDATA16 __REGw(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT_BUSY1
#define nand_select() (NFCONT &= ~(1
#define nand_deselect() (NFCONT |= (1
#define nand_clear_RnB() (NFSTAT |= (1
#elif defined(CONFIG_S3C6410) /* added by zhoulong */
#define NF_BASE 0x70200000
#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 + 0x28)
#define NFSTAT_BUSY1
#define nand_select() (NFCONT &= ~((1
#define nand_deselect() (NFCONT |= ((1
#define nand_clear_RnB() (NFSTAT |= (1
#endif
static inline void nand_wait(void)
{
int i;
while (!(NFSTAT & NFSTAT_BUSY))
for (i=0; i
}
struct boot_nand_t {
int page_size;
int block_size;
int bad_block_offset;
};
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 if (nand-page_size == 4096) { /* added by zhoulong */
page_num = i 12; /* addr / 4096 */
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 if (nand-page_size == 4096) { /* added by zhoulong */
page_num = addr 12;
/*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 page_size; i++) {
*buf = (NFDATA & 0xff);
buf++;
}
#elif defined(CONFIG_S3C2440)
for (i = 0; i page_size1); i++) {
*ptr16 = NFDATA16;
ptr16++;
}
#elif defined(CONFIG_S3C6410)
for (i = 0; i page_size; i++) {
*buf = (NFDATA & 0xff);
buf++;
}
#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
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)
{
unsigned char *p = buf;
int i, j;
unsigned short nand_id;
struct boot_nand_t nand;
/* chip Enable */
nand_select();
nand_clear_RnB();
for (i = 0; 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.page_size = 512;
nand.block_size = 16 * 1024;
nand.bad_block_offset = 5;
} 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;
} else if (nand_id == 0xecd5 ){/*added by zhoulong */
/* Samsung K9GAG08B0M K9GAG08U0M K9G08U1M */
nand.page_size = 4096;
nand.block_size = 512 * 1024;
nand.bad_block_offset = nand.page_size;
} 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
#ifdef CONFIG_S3C2410_NAND_SKIP_BAD
if (i & (nand.block_size-1)== 0) {
if (nand_id == 0xecd5) { /* added by zhoulong */
/*Check "FFh" at the column address 4,096 of the last page in the block */
if (is_bad_block(&nand,i + nand.block_size - nand.page_size)) {
/* Bad block */
i += nand.block_size;
size += nand.block_size;
continue;
}
} else {
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;
}
(未完待续。。。 转帖请注明出处: 武汉华嵌嵌入式培训 www.embedhq.org)
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。