用户名: 密码: 忘记密码? 注册

Arm开发板实验(4)---- uboot网络设备启动

作者:  时间: 2010-09-05
Chapter 8:uboot网络启动

调试uboot时,如果从头开始时见很麻烦的事,每次都要通过并口线把uboot下载到板子中。购买的开发板中,一般都自带uboot镜像,我们可以使用它简化开发流程。


1 修改uboot运行地址

修改board/smdk2440/config.mk中的TEXT_BASE。SDRAM内存为64M,地址范围为0x3000,0000 ~ 0x33ff,ffff。Uboot的默认加载地址为0x33f8,0000,我们的uboot要绕开这一块,加载到0x32f8,0000。前32M我们留给linux内核使用。

Uboot代码段起始地址在编译时通过“-Ttext $(TEXT_BASE)”指定,我们前面已经把这一地址指定为了0x32f8,0000。

在链接脚本u-boot.lds中,有下面的指令:

      . = 0x00000000;

      . = ALIGN(4);

      .text      :

      {

        cpu/arm920t/start.o       (.text)

        *(.text)

      }

这段脚本会吧start.o作为第一个文件链接,也就是实现了把_start函数放到text开头的作用。修改后的脚本如下:

      . = 0x30000000;

 

      . = ALIGN(4);

      .text      :

      {

        cpu/arm920t/start.o       (.text)

        *(.text)

      }

下载地址是uboot在bootm中下载版本后存放的位置。程序中的下载地址在include/configs/smdk2440.h中通过变量CFG_LOAD_ADDR设置。这里把下载地址修改为0x3200,0000,不改也没有关系。


2 如何通过flash中的uboot启动

首先要编译出uboot.bin文件。

真正的uboot是通过并口直接下载到flash上,也就是0x0地址。然后再start.s中把代码段从flash拷贝到内存中。但我们的uboot是通过uboot下载的,所以可以直接放到指定的内存中,省去中间的拷贝。

这种直接加载到内存中启动boot的方式下,start.s中的很多初始化都不能使用,需要把入口处的“b reset”指令改为“b stack_setup”,也就是说stack_setup前面的所有初始化都不做。猜测可能是因为之前的初始化都是在rom上对ram的初始化,但现象很诡异。


3 修改uboot的一些设置

首先是修改命令提示符:include/configs/smdk2440.h中的CFG_PROMT。这里我改为了”HQ_2440 >”。然后要在同一个文件中修改ip地址信息:

#define CONFIG_IPADDR         192.168.1.168

#define CONFIG_SERVERIP     192.168.1.200

启动boot后,会打印:*** Warning - bad CRC, using default environment\。这是在env_relocate中提示的,为了调试方便,这里要打开调试信息的打印。修改common/Env_common.c中的DEBUG_ENV的定义来打开调试信息。


4 网口芯片DM9000驱动

Arm开发板实验(5)---- uboot网络设备启动 - HQ - HQ的星空

 网口芯片DM9000的片选nCS接在CPU的nGCS3上,也就是在在BANK3上,所以基址为0x1800,0000。

CMD管脚为0时为INDEX端口,此时数据线输入的是寄存器地址;CMD管脚为1时为DATA端口,此时数据线输入的是刚才指定的寄存器的数据。每个寄存器都要通过两个命令周期才能完成设置。CMD引脚接在地址线LADDR2上。综上,只有最高两个 字节与第二跟地址线有效,其他可以随意设置。(arm是Little-Endian)

#define CONFIG_DRIVER_DM9000  1

#define CONFIG_DM9000_BASE  0x18000000

#define DM9000_IO   CONFIG_DM9000_BASE

#define DM9000_DATA   (CONFIG_DM9000_BASE+4)

#define CONFIG_DM9000_USE_16BIT

 

完成上面的配置后,编译出uboot测试结果为:

HQ_2440 -> tftp 0x30000000 t1

dm9000 i/o: 0x18000000, id: 0x90000a46

MAC: 00:80:00:80:00:80

could not establish link

TFTP from server 192.168.1.200; our IP address is 192.168.1.168

Filename 't1'.

Load address: 0x30000000

Loading: rx fifo error

rx crc error

网口驱动加载了,但是不通。

根据网上的文章,做如下修改:

(1)网卡MAC地址错误的解决方法:

/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
    ......
//tekkamanninja
    /* Set Node address */
/*    for (i = 0; i < 6; i++)
        ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
    if (is_zero_ether_addr(bd->bi_enetaddr) ||
     is_multicast_ether_addr(bd->bi_enetaddr)) {
*/
        /* try reading from environment */
//        u8 i;
        char *s, *e;
        s = getenv ("ethaddr");
        for (i = 0; i < 6; ++i) {
            bd->bi_enetaddr[i] = s ?
                simple_strtoul (s, &e, 16) : 0;
            if (s)
                s = (*e) ? e + 1 : e;
        }
