You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zedboard与Vivado环境下以太网传输字节序反转问题咨询

字节序不匹配导致的网络数据字节反转问题分析与解决

问题背景

你在Zedboard开发板上用Vivado 2017.3开发,基于lwIP的echo server读取PL端slv_reg0寄存器的数据,通过以太网发送到PC。gtkterm上能正常显示寄存器值(比如0x00000004到0x0000000E),但PC端收到的二进制数据却是字节反转的(比如04 00 00 00对应原本的0x00000004)。

问题根源:字节序(Endianness)不匹配

这个问题的核心是CPU端序和网络字节序的差异:

  • Zynq的ARM Cortex-A9内核采用小端序(Little-Endian):数据的低字节存储在内存的低地址,高字节存储在高地址。比如0x00000004在内存中会被存成04 00 00 00。
  • 网络传输遵循大端序(Big-Endian,即网络字节序):要求数据的高字节放在传输流的前面,也就是0x00000004应该被发送成00 00 00 04。

你现在的代码直接把内存中以小端序存储的unsigned long数组通过write发送到网络,没有做字节序转换,PC端接收后按大端序解析自然就出现了字节反转的现象。而gtkterm显示正常是因为xil_printf已经把二进制数据格式化成了字符串,字符串的字节顺序是和人类阅读习惯一致的,所以不会有问题。

可行的解决办法

1. 使用lwIP提供的标准字节序转换函数

lwIP内置了针对不同数据类型的字节序转换函数,最适合你的场景是htonl()(Host to Network Long),它能把主机端序(这里是小端)的32位整数转换成网络字节序(大端)。修改代码如下:

// 在准备发送前,逐个转换my_buffer中的元素
for(int j=0; j<11; j++){
    my_buffer[j] = htonl(my_buffer[j]);
}
// 再执行write发送
if ((nwrote = write(sd, my_buffer, sizeof (my_buffer))) < 0) {
    // ... 原有错误处理代码
}

如果PC端需要把收到的网络字节序数据转回主机端序(比如PC是x86架构,同样是小端),可以用ntohl()(Network to Host Long)来转换。

2. 手动实现字节反转函数

如果不想依赖lwIP的函数,也可以自己写一个32位整数的字节反转函数:

uint32_t reverse_32bit_bytes(uint32_t value) {
    return ((value >> 24) & 0x000000FF) |
           ((value >> 8)  & 0x0000FF00) |
           ((value << 8)  & 0x00FF0000) |
           ((value << 24) & 0xFF000000);
}

然后在发送前遍历my_buffer,对每个元素调用这个函数:

for(int j=0; j<11; j++){
    my_buffer[j] = reverse_32bit_bytes(my_buffer[j]);
}

3. 硬件端调整寄存器存储顺序(不推荐)

你也可以修改PL端的AXI外设设计,让寄存器的数据按大端序存储。但这种方式需要修改硬件逻辑,重新综合实现,相比软件转换成本更高,除非有特殊需求,否则不建议采用。

额外提示

在网络通信中,所有跨设备的二进制数据传输都应该遵循网络字节序的规范,避免出现类似的端序问题。如果后续扩展其他数据类型(比如16位整数),可以用htons()/ntohs()来处理。

内容的提问来源于stack exchange,提问作者upasana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:27:00