lwip的架构分析(基于LPC17xx)

终于开始这部分的工作,计划了很久,但一直都没有实施。以前一直只使用TCP/IP但对其处理的流程确一知半解。计划拿出几天的时间好好的学习下,理解其运行的基本原理。

       一个嵌入式的网络架构一般都由3部分构成:1、应用层。2、协议层。3、网卡层驱动。为了较好的理解lwip的架构。我们从应用层开始一层一层的剥开整个过程,了解整个系统时怎样串联起来的,

       首先是应用层,这里会初始化网络参数。参见下面用户初始化网络的代码:

tcpip_init(tcpip_init_done_signal,(void *) &tcpipdone);     

IP4_ADDR(&gw, 10, 1, 10, 1);

       IP4_ADDR(&ipaddr,10, 1, 10, 234);

       IP4_ADDR(&netmask,255, 255, 255, 0);

       /* Add netif interfacefor lpc17xx_8x */

       if(!netif_add(&lpc_netif, &ipaddr, &netmask, &gw, NULL,lpc_enetif_init,

                               tcpip_input)) {

              LWIP_ASSERT("Netinterface failed to initialize\r\n", 0);

       }

       netif_set_default(&lpc_netif);

       netif_set_up(&lpc_netif);

这是初始化网络代码的一部分。其中最重要的是tcpip_init()和net_add()函数。

串联其中的就是lpc_netif变量,它是一个struct netif结构体,一般一个网卡对应一个struct netif结构,并用一个list将所有网卡链接起来构成一个链表。首先先看看这个接口的定义:

struct netif {

  struct netif *next; /** pointer to next in linked list;指向下一个网卡 */

  ip_addr_t ip_addr;/**网卡的配置参数**/

  ip_addr_t netmask;

  ip_addr_t gw;

  /** This function iscalled by the network device driver

   *  to pass a packet up the TCP/IP stack. */

  netif_input_fn input;//这是个函数指针,由设备驱动程序调用,传递一个网络数据包到TCP/IP层。

  /** This functionis called by the IP module when it wants

   *  to send a packet on the interface. Thisfunction typically

   *  first resolves the hardware address, thensends the packet. */

  netif_output_fn output; //这也是一个函数指针,由IP模块调用发送一个网卡。

  /** This function is called by the ARP modulewhen it wants

   *  to send a packet on the interface. Thisfunction outputs

   *  the pbuf as-is on the link medium. */

  netif_linkoutput_fn linkoutput;//这个函数由ARP协议调用

};

       在tcpip_init()中会有一个重要的调用既创建了tcpip_thread()的线程。 我们来看看这个函数到底做了些什么呢?

void   tcpip_init(tcpip_init_done_fninitfunc, void *arg)

{

  lwip_init();

  if(sys_mbox_new(&mbox,TCPIP_MBOX_SIZE) != ERR_OK) {

    LWIP_ASSERT("failedto create tcpip_thread mbox", 0);

  }

#if LWIP_TCPIP_CORE_LOCKING

 if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) {

    LWIP_ASSERT("failed to createlock_tcpip_core", 0);

  }

#endif /* LWIP_TCPIP_CORE_LOCKING */

 

 sys_thread_new(TCPIP_THREAD_NAME ,tcpip_thread,NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);

}

我从中可以看到调用了3个函数:

1、lwip_init();初始化了lwip需要要用到的一些参数。

2、sys_mutex_new()创建了一个新的互斥锁。

3 sys_thread_new()新建了一个线程处理tcpip协议栈。在这个线程中你会看到线程会阻塞在读mbox的函数上,直到网卡接收到数据才会继续执行下去。详细的代码请参看tcpip.c文件。


下面我们在来看看另一函数net_add(),我们先看它的第六个参数:lpc_enetif_init(),这个参数是一个函数指针,它是lpc mac层的驱动程序中的一个函数。我们在来看看这个函数中到底干了些什么。