//    }
//tekkamanninja
    printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
           bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
           bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
......

 

红色的字符是要做的修改:功能是屏蔽原有获取MAC地址的语句,直接使用从U-Boot的参数区读取数据并存到bd->bi_enetaddr[i]中。

 

(2)“could not establish link” 提示和慢响应的解决方法:

/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
    ......
    DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */
    DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */
#if 0
    i = 0;
    while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
        udelay(1000);
        i++;
        if (i == 10000) {
            printf("could not establish link\n");
            return 0;
        }
        printf(" link=%d\n",i);
    }
#endif
......
}

屏蔽检测和延时的语句。

 

重新启动uboot,用tftp 0x30000000 t1下载文件t1,出现下面的异常。

Load address: 0x30000000

Loading: undefined instruction

pc : [<20647058>]    lr : [<32f8a514>]

sp : 32f4f9ec  ip : 00000006  fp : 32f4fdfa

r10: 32f97444  r9 : 32f97268  r8 : 32f4ffdc

r7 : 32f97428  r6 : 32f97ae0  r5 : 00006e65  r4 : 32f4f9f0

r3 : 32f936f0  r2 : 00000001  r1 : 32f4f9f0  r0 : 32f4f9f0

Flags: Nzcv  IRQs off  FIQs off  Mode SVC_32

Resetting CPU ...

 

查看资料后发现原因是uboot自带的是DM9000的驱动,而smdk2440带的是DM9000A的芯片,所以需要做如下改动:

在eth_rx中添加do while循环

eth_rx(void)

{

      u8 rxbyte, *rdptr;

      u16 RxStatus, RxLen;

      u32 tmplen, i;

#ifdef CONFIG_DM9000_USE_32BIT

      u32 tmpdata;

#endif

 

  DM9000_ior(DM9000_MRRH);

  DM9000_ior(DM9000_MRRI);

  do {

   rdptr = (u8 *) NetRxPackets[0];

   RxLen = 0;

      /* Check packet ready or not */

      DM9000_ior(DM9000_MRCMDX);    /* Dummy read */

      rxbyte = DM9000_inb(DM9000_DATA);    /* Got most updated data */

      if (rxbyte == 0)

             return 0;

。。。。。。。。。。。。。

。。。。。。。。。。。。。

      } else {

 

             /* Pass to upper layer */

             DM9000_DBG("passing packet to upper layer\n");

             NetReceive(NetRxPackets[0], RxLen);

             return RxLen;

      }

  }

  while (rxbyte ==DM9000_PKT_RDY);

//    return 0;

  Return RxLen;

}

 

每次ping结束后都会进如eth_halt,关闭网络,可能导致传输问题,所以要屏蔽halt函数的内容。


5 Nand Flash

根据书上的提示,打开了nandflash的驱动,然后编译时就出现了下面的错误:

arm-linux-ld: ERROR: /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_divsi3.oS) uses hardware FP, whereas u-boot uses software FP
arm-linux-ld: failed to merge target specific data of file /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_divsi3.oS)
arm-linux-ld: ERROR: /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_modsi3.oS) uses hardware FP, whereas u-boot uses software FP
arm-linux-ld: failed to merge target specific data of file /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_modsi3.oS)
lib_arm/libarm.a(_udivsi3.o)(.text+0x8c):/root/Desktop/u-boot-1.1.4/lib_arm/_udivsi3.S:67: relocation truncated to fit: R_ARM_PLT32 __div0
lib_arm/libarm.a(_umodsi3.o)(.text+0xa8):/root/Desktop/u-boot-1.1.4/lib_arm/_umodsi3.S:79: relocation truncated to fit: R_ARM_PLT32 __div0
/usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_divsi3.oS)(.text+0x11c):/work/crosstool-0.27/build/arm-linux/gcc-3.4.1-glibc-2.3.2/gcc-3.4.1/gcc/config/arm/lib1funcs.asm:735: relocation truncated to fit: R_ARM_PLT32 __div0
/usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/libgcc.a(_modsi3.oS)(.text+0xd8):/work/crosstool-0.27/build/arm-linux/gcc-3.4.1-glibc-2.3.2/gcc-3.4.1/gcc/config/arm/lib1funcs.asm:795: relocation truncated to fit: R_ARM_PLT32 __div0
make: *** [u-boot] ERROR 1

 

从网上查了下,是编译器的问题,换了个gcc2.95版本,错误更多。研究gcc3.4.1编译的错误,发现是浮点数问题。Gcc3.4.1用的是硬浮点,不支持软浮点。在cpu/arm920t/config.mk中吧-msoft-float改为-mhard-float,编译后可以通过了。