LWIP 代码图文分析

        LwIP是Light Weight (轻型)IP协议,有无操作系统的支持都可以运行。LwIP实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用,它只需十几KB的RAM和40K左右的ROM就可以运行,这使LwIP协议栈适合在低端的嵌入式系统中使用

1 协议解析(ICMP(ping)用于返回的错误信息或是分析路由,ARP 以太网地址解析)

        ICMP ping命令的机制就是回显请求和回显应答消息,具体是向网络上另一个主机上发送ICMP报文,如果指定的主机得到了这个报文,就将报文原封不动的发送回发送者。
        ARP 以太网地址解析协议

2  lwip提供三种API:1)RAW API 2)lwip API 3)BSD API。

3 代码整体架构

4 代码分析

MX_LWIP_Init() //创建3个线程(1 tcpip_thread 2ethernetif_set_link 3 ethernetif_input  )
{
    tcpip_init()
    {
        sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE);
        sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO)
        {
            tcpip_thread(void *arg)
            {
                while (1)
                { /* MAIN Loop */
                    /* wait for a message, timeouts are processed while waiting */
                    TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);
                    tcpip_thread_handle_msg(msg);
                }
            }
        }
    }
    /* add the network interface (IPv4/IPv6) with RTOS */
    netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input)
    {
        ethernetif_init()
        {
            low_level_init(netif)
            {
                osThreadNew(ethernetif_input, netif, &attributes)
                {
                    ethernetif_input()
                    {
                        for (;;)
                        {
                            osSemaphoreAcquire(s_xSemaphore, TIME_WAITING_FOR_INPUT);
                            netif->input(p, netif); //此函数为上面注册的tcpip_input
                        }
                    }
                }
            }
        }
        tcpip_input(struct pbuf * p, struct netif * inp)
        {
            tcpip_inpkt(p, inp, ip_input)
            {
                sys_mbox_trypost(&tcpip_mbox, msg); //收到数据发送信号量
            }
        }
    }
    /* Set the link callback function, this function is called on change of link status*/
    netif_set_link_callback(&gnetif, ethernetif_update_config);
    /* Create the Ethernet link handler thread */
    osThreadDef(LinkThr, ethernetif_set_link, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 2)
    {
        ethernetif_set_link() //检查网线连接状态
        {
            for (;;)
            {
                /* Check whether the netif link down and the PHY link is up */
                if (!netif_is_link_up(link_arg->netif) && (regvalue))
                {
                    netif_set_link_up(link_arg->netif); /* network cable is connected */
                    {
                        netif->link_callback(n); //执行前面注册的回调函数
                    }
                }
                else if (netif_is_link_up(link_arg->netif) && (!regvalue))
                {
                    netif_set_link_down(link_arg->netif); /* network cable is dis-connected */
                    {
                        netif->link_callback(n); //执行前面注册的回调函数
                    }
                }
                osDelay(200);
            }
        }
    }
}

netconn_new(t)
{
    netconn_alloc(t, callback)
    {
        conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
        sys_mbox_new(&conn->recvmbox, size); //创建信号量,当接收到数据时,注册的回调函数会发送此信号量
    }
    netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg))
    {
        lwip_netconn_do_newconn()
        {
            pcb_new(msg)
            {
                switch (NETCONNTYPE_GROUP(msg->conn->type))
                {
                case NETCONN_UDP: //设置接收到数据时执行的回调函数
                    udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
                    {
                        recv_udp()
                        {
                            buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
                            sys_mbox_trypost(&conn->recvmbox, buf); //当收到数据时,发送信号量
                        }
                    }
                    break;
                case NETCONN_TCP:
                    setup_tcp(msg->conn) //设置回调函数
                    {
                        tcp_arg(pcb, conn);
                        tcp_recv(pcb, recv_tcp);
                        tcp_sent(pcb, sent_tcp);
                        tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL);
                        tcp_err(pcb, err_tcp);
                    }
                    break;
                }
            }
        }
    }
}

netconn_recv()
{
    netconn_recv_data_tcp(conn, &p, 0);           // tcp
    netconn_recv_data(conn, (void **)new_buf, 0); // udp
    {
        sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); //等待信号量 非阻塞
    }
}

netconn_send(struct netconn *conn, struct netbuf *buf)
{
    netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg))
    {
        lwip_netconn_do_send(void *m)
        {
            udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port)
            {
                /* find the outgoing network interface for this packet */
                netif = ip_route(&pcb->local_ip, dst_ip);
                udp_sendto_if(pcb, p, dst_ip, dst_port, netif); //将package发送出去
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/w356877795/article/details/126935966