Chinaunix首页 | 论坛 | 博客
  • 博客访问: 95676
  • 博文数量: 17
  • 博客积分: 1512
  • 博客等级: 上尉
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-29 03:09
文章分类

全部博文(17)

文章存档

2010年(3)

2009年(1)

2008年(13)

我的朋友

分类: LINUX

2008-03-23 14:31:53

移植U-Boot.1.2.0到博创2410-S(S3C2410A)


一、在U-Boot中建立自己的开发板类型,并测试编译。
我为开发板取名叫: tekkaman2410

0 在工作目录下解压U-Boot。
$tar zxvf u-boot.git.tar.gz


1 进入U-Boot目录,修改Makefile
$cd u-boot.git/
$vi Makefile
#为tekkaman2410建立编译项

smdk2410_config :       unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

tekkaman2410_config    :    unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t tekkaman2410 tekkaman s3c24x0
各项的意思如下:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
tekkaman2410: 开发板的型号(BOARD),对应于board/tekkaman/tekkaman2410目录。
tekkaman: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。

同时在
“ifndef CROSS_COMPILE ”之前  加上自己交叉编译器的路径,比如我使用crosstool-0.43制作的基于2.6.22.2内核和gcc-4.1.0-glibc-2.3.2的ARM9TDMI交叉编译器,则:

CROSS_COMPILE=/home/tekkaman/working/crosstool-gcc410-k26222/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-



2 在/board子目录中建立自己的开发板tekkaman2410目录

由于我在上一步板子的
开发者/或经销商(vender)中填了 tekkaman ,所以开发板tekkaman2410目录一定要建在/board子目录中的tekkaman目录下 ,否则编译会出错。

