348|0

55

帖子

1

TA的资源

一粒金砂(中级)

【microchip PolarFire SoC FPGA 套件】PolarFire SoC FPGA 开发套件网络功能的尝试 [复制链接]

 

一、前期尝试:FPGA手工开发与IP核选用困境

最初,考虑直接使用FPGA进行以太网接口测试开发。然而,纯手工编写代码实现测试功能面临诸多挑战,开发周期长且容易出错,代码的复杂性和调试难度使得这一方案性价比极低。因此,转向使用官方提供的IP核,期望借此简化开发流程。
在众多IP核中,有CoreRMII、CoreTSE、CoreTSE_AHB、Core10100和CoreTCAM这五个模块可供选择。对这五个IP核的详细对比如下:
IP核名称 功能特点 优势 局限 适用场景
CoreRMII 负责MII到RMII的转换,减少连接PHY和MAC的信号数量;支持10/100Mbps模式,MII侧25MHz、RMII侧50MHz时钟;提供MDIO接口控制链路速度、传输类型和环回功能 资源占用低,在SmartFusion2、IGLOO2、PolarFire等器件系列中,逻辑元件使用数量少 功能单一,专注于接口转换,不支持1000Mbps高速传输模式 对接口转换需求简单,速率要求不高于100Mbps,且对资源占用敏感的场景
CoreTSE 提供10/100/1000Mbps以太网MAC功能,支持G/MII或SGMIITBI接口;支持全双工和半双工模式,具备WoL功能、帧统计计数器和目的地址过滤功能 功能丰富,能满足多种以太网应用需求;支持高速传输,适用于对网络功能要求较高的场景 资源占用相对较高;配置和使用复杂,对开发者技术要求高 对功能完整性和高速传输有要求,资源相对充足的项目,如工业控制、数据中心网络设备等
CoreTSE_AHB 提供10/100/1000Mbps以太网MAC功能,支持G/MII和TBI接口;通过AMBAAHB-发起端口接口,允许DMA引擎进行数据传输,提高效率 通过AHB接口实现高效数据传输和系统集成;在数据传输方面具有优势 硬件连接和软件配置复杂,开发难度大 对数据传输效率要求高,需要与AHB总线紧密集成的系统,如高性能计算设备的网络模块
Core10100 推测主要针对10/100Mbps以太网应用场景设计优化 在资源占用和成本控制上或许有优势 功能丰富度和高速传输支持较弱;缺乏详细资料,实际性能和功能特点难以准确评估 对成本敏感,对功能需求相对简单,速率要求不高于100Mbps的场景,如一些低成本物联网设备
CoreTCAM 推测与内容可寻址存储器(TCAM)技术相关,可能在地址查找、数据包过滤方面有独特优势 在需要快速进行地址匹配和数据过滤的场景中表现出色 缺乏详细资料,功能细节和性能表现难以明确 对地址查找和数据包过滤速度要求极高的特定网络应用,如网络安全设备中的数据包筛选模块
综合考虑项目需求,包括对多种网络环境的适应性、大数据传输的稳定性以及开发效率,最终选择了CoreTSE。尽管其资源占用较大,但全面的功能能更好地满足不同网络环境下的测试需求,且后续可通过优化资源配置来缓解资源压力。
在使用CoreTSE的过程中,却遇到了新的问题。下载过程极为缓慢,频繁出现卡死现象,严重影响开发进度。经过排查,发现是由于IP核数据量较大,在下载过程中与开发环境存在兼容性问题(我的电脑性能不足或者网络原因?)。
wd_002950hltjpg9pqtlxrr4l.png
这里的配置就按照默认的就可以了。
wd_002950k9cdnxxx1qz5fxnf.png
好不容易完成下载,又出现引脚太少无法满足测试需求的状况,这使得基于该IP核的测试方案难以继续推进。
wd_002951hsted3ymme7t7xri.png

二、新的探索:参考视频流传输方案

