3. VxWorks网络驱动开发基础
在VxWorks网络协议栈中,网络驱动并不直接与IP层、TCP层耦合,而是通过END(Enhanced Network Driver)驱动模型接入MUX层。理解END模型、驱动注册与初始化、MUX与驱动之间的回调机制,以及收发数据路径和中断/轮询两种工作模式,是开发与调试VxWorks网络驱动的基础。
END驱动模型与MUX的分层关系
VxWorks网络栈自下而上大致分为三层:最底层是具体硬件对应的END驱动,中间是MUX(Multiplexer)层,上层是协议栈(IP、ARP、TCP、UDP等)。END驱动只负责“把帧发到网口”和“从网口收帧”,不关心帧里承载的是IP还是ARP。MUX层负责把驱动与协议绑定,并在驱动与协议之间转发数据包。
END驱动需要向MUX注册一个NET_FUNCS结构体,其中包含一组函数指针,最核心的是start、send、ioctl、stop等。MUX通过这组回调调用驱动,驱动则通过MUX提供的muxBind、muxSend、muxReceive等接口与MUX交互。这种“驱动注册函数表、MUX回调驱动”的机制,使协议栈与硬件驱动解耦。
驱动注册与初始化流程
END驱动的注册通常分两步:先muxDevLoad加载驱动,再muxDevStart启动驱动。以常见的以太网驱动为例,初始化代码大致如下:
/* 示例:END 驱动注册与启动 */
int myEndLoad(void)
{
int unit = 0;
/* 加载驱动,返回 END_OBJ 指针 */
pEnd = muxDevLoad(unit, myEndLoad, NULL, FALSE, NULL);
if (pEnd == NULL)
return ERROR;
/* 启动驱动,触发 start() 回调 */
if (muxDevStart(pEnd) != OK)
return ERROR;
return OK;
}
其中myEndLoad是驱动提供的加载函数,MUX在muxDevLoad时调用它,驱动在此完成硬件探测、DMA描述符环分配、中断连接等。随后muxDevStart会调用驱动NET_FUNCS中的start回调,使能收发。若使用ifconfig或ifShow能看到接口处于UP状态,说明注册与启动基本成功。
MUX与驱动间的回调机制
MUX与驱动之间的交互是双向的。MUX调用驱动的send发送帧,调用ioctl查询或设置参数(如MAC地址、MTU、混杂模式),调用start/stop控制启停。驱动收到帧后,通过muxReceive把帧交给MUX,由MUX根据协议类型分发给上层。驱动还可以通过muxError上报错误,通过muxTxRestart在发送队列满时请求重启发送。
需要特别注意的是,muxReceive通常在中断服务程序或轮询任务中调用,因此驱动必须保证传入的M_BLK或clBlk结构合法,且不能在中断上下文中执行可能阻塞的操作。若驱动在中断中直接调用muxReceive,应确保MUX和协议栈的中断安全级别允许。
发送与接收数据路径
发送路径:协议栈生成数据包后,经MUX调用驱动的send回调。驱动从M_BLK链中取出数据,填充到DMA发送描述符,写硬件发送寄存器,启动发送。发送完成后,硬件产生发送完成中断,驱动回收描述符并释放M_BLK。若发送队列满,驱动返回END_ERR_AGAIN,MUX会稍后重试或调用muxTxRestart。
接收路径:硬件收到帧后产生接收中断,驱动在中断服务程序中读取接收描述符,分配M_BLK,把帧数据拷贝或映射到M_BLK,然后调用muxReceive上送MUX。MUX根据帧类型(如以太网类型字段)分发给ARP、IP等协议。若使用轮询模式,驱动则在任务中主动查询接收描述符,而非依赖中断。
中断处理与轮询模式
中断模式适合大多数通用场景:收发事件由硬件中断触发,CPU占用低,但中断频繁时可能增加延迟抖动。轮询模式则适合高吞吐或中断资源受限的场景,驱动在pollSend/pollReceive中主动检查描述符状态,避免中断开销,但会占用CPU轮询时间。
在VxWorks中,可通过驱动ioctl命令或配置参数切换模式。例如,某些驱动支持END_IOCTL_SET_POLL类命令。实际选择时,应结合CPU负载、帧率、延迟要求综合判断。若中断模式下出现丢包,可先检查中断服务程序是否过长、描述符环是否过小;若轮询模式下CPU占用过高,可适当降低轮询频率或改回中断模式。
常见驱动调试手段与工具
VxWorks提供了一组网络调试工具,常用的包括:
ifShow:查看接口状态、MAC地址、MTU、收发计数、错误计数。muxShow:查看MUX层绑定的协议与驱动关系。netStatShow:查看协议栈统计信息,辅助判断丢包发生在驱动还是协议层。arpShow、routeShow:排查ARP解析和路由问题。ping:验证链路连通性,结合ifShow计数判断收发是否正常。
调试时建议按“物理层→驱动层→MUX层→协议层”的顺序排查。先确认ifShow中接口UP且收发计数增长;若发送计数增长但接收计数不增长,重点检查接收中断、DMA描述符和muxReceive调用;若接收计数增长但上层无响应,检查MUX绑定和协议配置。必要时可在驱动send和muxReceive入口加日志,观察帧的进出情况。
NET_FUNCS,MUX通过回调调用驱动,驱动通过muxReceive上送数据。调试时优先用ifShow和muxShow确认绑定与计数,再逐层排查。