13397158231   jevian_ma@worldflying.cn

lwip无操作系统移植方式学习

2022-07-20 13:010:32

lwip是一套强大的tcpip库,对于低性能单片机类的设备中非常适合,可以方便的让设备在任何底层通信中使用tcpip传输协议。

通过lwip,可以实现uart传tcpip,lora等传tcpip等。下面就给大家介绍下如何实现无操作系统情况下对ethernet驱动的移植:

1、先去github下载lwip源码:传送门。这里下载lwip-STABLE-2_1_3_RELEASE版本。

2、解压,将src下的api、core、netif、include复制到自己的工程中去,不需要其他额外文件。

3、修改自己的工程管理工具将自己的main.c文件以及上面文件夹中的api、core、netif中包含的c文件都添加到工程中编译。

4、修改自己的工程管理工具让include变为编译头文件路径。

5、在自己的编译头文件路径中添加lwipopts.h、arch/cc.h与arch/cc.c文件。

6、在lwipopts.h中添加特定的宏,如#define NO_SYS 1

#ifndef LWIP_HDR_LWIPOPTS_H
#define LWIP_HDR_LWIPOPTS_H

// #define LWIP_DEBUG 1

#define MEM_ALIGNMENT 4

#define NO_SYS 1
#define SYS_LIGHTWEIGHT_PROT 0

#define LWIP_NETCONN 0
#define LWIP_SOCKET 0

#define LWIP_ETHERNET 1
#define LWIP_ARP 1

#define LWIP_DHCP 1
#define LWIP_AUTOIP 0

#define LWIP_IGMP 1
#define LWIP_DNS 1

#define MEM_SIZE 4096
#define TCP_SND_QUEUELEN 6

#define TCP_SNDLOWAT 1002
#define PBUF_POOL_SIZE 5
#endif

7、实现u32_t sys_now(void)函数

不同的芯片实现方式不同,这里返回的是毫秒时间。linux可以用如下方式模拟:

u32_t sys_now(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return 1000 * tp.tv_sec + tp.tv_nsec / 1000;
}

8、定义LWIP_RAND()方法

不同的芯片实现方式不同,这里返回的是毫秒时间。linux可以用如下方式模拟:

#define LWIP_RAND() ((u32_t)rand())

到此,移植完毕。下面介绍如何使用:

1、执行初始化函数

ip4_addr_t addr;
ip4_addr_t netmask;
ip4_addr_t gw;
IP4_ADDR(&addr, 192, 168, 37, 84);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 37, 1);
lwip_init();
netif_add(&netif, &addr, &netmask, &gw, &netif, eth_init, netif_input);
netif_set_default(&netif);
netif_set_up(&netif);
netif_set_link_up(&netif);
ip4_addr_t dns;
IP4_ADDR(&dns, 114, 114, 114, 114);
dns_setserver(0, &dns);

其中eth_init是初始化函数,

static err_t eth_init(struct netif *netif)
{
netif->name[0] = 'w';
netif->name[1] = 'f';
netif->output = etharp_output;
netif->linkoutput = low_tap_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
netif->hwaddr[0] = 0x00;
netif->hwaddr[1] = 0x23;
netif->hwaddr[2] = 0xC1;
netif->hwaddr[3] = 0xDE;
netif->hwaddr[4] = 0xD0;
netif->hwaddr[5] = 0x0D;
netif->hwaddr_len = 6;

return ERR_OK;
}

上诉代码就是实现了lwip的基本移植,上面代码配置了一个ip为192.168.37.84,mask为255.255.255.0,gateway为192.168.37.1,dns为114.114.114.114的网卡,该网卡的mac为00:23:c1:de:d0:d0。

初始化代码中的low_tap_output是底层发送函数,需要根据不同的芯片进行修改。

static err_t low_tap_output(struct netif *netif, struct pbuf *p)
{
    char buff[1518];
    int len = 0;
    for (struct pbuf *q = p; q != NULL; q = q->next)
    {
        memcpy(buff + len, q->payload, q->len);
        len += q->len;
    }
    write(tapfd, buff, len); // 底层发送函数
    return ERR_OK;
}

还有需要创建两个线程,一个是循环调用sys_check_timeouts()。另一个是接收物理端发过来的数据包。

void *checktimeout()
{
    while (1)
    {
        usleep(100000);
        sys_check_timeouts();
    }
}

void *low_tap_input()
{
    unsigned char buff[1518];
    while (1)
    {
        ssize_t len = read(tapfd, buff, 1518); // 接收底层物理数据
        if (len < 0)
        {
            continue;
        }
        struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
        if (p == NULL)
        {
            continue;
        }
        pbuf_take(p, buff, len);
        netif.input(p, &netif); // p在netif_input内已经释放了,无需再调用pbuf_free(p)
    }
    return NULL;
}

到此就可以尝试ping一下了。


文章作者:沃航科技

优秀产品推荐:可编程网络IO控制器

上一篇:openwrt根分区出现read only partition的解决方法

下一篇:vscode中添加clang-format插件并启动的方法

联系我们

  • 地址:武汉市东湖高新开发区光谷总部国际1栋2412室
  • QQ:932773931
  • 电话:027-59761089-806
  • 手机:13397158231
  • 邮箱:jevian_ma@worldflying.cn

关注公众号

扫码添加微信

沃航(武汉)科技有限公司版权所有

备案号:鄂ICP备16014230号-1

本网站由提供CDN加速/云存储服务