Chinaunix首页 | 论坛 | 博客
  • 博客访问: 306685
  • 博文数量: 75
  • 博客积分: 2710
  • 博客等级: 少校
  • 技术积分: 706
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-21 14:19
文章分类

全部博文(75)

文章存档

2011年(10)

2010年(22)

2009年(43)

我的朋友

分类: 嵌入式

2009-08-28 15:48:37

一、硬件环境介绍
CPU:S3C2410(ARM920T)
RAM:64M SDRAM(HY57V561620(32MB)两片共64M,SDRAM 的起始地址为0x30000000)
Flash:64M NANDFLASH(K9F1208)
NOR FLASH:64K
网络芯片:CS8900A
串口1、2、3
USB主从接口
LCD液晶屏
 
二、软件环境介绍
VMware+fedora9
交叉编译器:arm-linux-gcc-3.4.1(soft-float)
U-Boot版本:u-boot-2009.08-rc2
skyeye模拟器:skyeye-1.2.8_rc1
 
三、移植要求
从Nand启动,支持tftp、nfs及usb,添加nand命令、写环境变量至nand和内核启动参数支持(bootcmd、bootargs),支持ping命令,能正常启动内核。
 
四、移植过程详解
1、准备
(1)安装skyeye并测试
修正bug:
【1】make install不成功
原因:缺少mkinstalldirs,下载一份,拷贝到thirdparty目录下,修改为可执行即可。
【2】test-suite不能运行,出现read bus error问题解决
http://blog.csdn.net/alien75/archive/2009/06/26/4301485.aspx
修改memory/ram.c文件中的mem_read函数,
*(uint8_t *)value = (uint8_t)mem_read_byte (offset);改为*value = (uint8_t)mem_read_byte (offset);
*(uint16_t *)value = (uint16_t)mem_read_halfword (offset);改为*value = (uint16_t)mem_read_halfword (offset);
重新编译安装即可。
另外还需要制作mknandflashdump程序(在device/nandflash/tools/下,执行gcc mknandflashdump.c生成a.out重命名为mknandflashdump,然后移动到/usr/local/bin目录下即可),以生成虚拟nandflash。
(2)安装交叉编译器
使用crosstool-4.3编译,一定要编译成softfloat的;
一个gcc版本过低的BUG:
patches/glibc-2.3.3-allow-gcc-4.0-configure.patch
-    3.[2-9]*)
+    3.[2-9]*|4.[01]*)----------》3.[2-9]*|4.*)
 
2、阅读U-Boot的说明README,测试U-Boot
修改u-boot.lds,[.rodata:{*(.rodata)}];
make smdk2410_config
make成功
模拟测试:
编写skyeye.conf文件,生成nand.dump(mknandflashdump u-boot.bin nand.dump 0x0),然后执行
skyeye -c skyeye.conf即可。
skyeye.conf从skyeye测试包里拷贝一份,修改一下即可。
(从零地址开始的一块内存,file=./u-boot.bin,boot=yes)
3、修改U-boot代码,完成nand启动
(1)在start.S中添加搬运代码
/* boot from nand */
#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, #0x40000
    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 /* CONFIG_S3C2410_NAND_BOOT */
(2)在_start_armboot:    .word start_armboot之后添加两行:
    .align     2
DW_STACK_START:  .word  STACK_BASE+STACK_SIZE-4
(3)内存控制修改(lowlevel_init.S)
#define B1_BWSCON        (DW16)           @16位
(4)所需变量宏定义(include/configs/gyh2410.h)
#define oNFCONF               0x00
#define oNFCMD                0x04
#define oNFADDR               0x08
#define oNFDATA               0x0c
#define oNFSTAT               0x10
#define oNFECC                0x14
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE    0x33f00000
#define STACK_SIZE    0x8000
#define NAND_CTL_BASE            0x4E000000
(5)实现nand_read_ll函数(nand_read.c)
#define BUSY 1
inline void wait_idle(void) {
    int i;
    while(!(NFSTAT & BUSY))
    for(i=0; i<10; i++);
}
/* low level nand read function */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;
    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return -1; /* invalid alignment */
    }
    /* chip Enable */
    NFCONF &= ~0x800;
    for(i=0; i<10; i++);
    for(i=start_addr; i < (start_addr + size);) {
        /* READ0 */
        NFCMD = 0;
        /* Write Address */
        NFADDR = i & 0xff;
        NFADDR = (i >> 9) & 0xff;
        NFADDR = (i >> 17) & 0xff;
        NFADDR = (i >> 25) & 0xff;
        wait_idle();
        for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
            *buf = (NFDATA & 0xff);
            buf++;
        }
    }
    /* chip Disable */
    NFCONF |= 0x800; /* chip disable */
    return 0;
}
编译、测试。
4、添加nand命令,写环境变量至nand
(1)配置命令支持
#define CONFIG_CMD_NAND
#define CONFIG_ENV_IS_IN_NAND    1
#define CONFIG_ENV_SIZE        0x10000    /* Total Size of Environment Sector */
#define CONFIG_ENV_OFFSET    0x40000
(2)实现board_nand_init函数(在nand_read.c中添加)
#include

#if 0
#define DEBUGN    printf
#else
#define DEBUGN(x, args ...) {}
#endif

#include
#include
#include

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

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

#define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8

