Chinaunix首页 | 论坛 | 博客
  • 博客访问: 236825
  • 博文数量: 29
  • 博客积分: 1598
  • 博客等级: 上尉
  • 技术积分: 388
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-09 13:35
文章分类
文章存档

2012年(3)

2011年(4)

2010年(1)

2009年(21)

我的朋友

分类: LINUX

2009-04-20 23:33:09

8 分析到此告一段落,下面进入uboot的具体移植

1)创建自己的工作目录。board目录下创建自己的工作目录,将smdk2410目录下的内容全部拷贝到tc2410目录下

cd board

mkdir tc2410

cp -fr board/smdk2410 board/tc2410

cp include/configs/smdk2410.h include/configs/tc2410.h

修改tc2410目录下相关的文件名以及makefile,。在这个目录下需要添加nand_read.c文件,可以从vivi里面拷贝过来,nand_read.c文件主要实现了start.S文件中的nand_read_ll读写函数,用来将uboot拷贝到内存里去。

需要修改的地方:mv smdk2410.c tc2410.c COBJS := tc2410.o flash.o nand_read.o

修改顶层makefile,添加自己的信息:

tc2410_config    :    unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t tc2410 null s3c24x0


2修改start.S

禁止中断部分也要修改

# if defined(CONFIG_S3C2410)
    ldr    r1, =0x7ff   //
根据2410芯片手册,INTSUBMSK11位可用,
                       //vivi
也是0x7ff,不知为什么UBoot一直没改过来。
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

将以下UBoot的重定向语句替换这段relocate代码只对从norflash中启动的设备有效,因此可以去掉
#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_S3C2410_NAND_BOOT  

@ 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, #0x20000
  bl    nand_read_ll
这个函数在nand_read.c中实现
  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
,这句话的意思在start.S中已注释。
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_S3C2410_NAND_BOOT 

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

start.S文件修改到此结束。






3)在include/configs/tc2410.h头文件中添加nandflash的初始化信息,这个文件与板子密切相关,需要修改的地方也很多。

具体添加信息/*//添加的内容

//#define CFG_ENV_IS_IN_FLASH 1

#define CFG_ENV_IS_IN_NAND 1

#define CFG_ENV_OFFSET 0x020000

#define CFG_NAND_BASE 0x4E000000

#define CMD_SAVEENV

#define CFG_NAND_LEGACY

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

#define CFG_MONITOR_BASE PHYS_SDRAM_1


#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) {rNFCONF |= (1<<11);}

#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}

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


//添加的内容

/*

* Nandflash Boot

*/

#define CONFIG_S3C2410_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 oNFCMD 0x04

#define oNFADDR 0x08

#define oNFDATA 0x0c

#define oNFSTAT 0x10

#define oNFECC 0x14

#define rNFCONF (*(volatile unsigned int *)0x4e000000)

#define rNFCMD (*(volatile unsigned char *)0x4e000004)

#define rNFADDR (*(volatile unsigned char *)0x4e000008)

#define rNFDATA (*(volatile unsigned char *)0x4e00000c)

#define rNFSTAT (*(volatile unsigned int *)0x4e000010)

#define rNFECC (*(volatile unsigned int *)0x4e000014)

#define rNFECC0 (*(volatile unsigned char *)0x4e000014)

#define rNFECC1 (*(volatile unsigned char *)0x4e000015)

#define rNFECC2 (*(volatile unsigned char *)0x4e000016)

#endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/

#endif /*__CONFIG_H*/

4)我使用的是勤研开发板,在vivi里面并没有找到关于内存区配置的信息。lowlevel.init文件不知道如何修改。看见网上很多人说根据开发板的内存区情况配置,我找了半天没找到,郁闷至极。。。不过没有影响我成功移植,:-)


5)在include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入nandflash的具体信息。

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},
......

{NULL,}

};

6修改/lib_arm中的board.c

static int display_banner (void)
{
    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",
输出_armboot_start地址信息   
        _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);
}


7修改common/env_nand.c,具体nandflash的擦写需要使用nand_legacy_erase等函数实现,而不是nand-erase()函数
......

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