$cd board
$mkdir tekkaman tekkaman/tekkaman2410
$cp -arf smdk2410/*   tekkaman/tekkaman2410/
$cd tekkaman/tekkaman2410
$mv smdk2410.c tekkaman2410.c


   还要记得修改自己的开发板tekkaman2410目录下的Makefile文件,不然编译时会出错:
COBJS    := tekkaman2410.o flash.o
$vi Makefile



3 在include/configs/中建立配置头文件
$cd ../../..
$cp include/configs/smdk2410.h include/configs/tekkaman2410.h


4 测试编译能否成功
$make tekkaman2410_config
Configuring for tekkaman2410 board...
(如果出现:
$ make tekkaman2410_config

Makefile:1927: *** 遗漏分隔符 。 停止。
请在U-boot的根目录下的Makefile的
        @$(MKCONFIG) $(@:_config=) arm arm920t tekkaman2410 tekkaman)
前加上“Tab”键)
$make


    我到这一步测试交叉编译成功!!




二、修改U-Boot中的文件,以匹配博创的2410-S实验箱。
 1 修改/cpu/arm920t/start.S

  (1)修改中断禁止部分

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


  (2)修改时钟设置(可以不修改,因为后面的board_init函数也会
将时钟设为202.8MHz
   
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN

    mov    r1, #3
    str    r1, [r0]

    mrc    p15, 0, r1, c1, c0, 0        /*read ctrl register   tekkaman*/
    orr    r1, r1, #0xc0000000         /*Asynchronous  tekkaman*/
    mcr    p15, 0, r1, c1, c0, 0      /*write ctrl register tekkaman*/

    /*now, CPU clock is 202.8 Mhz   tekkaman*/
    mov    r1, #CLK_CTL_BASE    /* tekkaman*/
    mov    r2, #MDIV_200                   /* mpll_200mhz    tekkaman*/
    add    r2, r2, #PSDIV_200             /* mpll_200mhz    tekkaman*/
    str    r2, [r1, #0x04]               /* MPLLCON tekkaman */

#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */

    红色部分是我添加的,因为 U-Boot 使用的是
/* default FCLK is 120 MHz ! */
    我利用
博创提供的vivi的代码,将其设为202.8MHz 并在前面加上:

#elif defined(CONFIG_S3C2410)
# define pWTCON        0x53000000
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
#define CLK_CTL_BASE        0x4C000000 
/* tekkaman */
#define MDIV_200        0xa1 << 12   /* tekkaman */
#define PSDIV_200        0x31
       /* tekkaman */



 
(3)将从Flash启动改成从NAND Flash启动。
将以下U-Boot的重定向语句段:

#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   @tekkaman@@@@@@@@@@@@@@@@SSSSSSSSSSSSS
@ 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
  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  @tekkaman@@@@@@@@@@@@@@@@@@EEEEEEEEE

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


附:顺便提一下,在
start.S文件的注释部分有个小错误(红色部分:原来是2)
cpu_init_crit:
    ......
    /*
     * disable MMU stuff and caches
     */
    mrc    p15, 0, r0, c1, c0, 0
    bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
    bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
    orr    r0, r0, #0x00000002    @ set bit 1 (A) Align
    ......

 
在board/tekkaman/tekkaman2410加入NAND Flash读函数,建立nand_read.c文件,加入如下内容(copy from vivi):

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



3 修改board/tekkaman/tekkaman2410/Makefile文件
......
OBJS := tekkaman2410.o  nand_read.o

......


4 修改include/configs/tekkaman2410.h文件,添加如下内容:
......
/*
 * 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
#endif    /* __CONFIG_H */


5 修改board/tekkaman/tekkaman2410/lowlevel_init.S文件
    依照开发箱的内存区的配置情况, 修改board/tekkaman/tekkaman2410/lowlevel_init.S文件,我利用博创提供的vivi源码里的信息做了如下更改:
......
#define B1_BWSCON          (DW16)    /*@tekkaman*/
#define B2_BWSCON          (DW16)
#define B3_BWSCON          (DW16)    /*@tekkaman*/
#define B4_BWSCON          (DW16)
#define B5_BWSCON          (DW16)
#define B6_BWSCON          (DW32)
#define B7_BWSCON          (DW32)
......
#define B3_Tacs             0x0    /*  0clk */

#define B3_Tcos             0x0    /*  0clk
@tekkaman*/ 
#define B3_Tacc             0x7    /* 14clk */
#define B3_Tcoh             0x0    /*  0clk
@tekkaman*/ 
#define B3_Tah              0x0    /*  0clk */
#define B3_Tacp             0x0   
/*@tekkaman*/
#define B3_PMC              0x0    /* normal */
......
注:之所以Bank3的改动较大,是因为smdk2410的网卡CS8900是在
Bank3,而博创2410-S的AX88796是在Bank2。
......
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0xb2    /*@tekkaman*/
    .word 0x30
    .word 0x30


6 修改/board/tekkaman/tekkaman2410/tekkaman2410.c
  因为博创2410-S和smdk2410的GPIO连接有所不同,我依旧利用博创配的vivi,修改其对GPIO的配置(具体原因我并未深究,请参阅博创2410-S的硬件说明和2410芯片手册)
......
    gpio->GPEUP = 0x0000FFFF;
    gpio->GPFCON = 0x000051aa;  //0x000055AA;  tekkaman
    gpio->GPFUP = 0x000000ef;  //0x000000FF;  tekkaman
    gpio->GPGCON = 0xfd95ffba;  //0xFF95FFBA;  tekkaman
    gpio->GPGUP = 0x0000efff;  //0x0000FFFF;  tekkaman
    gpio->GPHCON = 0x0016faaa;  //0x002AFAAA;  tekkaman
    gpio->GPHUP = 0x000007FF;
......



7 为了实现NAND Flash的读写,再次修改

/include/configs/tekkaman2410.h
(请格外注意:如果编译时报错,在Linux下用KWrite等有高亮显示的文本编辑器看看文件的注释是不是为
注释应有的颜色(KWrite中为灰色),如果不是,则将注释删除。因为#define后面的注释被认为是程序的一部分。建议注释和#define分行写)
......
/*
 * Hardware drivers
 */
//#define CONFIG_DRIVER_CS8900    1    /* we have a CS8900 on-board */
//#define CS8900_BASE        0x19000300
//#define CS8900_BUS16        1 /* the Linux driver does accesses as shorts */
#define CONFIG_DRIVER_NE2000
#define CONFIG_DRIVER_NE2000_BASE (0x10000000+0x200)
......

/***********************************************************
 * Command definition
 ***********************************************************/
#define CONFIG_COMMANDS \
            (CONFIG_CMD_DFL     | \
            CFG_CMD_CACHE     | \
            CFG_CMD_NAND     | \
            CFG_CMD_NET     | \
            /*CFG_CMD_EEPROM |*/ \
            /*CFG_CMD_I2C     |*/ \
            /*CFG_CMD_USB     |*/ \
            CFG_CMD_PING | \
            CFG_CMD_ENV | \
            CFG_CMD_REGINFO  | \
            CFG_CMD_DATE     | \
            CFG_CMD_ELF)

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include
#define CONFIG_CMDLINE_TAG
//增加U-Boot对内核参数传递的功能,

//具体内容请参阅对《U-BOOT下使用bootm引导内核方法》的补充说明
......

#define    CFG_LONGHELP               
/* undef to save memory        */
#define    CFG_PROMPT   "[Tekkaman2410]#"
/*Monitor Command Prompt  */

#define    CFG_CBSIZE        256       
/* Console I/O Buffer Size    */
......
#define    CFG_LOAD_ADDR      0x30008000  
 /* default load address    */


......

//#define PHYS_FLASH_1        0x00000000 /* Flash Bank #1 */

//#define CFG_FLASH_BASE        PHYS_FLASH_1

/*-----------------------------------------------------------------------
 * FLASH and environment organization
 */
#define CFG_NO_FLASH    1
#if 0
#define CONFIG_AMD_LV400    1    /* uncomment this if you have a LV400 flash */
//#if 0   ///删掉这行
#define CONFIG_AMD_LV800    1    /* uncomment this if you have a LV800 flash */
#endif

//#define CFG_MAX_FLASH_BANKS    1    /* max number of memory banks */
......

/* timeout values are in ticks */
//#define CFG_FLASH_ERASE_TOUT    (5*CFG_HZ)
/* Timeout for Flash Erase */
//#define CFG_FLASH_WRITE_TOUT    (5*CFG_HZ)
/* Timeout for Flash Write */

#define    CFG_ENV_IS_IN_NAND    1  ///第一次改没有改好NAND
#define CFG_ENV_OFFSET  0X20000
//#define ENV_IS_EMBEDDED 1
#define CFG_NAND_LEGACY

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

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



8

include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入

static struct nand_flash_dev nand_flash_ids[] = {

......
    {"Samsung KM29N16000",NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000, 0},
    {"Samsung K9F1208U0M",  NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0},

    {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000, 0},

......

{NULL,}

};



9 修改/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",    //tekkaman
        _armboot_start, _bss_start, _bss_end);      //tekkaman
#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);
}



