对技术执着
分类: LINUX
2015-03-14 14:57:58
原文地址:Arm开发板实验(4)---- uboot网络设备启动 作者:fireaxe
调试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,不改也没有关系。
首先要编译出uboot.bin文件。
真正的uboot是通过并口直接下载到flash上,也就是0x0地址。然后再start.s中把代码段从flash拷贝到内存中。但我们的uboot是通过uboot下载的,所以可以直接放到指定的内存中,省去中间的拷贝。
这种直接加载到内存中启动boot的方式下,start.s中的很多初始化都不能使用,需要把入口处的“b reset”指令改为“b stack_setup”,也就是说stack_setup前面的所有初始化都不做。猜测可能是因为之前的初始化都是在rom上对ram的初始化,但现象很诡异。
首先是修改命令提示符: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的定义来打开调试信息。
网口芯片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 |
红色的字符是要做的修改:功能是屏蔽原有获取MAC地址的语句,直接使用从U-Boot的参数区读取数据并存到bd->bi_enetaddr[i]中。
(2)“could not establish link” 提示和慢响应的解决方法:
/* Initilize dm9000 board |
屏蔽检测和延时的语句。
重新启动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函数的内容。
根据书上的提示,打开了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 |
从网上查了下,是编译器的问题,换了个gcc2.95版本,错误更多。研究gcc3.4.1编译的错误,发现是浮点数问题。Gcc3.4.1用的是硬浮点,不支持软浮点。在cpu/arm920t/config.mk中吧-msoft-float改为-mhard-float,编译后可以通过了。