static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;

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

    if (ctrl & NAND_CTRL_CHANGE) {
        ulong IO_ADDR_W = NF_BASE;

        if (!(ctrl & NAND_CLE))
            IO_ADDR_W |= S3C2410_ADDR_NCLE;
        if (!(ctrl & NAND_ALE))
            IO_ADDR_W |= S3C2410_ADDR_NALE;

        chip->IO_ADDR_W = (void *)IO_ADDR_W;

        if (ctrl & NAND_NCE)
            NFCONF &= ~S3C2410_NFCONF_nFCE;
        else
            NFCONF |= S3C2410_NFCONF_nFCE;
    }

    if (cmd != NAND_CMD_NONE)
        writeb(cmd, chip->IO_ADDR_W);
}

static int s3c2410_dev_ready(struct mtd_info *mtd)
{
    DEBUGN("dev_ready\n");
    return (NFSTAT & 0x01);
}

#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
    DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
    NFCONF |= S3C2410_NFCONF_INITECC;
}

static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
                      u_char *ecc_code)
{
    ecc_code[0] = NFECC0;
    ecc_code[1] = NFECC1;
    ecc_code[2] = NFECC2;
    DEBUGN("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
        mtd , ecc_code[0], ecc_code[1], ecc_code[2]);

    return 0;
}

static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                     u_char *read_ecc, u_char *calc_ecc)
{
    if (read_ecc[0] == calc_ecc[0] &&
        read_ecc[1] == calc_ecc[1] &&
        read_ecc[2] == calc_ecc[2])
        return 0;

    printf("s3c2410_nand_correct_data: not implemented\n");
    return -1;
}
#endif

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

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

    /* read_buf and write_buf are default */
    /* read_byte and write_byte are default */

    /* hwcontrol always must be implemented */
    nand->cmd_ctrl = s3c2410_hwcontrol;

    nand->dev_ready = s3c2410_dev_ready;

#ifdef CONFIG_S3C2410_NAND_HWECC
    nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
    nand->ecc.calculate = s3c2410_nand_calculate_ecc;
    nand->ecc.correct = s3c2410_nand_correct_data;
    nand->ecc.mode = NAND_ECC_HW3_512;
#else
    nand->ecc.mode = NAND_ECC_SOFT;
#endif

#ifdef CONFIG_S3C2410_NAND_BBT
    nand->options = NAND_USE_FLASH_BBT;
#else
    nand->options = 0;
#endif

    DEBUGN("end of nand_init\n");

    return 0;
}
(2)配置nand
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK 511
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
5、支持tftp和nfs及usb,添加ping命令
#define CONFIG_CMD_NET
#define CONFIG_CMD_PING
#define CONFIG_USB_OHCI
#define CONFIG_USB_STORAGE
#define CONFIG_USB_KEYBOARD
#define CONFIG_DOS_PARTITION
#define CFG_DEVICE_DEREGISTER
#define CONFIG_SUPPORT_VFAT
#define LITTLEENDIAN
6、去除nor flash支持(板子上没有)
#define CONFIG_SYS_NO_FLASH
//#define PHYS_FLASH_1        0x00000000 /* Flash Bank #1 */
//#define CONFIG_SYS_FLASH_BASE        PHYS_FLASH_1
//#define CONFIG_AMD_LV400    0    /* uncomment this if you have a LV400 flash */
#define CONFIG_SYS_MAX_FLASH_BANKS    0    /* max number of memory banks */
7、支持内核启动参数
#define CONFIG_BOOTDELAY    3
#define CONFIG_BOOTARGS    "nointrd root=/dev/mtdblock2 console=ttySAC0,115200 mem=64M init=/linuxrc"
#define CONFIG_ETHADDR    08:00:3e:26:0a:5b
#define CONFIG_NETMASK          255.255.255.0
#define CONFIG_IPADDR        192.168.209.211
#define CONFIG_SERVERIP        192.168.209.129
#define CONFIG_BOOTCOMMAND    "tftp 30008000 uImage; bootm 30008000"
8、skyeye模拟测试(skyeye -c skyeye.conf)
Your elf file is little endian.
arch: arm
cpu info: armv4, arm920t, 41009200, ff00fff0, 2
mach info: name s3c2410x, mach_init addr 0x806a9e0
ethmod num=1, mac addr=8:0:3e:26:a:5b, hostip=10.0.0.1
nandflash: dump ./nand.dump
file size:69206016
dbct info: turn on dbct!
uart_mod:0, desc_in:, desc_out:, converter:
SKYEYE: use arm920t mmu ops
Loaded RAM   ./u-boot.bin
ERROR: s3c2410x_io_write_word(0x4c000000) = 0x00ffffff
ERROR: s3c2410x_io_write_word(0x4c000008) = 0x00048032


U-Boot 2009.08-rc2 ( 8月 31 2009 - 11:12:46)

DRAM:  64 MB
NAND:  64 MiB
Hit any key to stop autoboot:  0
GYH2410 #
9、注意事项
(1)命令定义时注意顺序,要在config_cmd_defaults.h引用之前或者添加到该头文件中
(2)去掉flash支持时Makefile中flash.o不能去掉,否则会引起错误,注意添加nand_read.o
10、存在的问题(望高手指点)
tftp和ping不正常的解决方法:修改net/tftp.c和net/nfs.c文件,将TIMEOUT改为10倍(因为是模拟,速度跟不上,所以要改)。

使用skyeye模拟时使用u-boot.bin可以,但是使用u-boot即会出现bus read error,且无法正常使用,经gdb调试发现nand_read_ll函数调用时参数传递不正确,难道时skyeye的原因?我换过1.2.6的版本还是不行。
阅读(1687) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~