Chinaunix首页 | 论坛 | 博客
  • 博客访问: 157025
  • 博文数量: 152
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-08 15:46
文章分类

全部博文(152)

文章存档

2016年(152)

我的朋友

分类: LINUX

2016-06-02 14:13:51

移植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,官方下载网页:
阅读(954) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~