10 修改common/env_nand.c
......
#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);

......


11 在/board/tekkaman/tekkaman2410/tekkaman2410.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



12 修正U-Boot的NE2000驱动的低级错误

将drivers/ne2000.h第45行:
 at */

改为:
 at

真是TNND汗死!!!!


13 因为没有Nor Flash芯片,所以注释掉/common/cmd_bootm.c中关于imls命令的程序段和/common/cmd_flash.c中的程序。不然,按上面的修改,编译会出错。

/common/cmd_bootm.c第91行:(“0”后面一定要换行!!!不然还会错!!!)
#if 0
(CONFIG_COMMANDS & CFG_CMD_IMLS)
#include
extern flash_info_t flash_info[]; /* info for FLASH chips */
static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#endif

/common/cmd_bootm.c第1237行:(“0”后面一定要换行!!!不然还会错!!!)
#if 0
(CONFIG_COMMANDS & CFG_CMD_IMLS)
/*-----------------------------------------------------------------------
 * List all images found in flash.
 */
int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    flash_info_t *info;
    int i, j;
    image_header_t *hdr;
    ulong data, len, checksum;

    for (i=0, info=&flash_info[0]; i        if (info->flash_id == FLASH_UNKNOWN)
......

/common/cmd_flash.c开头几行:(“0”后面一定要换行!!!不然还会错!!!)

......
#if 0

(CONFIG_COMMANDS & CFG_CMD_FLASH)

#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
#include
......





三、交叉编译U-Boot。
在U-Boot的根目录下
$make
一阵English飘过~~~~~~~~~~~~~~~~~~~~~~~
严格按上面的修改,应该是会成功的。因为我本着认真负责的态度,按上面的步骤又做了一遍,改了一遍,且编译成功。
如果你还遇到错误,可以找我讨论 QQ:78027228。
不过我建议:在看懂U-Boot的基础上移植,不然当有错误时你会狂郁闷,不知如何下手!

网友评论 、、、这个也给转过来了o(∩_∩)o...哈哈

网友: flylonglong 时间:2007-11-24 17:12:01 IP地址:202.115.65.★
为什么完全照着你的做的

一、在U-Boot中建立自己的开发板类型,并测试编译。
中的第四小步
4 测试编译能否成功
$make tekkaman2410_config
执行以上命令之后 出现以下提示:

Configuring for tekkaman2410 board...
ln:正在创建连至'asm-arm'的符号连接'asm':不允许的操作
make:***[ebest2410-config] Error 1

我昨天在编译内核的时候也出现了
ln:正在创建连至'asm-arm'的符号连接'asm':不允许的操作
这条错误
不知道怎么回事情
使用chmod命令也修改不了'asm-arm'文件的属性(它的属性是不可读写的)
不知道该怎么办了 不知道楼主知道否?????

PS:我开发环境是 vmware+redhat9.0

网友: flylonglong 时间:2007-11-24 18:04:06 IP地址:202.115.65.★
上面问题好象是解决了
不过还是在$make tekkaman2410_config 通过之后
在执行 $make 的时候
一堆英文过后
最后一行提示 make:*** [uboot] Error 1
诶 可能是我的开发环境和博主的不同吧
但是又实在找不出错在哪
真苦闷啊

Blog作者的回复:
flylonglong 您好!上面的问题我还从来没碰过。我猜想可能的原因有两个:1、你的编译器没有制作好。2、你的开发系可能老了点。我建议你自己制作一个编译器看看 ,第一个问题的可能性比较大。


网友: jscorps 时间:2007-12-28 18:14:38 IP地址:211.23.177.★
很冒昧的請問一下 , 在u-boot 1.2.0中, 原本就有sbc2410x的board 設定. 它如果用在friendly -arm上的sbc2410x , 是不是就可以從NAND FLASH上面啟動呢? 還是u-boot 1.2.0 中的sbc2410x 本來就沒有支援NAND flash boot up.

Thanks

Blog作者的回复:
sbc2410x源码不支持NAND启动,也要通过类似2410-S的一些修改来实现。


网友: jscorps 时间:2007-12-31 16:16:13 IP地址:210.202.45.★
我了解了 , 謝謝您的回覆.....
有問題 , 再跟您請教...^_^

网友: heufkk 时间:2007-12-31 16:18:08 IP地址:218.7.43.★
你好,参照你的文章我移植1.1.5,遇到如下问题
/root/u-boot-1.1.5/include/configs/fk2410.h:220:1: warning: this is the location of the previous definition
/root/bin/arm-uclinux-tool/bin/arm-uclinux-gcc -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000  -I/root/u-boot-1.1.5/include -fno-builtin -ffreestanding -nostdinc -isystem /root/bin/arm-uclinux-tool/lib/gcc/arm-uclinux/3.4.0/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes -c -o env_dataflash.o env_dataflash.c
/root/bin/arm-uclinux-tool/bin/arm-uclinux-gcc -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000  -I/root/u-boot-1.1.5/include -fno-builtin -ffreestanding -nostdinc -isystem /root/bin/arm-uclinux-tool/lib/gcc/arm-uclinux/3.4.0/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes -c -o env_flash.o env_flash.c
env_flash.c:70: error: `CFG_FLASH_BASE' undeclared here (not in a function)
env_flash.c: In function `saveenv':
env_flash.c:330: warning: implicit declaration of function `flash_sect_protect'
env_flash.c:334: warning: implicit declaration of function `flash_sect_erase'
env_flash.c:338: warning: implicit declaration of function `flash_write'
make[1]: *** [env_flash.o] 错误 1
make[1]: Leaving directory `/root/u-boot-1.1.5/common'
make: *** [common/libcommon.a] 错误 2
你前面把CFG_FLASH_BASE'注释掉了,那么我遇见这样的问题是怎么回事?
感谢你的回答

Blog作者的回复:
env_flash 是使用nor flash。2410-S没有nor flash ,所以我移植时,将一些关于nor flash 的源码删除或是不去理会。可能是这里出了问题,你要参考一下有关nor flash 移植的资料。


网友: freeubuntu 时间:2008-01-08 12:04:50 IP地址:58.60.126.★
我完全按照你的方法修改uboot1.2.0,gpio和内存地址分配参考开发商提供的bootloader
编译时保错,主要原因是在修改中删除了很多define,很多东西都没有定义了
flash.c: In function 'flash_init':
flash.c:64: error: 'CFG_MAX_FLASH_BANKS' undeclared (first use in this function)
flash.c:64: error: (Each undeclared identifier is reported only once
flash.c:64: error: for each function it appears in.)
flash.c:67: error: 'flash_info' undeclared (first use in this function)
flash.c:75:2: error: #error "Unknown flash configured"
flash.c:77: error: 'PHYS_FLASH_SIZE' undeclared (first use in this function)
flash.c:78: error: 'CFG_MAX_FLASH_SECT' undeclared (first use in this function)
flash.c:81: error: 'PHYS_FLASH_1' undeclared (first use in this function)
flash.c:113: warning: implicit declaration of function 'flash_protect'
flash.c:113: error: 'FLAG_PROTECT_SET' undeclared (first use in this function)
flash.c:114: error: 'CFG_FLASH_BASE' undeclared (first use in this function)
flash.c:119: error: 'CFG_ENV_ADDR' undeclared (first use in this function)
flash.c: At top level:
flash.c:127: error: expected ')' before '*' token
flash.c:172: error: expected ')' before '*' token
flash.c:293: error: expected ')' before '*' token
flash.c:371: error: expected ')' before '*' token
你有碰到过这些问题吗?

Blog作者的回复:
出现这种情况的原因很可能是nor flash 的驱动造成的。如果你的板上有nor flash ,请参考我移植SBC2440V4的文章,那个板子有nor flash ,而且在nor flash方面两个芯片的基本代码一样。
如果你不使用nor flash ,那就是你没有将nor flash的驱动清干净,比如:修改/include/configs/tekkaman2410.h时漏了什么。

最后出现
flash.c:127: error: expected ')' before '*' token
flash.c:172: error: expected ')' before '*' token
flash.c:293: error: expected ')' before '*' token
flash.c:371: error: expected ')' before '*' token
有可能是语法错误,可能是你手误,多删或少删了什么,比如“;”或“)”等等。
移植到2410的那篇文章我复查过应该不会有问题。


