SylixOS网卡驱动调用篇

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SylixOS网卡驱动调用篇相关的知识,希望对你有一定的参考价值。

1. 开发环境

  • 操作系统:SylixOS

  • 编程环境:RealEvo-IDE3.1

  • 硬件平台:IMX6Q实验箱


2. 技术实现

SylixOS网卡驱动框架篇》里提过,网卡驱动的收发功能是通过netdev结构里的transmitreceive两个成员实现的。本篇文章将介绍SylixOS里的LWIP协议栈是如何调用底层网卡驱动里的这两个成员函数的。

2.1      网卡发送函数的调用

整个网卡驱动发送函数的调用关系如 21所示。

技术分享



网卡驱动在向SylixOS注册网卡驱动时,需要调用netdev_add函数,这个函数接收一个netdev结构的参数。因为在网卡驱动初始化过程中,已经在底层驱动里实现了netdev下的transmitreceive两个成员。所以netdev_add函数可以通过netdev这个参数找到驱动里的收发功能函数。


netdev_add函数里会调用netifapi_netif_add 来添加API函数,netifapi_netif_add接收的一个函数参数是netdev_netif_initnetifapi_netif_add函数最终会调用netdev_netif_init函数。


netdev_netif_init函数会把netdev_netif_linkoutput赋值给netif结构体下的linkoutputnetdev_netif_linkoutput的具体实现如程序清单 21 所示。


LWIP协议栈里最终调用到底层驱动时,就是通过netiflinkoutput实现的,如程序清单 21所示,netdev_netif_linkoutput会调用宏NETDEV_TRANSMIT,这个宏的实现如程序清单 22 所示NETDEV_TRANSMIT会调用netdev里的transmit成员函数来进行数据包的发送。


程序清单 21 netdev_netif_linkoutput函数


/* lwip netif linkoutput hook function */
static err_t  netdev_netif_linkoutput(struct netif *netif, struct pbuf *p)
{
  netdev_t *netdev = (netdev_t*)(netif->state);
  int ret;
 
#if ETH_PAD_SIZE
  pbuf_header(p, -ETH_PAD_SIZE);
#endif
 
  ret = NETDEV_TRANSMIT(netdev, p);
  
#if ETH_PAD_SIZE
  pbuf_header(p, ETH_PAD_SIZE);
#endif
 
  if (ret < 0) {
    return (ERR_IF);
  }
  return (ERR_OK);
}


程序清单 22NETDEV_TRANSMIT

 #define  NETDEV_TRANSMIT(netdev, a)    (netdev)->drv->transmit((netdev), a)


2.2    网卡接收函数的调用

SylixOS网卡驱动实现篇》里提到过,网卡驱动里的接收中断使用netdev_notify函数来通知协议栈已经收到数据,并让协议栈调用netdevreceive成员函数来进行接收报文的处理。


接收处理函数enetCoreRecv里接收两个参数,一个是netdev结构体,另一个是input类型的函数。


netdev_notify的具体实现如程序清单 23 所示,里面会通过q_en这个参数来决定是否使用队列的方式来接收,如果不使用,则直接调用宏NETDEV_RECEIVE,否则通过netJobAdd把接收处理函数添加到队列中。不管哪一种方式,最后都会调用netdev下的receive成员函数,而receive的第二个input类型的参数就是程序清单 23 中的netdev_netif_linkinput


因此,底层驱动的接收处理函数会通过netdev_netif_linkinput把网卡收到的数据一层层的传到协议栈中去进行对应的处理。


程序清单 23 netdev_notify函数


/*if netdev detected a packet in netdev buffer, driver can callthis function to receive this packet.
   notify:0 can transmit 1: can receive 
   qen:0 do not use netjob queue1:use netjob queue */
int  netdev_notify (struct netdev *netdev,netdev_inout inout, int q_en)
{
  if (!netdev || (netdev->magic_no !=NETDEV_MAGIC)) {
    return (-1);
  }
  
  if (inout != LINK_INPUT) {
    return (0);
  }
  
  if (q_en) {
    if (netJobAdd(netdev->drv->receive,netdev, 
                  (void*)netdev_netif_linkinput, 0, 0, 0, 0) == 0) {
      return (0);
    
    } else {
      return (-1);
    }
  }
  
  NETDEV_RECEIVE(netdev,netdev_netif_linkinput);
  
  return (0);
}


3. 参考资料



本文出自 “11451177” 博客,请务必保留此出处http://11461177.blog.51cto.com/11451177/1914772

以上是关于SylixOS网卡驱动调用篇的主要内容,如果未能解决你的问题,请参考以下文章

SylixOS 下的IO系统调用

SylixOS网卡驱动优化

SylixOS网络数据异步处理原理

SylixOS 驱动调试软件使用说明

SylixOS基于Nuc970平台的SD驱动移植

SylixOS字符设备驱动框架