返回首页

u-boot-2010.09移植到S3C6410笔记(一)

时间:2012-08-12 16:11来源:武汉华嵌嵌入式培训 作者:技术部 点击:
u-boot-2010.09移植到S3C6410笔记(一) 作者: 武汉华嵌高级讲师 周老师 一、移植环境 Oracle VM VirtualBox + Ubuntu 12.04 开发板CPU S3C6410, 该开发板: 256MSDROM : (0x5000 0000- 0x5f00 0000, 0x6000 0000 0x6f00 00
  

u-boot-2010.09移植到S3C6410笔记(一)

作者: 武汉华嵌高级讲师   周老师

 

一、移植环境

  1. Oracle VM VirtualBox + Ubuntu 12.04
  2. 开发板CPU S3C6410, 该开发板:

256MSDROM : (0x5000 0000- 0x5f00 0000, 0x6000 0000 – 0x6f00 0000)

2GMLC nandflash: 型号K9GAG08U0D , page size: 4K, block size: 512K

以太网卡:DM9000, 片选Xm0CSn[1] (基址0x1800 0000)

  1. u-boot版本号是u-boot-2010.09,其官方下载地址:ftp://ftp.denx.de/pub/u-boot/;
  2. 交叉编译器使用:EABI-4.3.3_EmbedSky_20100610.tar.bz2。

该版本的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<<12)|(7<<8)|(7<<4)|(1<<2) )

       str   r2, [r1, #oNFCONF]

      

       ldr   r2, =( (1 << 5) | (1<<4)| (0 << 2) | (0<<1) |(1<<0) )   @ Active low CE Control

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

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

#define nand_deselect()  (NFCONT |= (1 << 1))

#define nand_clear_RnB()     (NFSTAT |= (1 << 2))

#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 << 1) | (1 << 2)))

#define nand_deselect()  (NFCONT |= ((1 << 1) | (1 << 2)))

#define nand_clear_RnB()     (NFSTAT |= (1 << 4))

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

};

 

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 < nand->page_size; i++) {

              *buf = (NFDATA & 0xff);

              buf++;

       }

#elif defined(CONFIG_S3C2440)

       for (i = 0; i < (nand->page_size>>1); i++) {

              *ptr16 = NFDATA16;

              ptr16++;

       }

#elif defined(CONFIG_S3C6410)

       for (i = 0; i < nand->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 << 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)

{

       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 < 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.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 < (start_addr + size);) {

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

------分隔线----------------------------

  • 李老师
  • 李老师
  • 胡老师
  • 胡老师
合作伙伴
  • 武汉工程大学合作培训机构

  • 国家信息技术紧缺人才培养工程(NITE)

  • ARM公司全球授权培训中心

  • 国内首家Symbian授权培训

  • 微软全球嵌入式合作伙伴

  • Altera全球合作培训机构

在线客服
  • 客服热线:
    139-8620-3604
    159-2752-9536



  • 官方微信
  •  咨询微信二维码