网友: freeubuntu 时间:2008-01-09 16:37:35 IP地址:58.60.126.★
上个问题解决了,可还是有错误,报错如下:
common/libcommon.a(env_nand.o): In function `saveenv':
/home/freedom/Desktop/uboot/u-boot-1.2.0/common/env_nand.c:212: undefined reference to `nand_info'
make: *** [u-boot] Error 1
看了上面的解答,知道应该是nor flash的问题,nor flash删除了一些什么内容呢?我再看一下

Blog作者的回复:
可能是你在:
10 修改common/env_nand.c时,漏了extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE];

你仔细看看10 修改common/env_nand.c这部分,看看有没有漏改了什么。

 



移植U-Boot.1.2.0到博创2410-S(S3C2410A)
补:AX88796驱动移植
 引言:
     一个Bootloader没有tftp的支持,那么移植内核实在是痛苦的事。因为你要不断的用串口烧写内核到SDRAM里,时间少则2分多钟,多则4分多钟,错了还要重烧!在实现这个驱动前,我用U-Boot就是这么痛苦。
    在移植完Linux2.6.22.2的AX88796的驱动之后,我决心一定要把AX88796移植到U-Boot上,一劳永逸。借助移植Linux下的AX88796的经验,我首先看懂了/drivers下的ne2000.c的驱动,再参考了一些RTL8019的移植记录(都是NE2000兼容网卡),在痛苦了三四天后,驱动成功,ping和tftp成功,高兴得差点跳起来!以下介绍驱动的移植和U-Boot下网卡驱动移植、编写的一般方法。


本次驱动移植的参考资料:
1、AX88796L Datasheet
2、《NE2000 网卡芯片驱动程序》巨龙公司系统集成开发部 杨屹 2002/10/20
3、《REALTEK8019as 芯片资料翻译》也就是RTL8019网卡的中文资料
4、
zcx3000的关于网卡驱动的一系列文章,特别对于网卡初始化的顺序讲解的很细,必看。URL:http://blog.csdn.net/zcx3000/category/237774.aspx
5、
《嵌入式系统接口设计与Linux驱动程序开发》(刘淼 编著)第十五章:以太网接口与Linux网络驱动程序设计
6、《ARM嵌入式常用模块与综合系统设计实例精讲》 张绮文 谢建雄 谢劲心 编著 电子工业出版社  第16章 以太网控制器模块设计


 U-Boot下网卡驱动框架:
   U-Boot的