在困境中,通过仔细研读PolarFireSoCFPGA相关手册,发现其中的视频流传输方案可能为以太网接口测试提供新的思路。视频流传输同样涉及大量数据在网络中的传输,与以太网接口测试在数据传输特性上有一定相似性。
在困境中,通过仔细研读PolarFireSoCFPGA相关手册,发现其中的视频流传输方案可能为以太网接口测试提供新的思路。视频流传输同样涉及大量数据在网络中的传输,与以太网接口测试在数据传输特性上有一定相似性。
从《PolarFir eSoCFPGAH.264 Video Streamin g Over Ethernet Application Note AN4529》文档可知,视频流传输方案利用了一系列IP块,如PolarFireOscillator、PolarFire ClockConditioning Circuit(CCC)等协同工作。其中,网络通信部分的设计对以太网接口测试有重要参考价值。在时钟管理方面,通过合理配置PolarFireCCC块,利用148.5MHz的板载参考时钟生成125MHz的织物时钟,为FPGA与MSS(Microprocessor Subsystem)之间的通信提供稳定时钟信号。这在以太网接口测试中也至关重要,稳定的时钟是保证数据准确传输、测试通信稳定性和速率的基础。
同时,该方案中的数据传输路径设计,如从摄像头获取数据后经一系列处理再通过以太网发送,为测试数据的传输提供了可借鉴的流程。在测试以太网接口时,也需要构建类似的数据传输链路,将测试数据准确发送并接收,以分析丢包率等指标。
基于此,确定了工程结构。在硬件层面,以PolarFireSoC FPGA为核心,连接以太网接口模块,确保数据的输入输出稳定。在软件层面,参考视频流传输方案中的驱动和配置代码,构建测试数据的生成、发送和接收逻辑。
需要添加的代码主要集中在测试数据的生成函数、数据发送与接收的控制逻辑以及丢包率和传输速率计算的函数。
例如,编写专门的函数用于生成不同大小和格式的测试数据包,模拟大数据传输场景;在数据发送端,根据不同网络环境的模拟需求,添加控制数据包发送频率和数量的代码;在接收端,增加对接收数据的校验和计数功能,以便准确计算丢包率。同时,结合时钟配置代码,确保数据在不同网络环境下能稳定传输。
wd_002951qxrujtx1bfzb8zfr.png
参考里面的mpfs-mac-mcc-stack项目和mpfs-mac-simple-test-multi-emac项目
在mpfs-mac-mcc-stack项目中,包含了BACnet协议相关的测试函数,BACnet是一种用于楼宇自动化和控制网络的通信协议,在以太网通信测试中可能会涉及到一些通用的网络通信功能。
比如在src/middleware/bacnet/src/npdu.c文件,包含了testNPDU1和testNPDU2函数,这些函数用于测试网络协议数据单元(NPDU)的编码和解码功能,涉及到以太网通信中的数据包处理。
有兴趣的可以在工程里面看一下testNPDU1和testNPDU2两函数。
而位于src/middleware/bacnet/src/ptransfer.c,代码包含了test_Private_Transfer_Request和test_Private_Transfer_Ack函数,用于测试私有传输请求和响应的编码和解码,有助于理解以太网通信中的消息交互。
最后是文件src/middleware/bacnet/src/mstp.c,它包含了testReceiveNodeFSM函数,用于测试MSTP(主从/令牌传递)网络的接收节点有限状态机,对于理解以太网通信中的状态管理和数据包接收处理有帮助。
PPP协议参考driver-examples/mss/mss-ethernet-mac/mpfs-uart-mac-freertos_lwip/src/middleware/lwip-2.0.0-wip/netif/ppp/ppp.c。
数据传输参考:applications/benchmarks/dma_benchmarking/mpfs-dma-benchmarking/src/application_pdma/hart1/pdma_benchmarking_config.h。定义了 DMA(直接内存访问)基准测试的配置,包括传输大小范围、内存地址等。虽然这主要是关于 DMA 的配置,但在大数据传输速率测试中,DMA 可以用于高效的数据传输。
进行一个简单的功能代码的编写:
#define BUFFER_SIZE 1024
#define PORT 8888
#define SERVER_IP "192.168.68.74"
#define PACKET_COUNT 1000
typedef struct {
uint8_t protocol_version;
bool data_expecting_reply;
bool network_layer_message;
BACNET_MESSAGE_PRIORITY priority;
BACNET_NETWORK_MESSAGE_TYPE network_message_type;
uint16_t vendor_id;
uint8_t hop_count;} BACNET_NPDU_DATA;
void npdu_copy_data(BACNET_NPDU_DATA * dest, BACNET_NPDU_DATA * src) {
if (dest && src) {
dest->protocol_version = src->protocol_version;
dest->data_expecting_reply = src->data_expecting_reply;
dest->network_layer_message = src->network_layer_message;
dest->priority = src->priority;
dest->network_message_type = src->network_message_type;
dest->vendor_id = src->vendor_id;
dest->hop_count = src->hop_count;
}}
int send() {
int sockfd;
struct sockaddr_in server_addr;
uint8_t buffer[1024];
Packet packet;
int i;
clock_t start_time, end_time;
double total_time;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
start_time = clock();
for (i = 0; i < PACKET_COUNT; i++) {
packet.packet_id = i;
packet.timestamp = (uint64_t)time(NULL);
snprintf((char *)packet.data, sizeof(packet.data), "Packet %d", i);
packet.data_length = strlen((char *)packet.data);
int encoded_length = encode_packet(buffer, &packet);
sendto(sockfd, buffer, encoded_length, 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
usleep(1000);
}
end_time = clock();
total_time = (double)(end_time - start_time) / CLOCKS_PER_SEC;
printf("Sent %d packets in %.2f seconds.\n", PACKET_COUNT, total_time);
close(sockfd);
return 0;
}
#define BUFFER_SIZE 1024
#define PORT 8888
int receive() {
int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len = sizeof(client_addr);
uint8_t buffer[1024];
Packet packet;
int packet_count = 0;
int received_count = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind failed");
return -1;
}
while (1) {
ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_addr_len);
if (recv_len > 0) {
decode_packet(buffer, &packet);
received_count++;
printf("Received packet %d at %lu: %s\n", packet.packet_id, packet.timestamp, packet.data);
if (packet.packet_id == MAX_PACKET_ID) {
break;
}
}
}
int lost_count = MAX_PACKET_ID - received_count + 1;
float loss_rate = (float)lost_count / (MAX_PACKET_ID + 1) * 100;
printf("Received %d packets, lost %d packets, loss rate: %.2f%%\n", received_count, lost_count, loss_rate);
close(sockfd);
return 0;}
int encode_packet(uint8_t * buffer, Packet * packet) {
uint8_t * ptr = buffer;
*(uint32_t *)ptr = packet->packet_id;
ptr += sizeof(uint32_t);
*(uint64_t *)ptr = packet->timestamp;
ptr += sizeof(uint64_t);
*(uint16_t *)ptr = packet->data_length;
ptr += sizeof(uint16_t);
for (int i = 0; i < packet->data_length; i++) {
*ptr++ = packet->data;
}
return ptr - buffer;
}
int decode_packet(uint8_t * buffer, Packet * packet) {
uint8_t * ptr = buffer;
packet->packet_id = *(uint32_t *)ptr;
ptr += sizeof(uint32_t);
packet->timestamp = *(uint64_t *)ptr;
ptr += sizeof(uint64_t);
packet->data_length = *(uint16_t *)ptr;
ptr += sizeof(uint16_t);
for (int i = 0; i < packet->data_length; i++) {
packet->data = *ptr++;
}
return ptr - buffer;
}
  1. 模拟测试结果与分析
wd_002951k72qa7jqhcpfgjjo.jpg
wd_002951l8k8uvfrvm8l8v88.png
wd_002951ozpyi316sy914dxx.png
wd_002951r96a4oddnoo4sygg.png
wd_002951xnr5pptoonygrofq.png
对以太网接口进行模拟测试。在不同网络环境下,包括不同带宽、不同干扰强度的模拟场景中,测试结果显示:在理想网络环境下,即高带宽且低干扰的场景中,以太网接口的通信稳定性良好,丢包率低于1%,大数据传输速率可达到接近理论最大值。

此帖出自FPGA/CPLD论坛

回复
举报
您需要登录后才可以回帖 登录 | 注册

开源项目 更多>>
    随便看看
    查找数据手册?

    EEWorld Datasheet 技术支持

    相关文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

     
    EEWorld订阅号

     
    EEWorld服务号

     
    汽车开发圈

     
    机器人开发圈

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 5

    北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表