专栏中心

EEPW首页 > 专栏 > u-boot-2010.09移植到S3C6410笔记(一)

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

发布人:华嵌 时间:2013-08-09 来源:工程师 发布文章

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

 

一、移植环境

  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

       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)

专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词:

相关推荐

高性能 C64+ DSP 上 TCP2/VCP2 协处理器的应用

视频 2010-03-18

四个月两次到访,中国市场对英伟达到底有多重要?

国际视野 2025-04-29

EasyARM2104开发实验板可固化的EINT1中断实验程序

EasyARM2131 选型指南

资源下载 2007-03-30

集成电路发明历程

视频 2010-03-18

集成隔离式 CAN 收发器 - ISO1050

视频 2010-03-18

新型SiC模块,可将安装面积减少一半

高性能 DSP 上的串行 RapidIO 接口

视频 2010-03-18

在上海车展的光辉下,是贸易战下的全球汽车产业衰退

宇视科技张鹏国:构建“万物皆可Chat”全新生态

2025-04-29

EasyARM2104开发套件快速入门和LPC2104工程模板

意法半导体收购端侧AI公司

英伟达否认将分拆中国业务独立运营:这些说法没有任何依据

高性能 32位嵌入式处理器TMS470 家族

视频 2010-03-18

基于onsemi NCP12400的固定频率电流模式AC/DC医疗级插墙式20W适配器

基于onsemi NCP681的图腾柱 PFC 控制器的AC/DC医疗级600W适配器

微软警告:量子计算竞争美国绝不能落后中国,更输不起整场竞赛

EasyARM2104开发套件功能介绍

基于意法半导体STM32G473和STDRIVE 101的电池供电BLDC/PMSM电动工具

更多 培训课堂
更多 焦点
更多 视频

技术专区