/drivers文件夹包含了许多U-Boot可能用到的驱动,其中包括:nand flash和网卡。(如果你有修改过nand flash驱动,你一定来过这。)这些驱动基本上都是最底层的硬件驱动。网卡驱动也不例外,它并不包含协议层,只实现网卡初始化、读写、停止等等功能,所以移植起来比较容易。
U-Boot网卡驱动的接口函数由以下四个函数组成:

int eth_init(bd_t *bd):完成网卡初始化的过程:热复位、相应寄存器的赋值、设置MAC地址等等
void eth_halt() :停止网卡运行
int eth_rx() :接收网络数据
int eth_send(volatile void *packet, int length) :发送数据

U-Boot在进行网络操作时,调用的就是这四个函数。所以移植时,只要集中精力在这四个函数,使它们对网卡的操作是正确的,移植就成功了。知道以上的知识,再学习一些网卡和网络的知识,看看成功的网卡驱动,要是以后出现U-boot不支持的网卡,也可以自己写驱动了!

U-Boot下AX88796网卡移植过程
    U-Boot下的AX88796网卡(NE2000寄存器兼容)驱动是使用NE2000的驱动,用到的文件是在/drivers文件夹下的8390.hne2000.cne2000.h

    首先说明一个关键问题,U-Boot的NE2000驱动是为8位总线写的,而博创的2410-S实验箱的AX88796的硬件连接适合16位总线的网卡驱动。所以必须将NE2000驱动该写成16位总线的驱动。(也许你会想:我也可以把2410的总线宽度改成8位,来使用8位的驱动。但是请你注意看看AX88796的数据手册的第51页和实验箱原理图的网卡部分,你就会知道:即使你用8位的驱动,你也必须使用16位 的总线,而且数据会处理更加麻烦。)还有就是没有修改过的驱动有BUG,没有修正是无法正常使用的。


 (1)修改
ne2000.c
......
#define DEBUG 0


#if DEBUG & 1
#define DEBUG_FUNCTION() do { printf("%s\n", __FUNCTION__); } while (0)
#define DEBUG_LINE() do { printf("%d\n", __LINE__); } while (0)
#else
#define DEBUG_FUNCTION() do {} while(0)
#define DEBUG_LINE() do {} while(0)
#endif

#include "ne2000.h"
//将8390的头文件上移到此,因为前面就要用到
#include "8390.h"

#if DEBUG & 1
#define PRINTK(args...) printf(args)
#else
#define PRINTK(args...)
#endif

static dp83902a_priv_data_t nic; /* just one instance of the card supported */

//添加从U-Boot的参数区读取MAC地址的函数
static int
ne2000_read_mac_addr(unsigned char * enaddr)
{
    int ii;
    char *s, *e;

    s = getenv ("ethaddr");
    if (s == NULL){
        return -1;
    }
    else{
        for(ii = 0; ii < 12; ii+=2) {
            enaddr[ii] =enaddr[ii+1]= s ? simple_strtoul (s, &e, 16) : 0;
            if (s){
                s = (*e) ? e + 1 : e;
            }
        }
    }
    return 0;
}
......

static void
dp83902a_start(unsigned char * enaddr)
{
    dp83902a_priv_data_t *dp = &nic;
    cyg_uint8 *base = dp->base;
    int i;

    DEBUG_FUNCTION();

    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */
    DP_OUT(base, DP_DCR, 0x49); //将网卡的总线宽度改为16位
    DP_OUT(base, DP_RBCH, 0);        /* Remote byte count */

......

DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);
    DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */
    DP_OUT(base, DP_RCR, DP_RCR_AB);  /* Accept broadcast, no errors, no multicast */
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
    dp->running = true;
}

......

static void
dp83902a_send(unsigned short *data, int total_len, unsigned long key)
{
......

    DP_OUT(base, DP_ISR, DP_ISR_RDC);  /* Clear end of DMA */
    {
        /* Dummy read. The manual sez something slightly different, */
        /* but the code is extended a bit to do what Hitachi's monitor */
        /* does (i.e., also read data). */
/*    //屏蔽无用的语句
        cyg_uint16 tmp;
        int len = 1;

        DP_OUT(base, DP_RSAL, 0x100-len);
        DP_OUT(base, DP_RSAH, (start_page-1) & 0xff);
        DP_OUT(base, DP_RBCL, len);
        DP_OUT(base, DP_RBCH, 0);
        DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
        DP_IN_DATA(dp->data, tmp);
*/    }

......

#if DEBUG & 4
    printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len);
    dx = 0;
#endif
    while (len > 1) {
#if DEBUG & 4
        printf(" %04x", *data);
        if (0 == (++dx % 16)) printf("\n ");
#endif
        DP_OUT_DATA(dp->data, *data++);
        len-=2;
    }
#if DEBUG & 4
   
    if (len==1)     printf(" %04x", (*data)&0xff);
    printf("\n");