8/board/tc2410/tc2410.c文件的末尾添加对Nand Flash 的初始化函数(在后面Nand Flash的操作都要用到)

u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nnd/nand.c中的nand_init();否则调用board/smdk2410/smdk2410.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_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->NFCONF &= ~(1<<11);
break;

case NFCE_HIGH:
nand->NFCONF |= (1<<11);
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->NFCONF |= (1<<12);
}

static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

return(nand->NFECC);
}

#endif

/*

* NAND flash initialization.
*/
#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((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<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

9)移植的大部分问题是解决了,但是将Uboot烧进去后,可能还是会碰到问题。<开发板u-boot-1>>这本pdf资料描述的问题我全都碰到了。呵呵,不过根据书上所提出的方法,我们都可以一一解决。

a 比如你如果没打开tc2410.h文件中的CFG_CMD_PING选项,使用ping 192.168.1.X命令时,可能ping不通。

b 不能保存环境变量,

Nand flash saveenv命令实现的函数 common/env_nand.c主要由以下几个宏决定:

CFG_CMD_ENV

CFG_CMD_NAND

CFG_ENV_IS_IN_NAND ---> 此宏决定调用 common/env_nand.c中的saveenv()函数,

如果定义CFG_ENV_IS_IN_FLASH宏,则调用 common/env_flash.c中的saveenv()函数

CFG_ENV_OFFSET 0X20000

#define CFG_NAND_BASE 0X4E000000

#define CMD_SAVEENV

#define CFG_NAND_LEGACY

#define CFG_ENV_SIZE 0x10000 //64kB

这些也是要在tc2410.h中添加的信息。

c tftp下载时出现TTTTTTTTTT然后超时的提示信息。我被这个问题困扰了很长时间,我也按照<开发板u-boot-1>>这本pdf资料修改,将U_BOOT_CMD(

bootm, CFG_MAXARGS, 1, do_bootm,

"bootm - boot application image from memory\n",

"[addr [arg ...]]\n - boot application image stored in memory\n"

"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"

"\t'arg' can be the address of an initrd image\n"

/*#ifdef CONFIG_OF_FLAT_TREE

"\tWhen booting a Linux kernel which requires a flat device-tree\n"

"\ta third argument is required which is the address of the

"\tdevice-tree blob. To boot that kernel without an initrd image,\

"\tuse a '-' for the second argument. If you do not pass a third\

"\ta bd_info struct will be passed instead\n"

endif */

Ifdef注释掉以后,然后再将config.mk中的OsO2都改做O.

终端再输入:make distclean

make tc2410_config

make CROSS_COMPILE=arm-linux-

生成了uboot镜像,共110.4K。烧到板子里去后,使用tftp下载内核,搞定!!!终于把uboot搞定了,断断续续的大概花了1个多月的时间,参考了网上众多高手的心得以及很多不错的资料,总算勉强的弄出来Uboot了,但还是有很多问题没有弄清楚呵呵,不过还是挺有成就感的。


疑问:

1 可以在include/configs/smdk2410.h中添加nandflash的宏定义

2 board.c里面的start_armboot()函数需要调用nand_init,即nandflash的初始化。在drive/nand/nand.c中有这样一段代码

#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)

意思就是 如果没有定义CFG_NAND_LEGACY那么则调用nand.c文件中的nand_init()函数。这个是默认的初始化函数。但还有个board_nand_init()函数没有实现。为了安全起见,我们可以定义CFG_NAND_LEGACY,从而可以调用board/smdk2410/smdk2410.c中的nand_init()函数.这样我们需要在smdk2410.c中添加这个初始化函数。nand_legacy.c中添加这个nand_init()与在smdk2410.c中添加有什么区别??

board/smdk2410/smdk2410.c文件里只有board_init(),dram_init()函数,没有nand_init()函数。那这个函数去哪里实现。

3 nand_read_ll用来将代码拷贝到RAM中去,这个函数可以从vivi中拷贝过来

阅读(2991) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~