{

       err= low_level_init(netif);//初始化MAC以及Phy芯片

       netif->output= lpc_etharp_output;//设置网卡arp输出函数到网卡接口

       netif->linkoutput= lpc_low_level_output;//设置网卡IP数据输出函数网卡接口

sys_thread_new("receive_thread",vPacketReceiveTask, netif->state,

                               DEFAULT_THREAD_STACKSIZE,tskRECPKT_PRIORITY);

                            //底层的接收线程

sys_thread_new("txclean_thread",vTransmitCleanupTask, netif->state,

                               DEFAULT_THREAD_STACKSIZE,tskTXCLEAN_PRIORITY);

                            //底层的发送线程

}

我们再看看接收线程:

首先线程信号量:/* Wait for receive task to wakeup*/

sys_arch_sem_wait(&lpc_netifdata->RxSem,0);

然后读取网卡数据:

lpc_enetif_input(lpc_netifdata->netif);  à pbuf * p=lpc_low_level_input(netif);//读一个包到pbuf包中  à  netif->input(p, netif)//将数据传递给注册的input函数(即tcpip_input()函数)。

 

看完上面的,我们在看看我们在netif_add注册的tcpip_input()

lpc_netif.input=tcpip_input() 及网卡收到网络数据包调用该input函数指针。tcpip_input()函数会根据协议调用sys_mbox_trypost(&mbox, msg)邮箱发送函数,这个函数会将接收到的pbuf数据发给TCP/IP协议栈的处理进程处理(即阻塞的tcpip_thread进程);

 

看到这儿,我都感觉有点凌乱了。在重新的串一下整个流程:首先在主函数中,调用了tcpip_init()函数建立了tcpip的协议栈线程。接着又调用了net_add()函数,特别需要注意的是其两个传入的函数指针(这两个函数是在网卡驱动中实现的(在这里驱动与tcpip栈建立了联系)init参数和input参数。init()函数会调用网卡驱动的初始化函数err_t lpc_enetif_init(struct netif *netif)。在这个函数会新建两个线程,一个是网卡的接收线程(从网卡中读取一个数据包,并调用我们在netif中注册的input函数将数据包交给tcpip协议栈线程处理了),一个是网卡的发送线程(它会阻塞在一个信号量上,当有数据需要发送时,将数据发送出去)。讲到这里应该大概明白了lwip的驱动基本架构了吧!。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LWIP(轻量级IP协议栈)和UIP(嵌入式IP协议栈)都是广泛使用的嵌入式操作系统网络协议栈。在LPC1788处理器上进行LWIP和UIP的移植可以实现网络功能。LPC1788是一款由恩智浦半导体公司生产的ARM Cortex-M3内核的微控制器。 LWIP和UIP的移植过程相似,下面是一个简单的移植指南: 1. 首先,需要在LPC1788处理器上设置合适的硬件和软件环境。确保处理器的外围设备(例如以太网控制器)和网络接口正确配置并连接。 2. 接下来,从LWIP或UIP的官方网站上下载相应的源代码。确保下载的版本与LPC1788处理器兼容。 3. 将源代码解压缩到LPC1788处理器的开发环境中。确保源代码的文件结构正确。 4. 打开源代码文件中的配置文件,通常是一个.h文件,根据LPC1788处理器的硬件配置进行相应的设置。这些配置包括网络接口和IP地址的设置,以太网控制器和中断的配置等。 5. 根据LPC1788处理器的中断控制器的配置,修改源代码中的中断处理函数。这些函数负责接收和处理网络数据包。 6. 根据LPC1788处理器的时钟配置,调整源代码中的时钟设置,以确保网络功能与处理器的时钟频率同步。 7. 最后,对源代码进行编译和链接,生成可执行文件。将可执行文件下载到LPC1788处理器并运行,即可进行网络通信。 通过以上步骤,就可以在LPC1788处理器上成功移植LWIP和UIP的网络协议栈,实现网络功能。可以使用网络协议栈提供的API来进行数据的发送和接收,实现远程数据通信等功能。同时,还可以根据具体应用的需求进行定制和优化,以提高系统的性能和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值