#endif
   
    if (len==1)     {DP_OUT_DATA(dp->data, (*data++)&0xff);    total_len++;    }

    if (total_len < pkt_len) {
#if DEBUG & 4
        printf("  + %d bytes of padding\n", pkt_len - total_len);
#endif
        /* Padding to 802.3 length was required */
        for (i = total_len;  i < pkt_len;) {
           
i+=2;
            DP_OUT_DATA(dp->data, 0);
        }
    }

......
}

/*
  This function is called when a packet has been received.  It's job is
  to prepare to unload the packet from the hardware.  Once the length of
  the packet is known, the upper layer of the driver can be told.  When
  the upper layer is ready to unload the packet, the internal function
  'dp83902a_recv' will be called to actually fetch it from the hardware.
*/
static void
dp83902a_RxEvent(void)
{
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
    cyg_uint8 *base = dp->base;
    unsigned char rsr;
    unsigned short rcv_hdr[2];
    int i, len, pkt, cur;
......
        DP_OUT(base, DP_RBCL, 4);
        DP_OUT(base, DP_RBCH, 0);
        DP_OUT(base, DP_RSAL, 0);
        DP_OUT(base, DP_RSAH, pkt);
        if (dp->rx_next == pkt) {
            if (cur == dp->rx_buf_start)
                DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
            else
                DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */
            return;
        }
        dp->rx_next = pkt;
        DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
        DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
        CYGACC_CALL_IF_DELAY_US(10);
#endif

        for (i = 0;  i < sizeof(rcv_hdr);) {
            DP_IN_DATA(dp->data, rcv_hdr[i++]);
        }

#if DEBUG & 5
        printf("rx hdr %04x %04x \n",
               rcv_hdr[0], rcv_hdr[1]);
#endif
        len = rcv_hdr[1] - 4;
        uboot_push_packet_len(len);
        if (((rcv_hdr[0] >>8)&0xff) == dp->rx_buf_start)
            DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
        else
            DP_OUT(base, DP_BNDRY, ((rcv_hdr[0] >>8)&0xff)-1); /* Update pointer */
    }
}

/*
  This function is called as a result of the "eth_drv_recv()" call above.
  It's job is to actually fetch data for a packet from the hardware once
  memory buffers have been allocated for the packet.  Note that the buffers
  may come in pieces, using a scatter-gather list.  This allows for more
  efficient processing in the upper layers of the stack.
*/
static void
dp83902a_recv(unsigned short *data, int len)
{
    ......

    /* Read incoming packet data */
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
    DP_OUT(base, DP_RBCL, len & 0xFF);
    DP_OUT(base, DP_RBCH, (len >> 8)& 0xFF);
    DP_OUT(base, DP_RSAL, 4);        /* Past header */
    DP_OUT(base, DP_RSAH, dp->rx_next);
    DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
    DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
    CYGACC_CALL_IF_DELAY_US(10);
#endif

    saved = false;
    for (i = 0;  i < 1;  i++) {
        if (data) {
            mlen = len;
#if DEBUG & 4
            printf(" sg buf %08lx len %08x \n", (unsigned long) data, mlen);
            dx = 0;
#endif
            while (0 < mlen) {
                /* Saved byte from previous loop? */
                if (saved) {
                    *data++ = saved_char;
                    mlen--;
                    saved = false;
                    continue;
                }

                {
                    cyg_uint16 tmp;
                    DP_IN_DATA(dp->data, tmp);
#if DEBUG & 4
                    printf(" %04x", tmp);
                    if (0 == (++dx % 16)) printf("\n ");
#endif
                    *data++ = tmp;
                    mlen-=2;
                    if (mlen==1) {
                            DP_IN_DATA(dp->data, tmp);
                            tmp = tmp & 0xff;
#if DEBUG & 4
                            printf(" %04x", tmp);
#endif
                            *data++ = tmp;
                            mlen--;
                            }
                }
            }
#if DEBUG & 4
            printf("\n");
#endif
        }
    }
}

......
//添加自定义的AX88796硬件信息,在这里定义了如果网卡的MAC地址的前三个为

//0x08, 0x08, 0x08,那就是AX88796。如果你要修改MAC地址 ,
//最好前三个要和这三个一样,不然驱动会认不到网卡。

static hw_info_t hw_info[] = {
 ......
    { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
    { /* AX88796 */ 0x0ff0, 0x08, 0x08, 0x08, 0 },
    { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
......
};

......

static void pcnet_reset_8390(void)
{
    int i, r;

    PRINTK("nic base is %lx\n", nic_base);

#if 1
    n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
    PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
    n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
    PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
    n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
    PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
#endif
    n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);

    n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET);  
//低级错误,严重的BUG,没有修改无法实现网卡的热复位,晕死。


    for (i = 0; i < 100; i++) {
        if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
            break;
        PRINTK("got %x in reset\n", r);
        my_udelay(100);
    }
    n2k_outb(0xff, EN0_ISR); /* Ack intr. */

    if (i == 100)
        printf("pcnet_reset_8390() did not complete.\n");
} /* pcnet_reset_8390 */

