Uboot Ping指令导致data abort重启

报错内容

=> ping 192.168.110.111
FEC1 Waiting for PHY auto negotiation to complete.... done
Using FEC1 device
data abort
pc : [<9ff910e8>]          lr : [<9ff923b8>]
reloc pc : [<8783a0e8>]    lr : [<8783b3b8>]
sp : 9ef54d08  ip : 00000000     fp : 9ff61b78
r10: 00000002  r9 : 9ef54eb8     r8 : 00000000
r7 : 00000001  r6 : 00000000     r5 : 0000002a  r4 : 9ffed68e
r3 : 14000045  r2 : 706ea8c0     r1 : 6f6ea8c0  r0 : 9ffed68e
Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
Resetting CPU ...

resetting ...

可以看到是运行到8783a0e8这一行出错的,使用addr2line找出错误的代码:

arm-linux-gnueabihf-addr2line -e u-boot 0x8783a0e8

对应的代码为

void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source)
{
	struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt;

	/*
	 *	Construct an IP header.
	 */
	/* IP_HDR_SIZE / 4 (not including UDP) */
	ip->ip_hl_v  = 0x45;
	ip->ip_tos   = 0;
	ip->ip_len   = htons(IP_HDR_SIZE);
	ip->ip_id    = htons(net_ip_id++);
	ip->ip_off   = htons(IP_FLAGS_DFRAG);	/* Don't fragment */
	ip->ip_ttl   = 255;
	ip->ip_sum   = 0;
	/* already in network byte order */
	net_copy_ip((void *)&ip->ip_src, &source);
	/* already in network byte order */
	net_copy_ip((void *)&ip->ip_dst, &dest);
}

看起来好像没啥问题,问了下 AI,发现是因为数据包的地址不符合arm的地址对齐规则,在正点原子论坛里也有人提到了这一点,可以通过降低编译器版本和修改源码的方式解决,我采用的是修改源码,将arch/arm/cpu/armv7/start.S中的第130行修改为

orr r0, r0, #0x00000000 @ set bit 1 (--A-) Align	/* 原本为0x00000002 */

重新编译后就解决了