static hw_info_t * get_prom(void ) {
    unsigned char prom[32];
    char ethaddr[20];    //tekkaman
    int i, j, tekkaman;    //tekkaman
    unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman

    ......

    pcnet_reset_8390();

    mdelay(10);

    for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
        n2k_outb(program_seq[i].value, program_seq[i].offset);

    tekkaman=ne2000_read_mac_addr(prom);
    if (tekkaman)    {
        printf("ethaddr in nand is not found ,loading ne_defethaddr:");
        for (i = 0; i < 12; i++) {
            prom[i] = ne_defethaddr[i/2];
            printf(" %02x", prom[i]);
        }
    }
    prom[28] = prom[30] = 0x57;

    PRINTK("\n");
    for (i = 0; i < NR_INFO; i++) {
        if ((prom[0] == hw_info[i].a0) &&
            (prom[2] == hw_info[i].a1) &&
            (prom[4] == hw_info[i].a2)) {
            PRINTK("matched board %d\n", i);
            break;
        }
    }
    if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
        for (j = 0; j < 6; j++)
            dev_addr[j] = prom[j<<1];
        PRINTK("on exit i is %d/%ld\n", i, NR_INFO);
        PRINTK("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n",
               dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]);
        return (i < NR_INFO) ? hw_info+i : &default_info;
   
        if (tekkaman) {
        sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
         dev_addr[0], dev_addr[1],
         dev_addr[2], dev_addr[3],
         dev_addr[4], dev_addr[5]) ;
        printf("Set environment from HW MAC addr = \"%s\"\n", ethaddr);
        setenv ("ethaddr", ethaddr);
        }
    }
    return NULL;
}

/* U-boot specific routines */

#define NB 5

static unsigned short *pbuf = NULL;
static int plen[NB];
static int nrx = 0;

static int pkey = -1;

void uboot_push_packet_len(int len) {
    PRINTK("pushed len = %d, nrx = %d\n", len, nrx);
    if (len>=2000) {
        printf("NE2000: packet too big\n");
        return;
    }
    if (nrx >= NB) {
        printf("losing packets in rx\n");
        return;
    }
    plen[nrx] = len;
    dp83902a_recv(&pbuf[nrx*1000], len);
    nrx++;
}

void uboot_push_tx_done(int key, int val) {
    PRINTK("pushed key = %d\n", key);
    pkey = key;
}

int eth_init(bd_t *bd) {
    static hw_info_t * r;
//    char ethaddr[20];

    PRINTK("### eth_init\n");

    if (!pbuf) {
        pbuf = malloc(NB*1000);
        if (!pbuf) {
            printf("Cannot allocate rx buffers\n");
            return -1;
        }
    }

#ifdef CONFIG_DRIVER_NE2000_CCR
    {
        volatile unsigned char *p =  (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR;

        PRINTK("CCR before is %x\n", *p);
        *p = CONFIG_DRIVER_NE2000_VAL;
        PRINTK("CCR after is %x\n", *p);
    }
#endif

    nic_base = CONFIG_DRIVER_NE2000_BASE;
    nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE;

    r = get_prom();
    if (!r)
        return -1;
/*//屏蔽无用的语句
    sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
         dev_addr[0], dev_addr[1],
         dev_addr[2], dev_addr[3],
         dev_addr[4], dev_addr[5]) ;
   PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr);
    setenv ("ethaddr", ethaddr);
*/

#define DP_DATA        0x10
    nic.data = (unsigned short *) (nic.base + DP_DATA);
    nic.tx_buf1 = 0x40;
    nic.tx_buf2 = 0x46;
    nic.rx_buf_start = 0x4C;
    nic.rx_buf_end = 0x80;
   
    dp83902a_start(dev_addr);
    if (dp83902a_init() == false)
        return -1;
    return 0;
}

void eth_halt() {

    PRINTK("### eth_halt\n");

    dp83902a_stop();
}

int eth_rx() {
    int j, tmo;
    volatile uchar * inpkt
    PRINTK("### eth_rx\n");

    tmo = get_timer (0) + TOUT * CFG_HZ;
   
    while(1) {
        dp83902a_poll();
        if (nrx > 0) {
            for(j=0; j                inpkt = (uchar *) &pbuf[j*1000];


                NetReceive(inpkt, plen[j]);//这句的作用就是将接收到的数据

                                           //送到MAC层以上的协议层
            }
            nrx = 0;
            return 1;
        }
        if (get_timer (0) >= tmo) {
            printf("timeout during rx\n");
            return 0;
        }
    }
    return 0;
}

int eth_send(volatile void *packet, int length) {
    int tmo;

    PRINTK("### eth_send\n");

    pkey = -1;

    dp83902a_send((unsigned short *) packet, length, 666);
    tmo = get_timer (0) + TOUT * CFG_HZ;
    while(1) {
        dp83902a_poll();
        if (pkey != -1) {
            PRINTK("Packet sucesfully sent\n");
            return 0;
        }
        if (get_timer (0) >= tmo) {
            printf("transmission error (timoeut)\n");
            return 0;
        }

    }
    return 0;
}

#endif

ne2000.c修改完毕




 (2)修改ne2000.h
NE2000驱动的低级错误
第45行:
 at */

改为:
 at

就是去掉“*/”   ,   真是TNND汗死!!!!


......

#define DP_IN(_b_, _o_, _d_)  (_d_) = *( (volatile unsigned char *) ((_b_)+(_o_)))
#define DP_OUT(_b_, _o_, _d_) *( (volatile unsigned char *) ((_b_)+(_o_))) = ((unsigned char) (_d_))

#define DP_IN_DATA(_b_, _d_)  (_d_) = *( (volatile unsigned short *) ((_b_)))
#define DP_OUT_DATA(_b_, _d_) *( (volatile unsigned short *) ((_b_))) = ((unsigned short) (_d_))


/* here is all the data */

#define cyg_uint8 unsigned char
#define cyg_uint16 unsigned short
#define bool int

#define false 0
#define true 1

#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 1
#define CYGACC_CALL_IF_DELAY_US(X) my_udelay(X)

typedef struct dp83902a_priv_data {
    cyg_uint8* base;
    cyg_uint16* data;
    cyg_uint8* reset;
    int tx_next;           /* First free Tx page */
    int tx_int;            /* Expecting interrupt from this buffer */
    int rx_next;           /* First free Rx page */
    int tx1, tx2;          /* Page numbers for Tx buffers */
    unsigned long tx1_key, tx2_key;   /* Used to ack when packet sent */
    int tx1_len, tx2_len;
    bool tx_started, running, hardwired_esa;
    cyg_uint8 esa[6];
    void* plf_priv;

    /* Buffer allocation */
    int tx_buf1, tx_buf2;
    int rx_buf_start, rx_buf_end;
} dp83902a_priv_data_t;

......



(3)修改8390.h

......
/*
 *    Only generate indirect loads given a machine that needs them.
 *      - removed AMIGA_PCMCIA from this list, handled as ISA io now
 */

#define n2k_inb(port)   (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)))
#define n2k_outb(val,port)  (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)) = ((unsigned char) val))

#define EI_SHIFT(x)    (x)
......




网卡驱动程序的修改到此结束,以下是总线参数的修改:

修改/board/tekkaman/tekkaman2410/lowlevel_init.S文件(参数都是参考 刘淼 的书):

#define B1_BWSCON    (DW16) 
#define B2_BWSCON    (DW16 + UBLB)
#define B3_BWSCON    (DW16) 

......

#define B2_Tacs    0x3 /*  4clk tekkaman*/
#define B2_Tcos    0x3 /*  4clk tekkaman*/

#define B2_Tacc    0x7 /*  14clk */
#define B2_Tcoh    0x3 /*  4clk tekkaman*/
#define B2_Tah    0x3 /*  4clk tekkaman*/
#define B2_Tacp    0x3 /*  6clk tekkaman*/

#define B2_PMC    0x0 /* normal */

......


在/include/configs/tekkaman2410.h文件中加上AX88796网卡驱动的信息:
/*
 * Hardware drivers
 */
//#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
//#define CS8900_BASE  0x19000300
//#define CS8900_BUS16  1 /* the Linux driver does accesses as shorts */
#define CONFIG_DRIVER_NE2000  1
#define CONFIG_DRIVER_NE2000_BASE (0x10000000+0x200)



U-Boot下的AX88796移植结束了,我有复查过,应该在编译网卡驱动的时候连警告都不会有,所以如果您遇到了问题,在检查是否按照上面步骤移植后,还不能解决,可以联系我,QQ:78027228。不过我建议:最好是在看过我介绍的资料后再来移植,出了问题你自己就可以解决了。下一步的目标是U-Boot和Linux下的LCD驱动。以下附上我启动时和运行的输出信息(请注意U-Boot环境变量的设定):

U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)

U-Boot code: 33F80000 -> 33F98BC0  BSS: -> 33F9D3C0
DRAM:  64 MB
NAND:    64 MB
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0
[Tekkaman2410]# printenv
bootdelay=3
baudrate=115200
ethaddr=08:08:08:08:12:27
netmask=255.255.255.0
bootfile=zImage.img
loadaddr=0x30008000
bootargs=root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs ip=192.168.1.2:192.168.1.22::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M
bootcmd=tftp;bootm
ipaddr=192.168.1.2
serverip=192.168.1.22
stdin=serial
stdout=serial
stderr=serial

Environment size: 382/65532 bytes


U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)

U-Boot code: 33F80000 -> 33F98BC0  BSS: -> 33F9D3C0
DRAM:  64 MB
NAND:    64 MB
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0
### eth_init
matched board 31
AX88796 - tekkmana ESA: 08:08:08:08:12:27
TFTP from server 192.168.1.22; our IP address is 192.168.1.2
Filename 'zImage.img'.
Load address: 0x30008000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #############
done
Bytes transferred = 1727136 (1a5aa0 hex)
## Booting image at 30008000 ...
   Image Name:   tekkamanninja
   Created:      2007-09-25   9:28:11 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1727072 Bytes =  1.6 MB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK

Starting kernel ...

Uncompressing Linux................................................................................................................ done, booting the kernel.
Linux version 2.6.22.2 () (gcc version 4.1.0) #5 Tue Sep 25 15:43:11 CST 2007
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
Machine: Tekkaman2410
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410A (id 0x32410002)
S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists.  Total pages: 16256
Kernel command line: root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs ip=192.168.1.2:192.168.1.22::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M
irq: clearing pending ext status 00000100
irq: clearing subpending status 00000002
(以下略)


主机Host的tftp服务:
    在Linux下运行tftp服务,你可以参考《 嵌入式linux下的tftp开发环境建立 》,很不错。我没找到原文地址,在这里发两个链接:

 
    你如果想在Windows下开发(不推荐),你可以使用tftpd32.exe,官方下载网页:
阅读(2222) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~