lwip 移植到裸板(不带OS)指南

参考

https://lwip.fandom.com/wiki/Porting_For_Bare_Metal

 

步骤

1、创建 cc.h

参考 https://www.cnblogs.com/zhangzhiwei122/p/15871026.html 查看,需要在 cc.h 中提供的内容。

 

2、创建 sys_arch.h

因为 是不带 OS 的移植,所以不需要 实现 os abstract layer.

sys_arch.h 中只需要   typedef 一些类型,和define 一些宏定义即可

参考  https://www.cnblogs.com/zhangzhiwei122/p/15871026.html 查看,需要在 sys_arch.h 中提供的 类型和宏。

 

3、创建 lwipopts.h 文件

这个是用户自定义配置文件,里面有许多宏定义,我们最关心的是,必须有

#define NO_SYS   1

 

4、创建设备驱动程序(用于收发数据)

参考 https://lwip.fandom.com/wiki/Writing_a_device_driver 

 

5、创建sys_now 函数,返回当前系统时间的 毫秒数

 

6、创建main函数

6.1 初始化lwip

6.2 初始化定时器

6.3 使用 netif_add 添加网卡驱动

6.4 进入循环

6.4.1    循环处理收到的frame

6.4.2    1.3 及以前的版本:间隔调用 etharp_tmr(), ip_reass_tmr(), tcp_tmr() 等函数【调用哪些函数,取决于你启用的功能】 1.4 版本之后:调用 sys_check_timeouts() 函数

 

示例 - 基于 1.3.2版本

The compiler was gcc, the architecture was MIPS-32 (big-endian).

基于 gcc 和 mips-32 big-endian

arch/cc.h

#ifndef __ARCH_CC_H__
#define __ARCH_CC_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/time.h>

// Includes definition of mch_printf macro to do printf
#include "mch.h"

#define BYTE_ORDER  BIG_ENDIAN

typedef uint8_t     u8_t;
typedef int8_t      s8_t;
typedef uint16_t    u16_t;
typedef int16_t     s16_t;
typedef uint32_t    u32_t;
typedef int32_t     s32_t;

typedef uintptr_t   mem_ptr_t;

#define LWIP_ERR_T  int

/* Define (sn)printf formatters for these lwIP types */
#define U16_F "hu"
#define S16_F "hd"
#define X16_F "hx"
#define U32_F "u"
#define S32_F "d"
#define X32_F "x"

/* Compiler hints for packing structures */
#define PACK_STRUCT_FIELD(x)    x
#define PACK_STRUCT_STRUCT  __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END

/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(x)   do {                \
        mch_printf x;                   \
    } while (0)

#define LWIP_PLATFORM_ASSERT(x) do {                \
        mch_printf("Assert \"%s\" failed at line %d in %s\n",   \
                x, __LINE__, __FILE__);             \
        mch_abort();                        \
    } while (0)

#endif /* __ARCH_CC_H__ */

sys_arch.h

#ifndef __ARCH_SYS_ARCH_H__
#define __ARCH_SYS_ARCH_H__

#define SYS_MBOX_NULL   NULL
#define SYS_SEM_NULL    NULL

typedef void * sys_prot_t;

typedef void * sys_sem_t;

typedef void * sys_mbox_t;

typedef void * sys_thread_t;

#endif /* __ARCH_SYS_ARCH_H__ */

lwipopts.h

#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

#define NO_SYS                      1
#define MEM_LIBC_MALLOC             1
#define MEMP_MEM_MALLOC             1
#define MEM_ALIGNMENT               4
#define MEM_SIZE                    (4 * 1024 * 1024)
#define MEMP_NUM_PBUF               1024
#define MEMP_NUM_UDP_PCB            20
#define MEMP_NUM_TCP_PCB            20
#define MEMP_NUM_TCP_PCB_LISTEN     16
#define MEMP_NUM_TCP_SEG            128
#define MEMP_NUM_REASSDATA          32
#define MEMP_NUM_ARP_QUEUE          10
#define PBUF_POOL_SIZE              512
#define LWIP_ARP                    1
#define IP_REASS_MAX_PBUFS          64
#define IP_FRAG_USES_STATIC_BUF     0
#define IP_DEFAULT_TTL              255
#define IP_SOF_BROADCAST            1
#define IP_SOF_BROADCAST_RECV       1
#define LWIP_ICMP                   1
#define LWIP_BROADCAST_PING         1
#define LWIP_MULTICAST_PING         1
#define LWIP_RAW                    1
#define TCP_WND                     (4 * TCP_MSS)
#define TCP_MSS                     1460
#define TCP_SND_BUF                 (8 * TCP_MSS)
#define TCP_LISTEN_BACKLOG          1
#define LWIP_NETIF_STATUS_CALLBACK  1
#define LWIP_NETIF_LINK_CALLBACK    1
#define LWIP_NETIF_HWADDRHINT       1
#define LWIP_NETCONN                0
#define LWIP_SOCKET                 0
#define LWIP_STATS_DISPLAY          1
#define MEM_STATS                   0
#define SYS_STATS                   0
#define MEMP_STATS                  0
#define LINK_STATS                  0
#define ETHARP_TRUST_IP_MAC         0
#define ETH_PAD_SIZE                2
#define LWIP_CHKSUM_ALGORITHM       2

#define LWIP_TCP_KEEPALIVE          1

// Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing
#define TCP_KEEPIDLE_DEFAULT        10000UL // Default KEEPALIVE timer in milliseconds
#define TCP_KEEPINTVL_DEFAULT       2000UL  // Default Time between KEEPALIVE probes in milliseconds
#define TCP_KEEPCNT_DEFAULT         9U      // Default Counter for KEEPALIVE probes

#include "mch.h"

#define mem_init()
#define mem_free                    mch_free
#define mem_malloc                  mch_malloc
#define mem_calloc(c, n)            mch_zalloc((c) * (n))
#define mem_realloc(p, sz)          (p)

#define LWIP_DEBUG                  0

#define ETHARP_DEBUG                LWIP_DBG_OFF
#define NETIF_DEBUG                 LWIP_DBG_OFF
#define PBUF_DEBUG                  LWIP_DBG_OFF
#define API_LIB_DEBUG               LWIP_DBG_OFF
#define API_MSG_DEBUG               LWIP_DBG_OFF
#define SOCKETS_DEBUG               LWIP_DBG_OFF
#define ICMP_DEBUG                  LWIP_DBG_OFF
#define INET_DEBUG                  LWIP_DBG_OFF
#define IP_DEBUG                    LWIP_DBG_OFF
#define IP_REASS_DEBUG              LWIP_DBG_OFF
#define RAW_DEBUG                   LWIP_DBG_OFF
#define MEM_DEBUG                   LWIP_DBG_OFF
#define MEMP_DEBUG                  LWIP_DBG_OFF
#define SYS_DEBUG                   LWIP_DBG_OFF
#define TCP_DEBUG                   LWIP_DBG_OFF
#define TCP_INPUT_DEBUG             LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG            LWIP_DBG_OFF
#define TCP_RTO_DEBUG               LWIP_DBG_OFF
#define TCP_CWND_DEBUG              LWIP_DBG_OFF
#define TCP_WND_DEBUG               LWIP_DBG_OFF
#define TCP_FR_DEBUG                LWIP_DBG_OFF
#define TCP_QLEN_DEBUG              LWIP_DBG_OFF
#define TCP_RST_DEBUG               LWIP_DBG_OFF
#define UDP_DEBUG                   LWIP_DBG_OFF
#define TCPIP_DEBUG                 LWIP_DBG_OFF
#define PPP_DEBUG                   LWIP_DBG_OFF
#define SLIP_DEBUG                  LWIP_DBG_OFF
#define DHCP_DEBUG                  LWIP_DBG_OFF

#endif /* __LWIPOPTS_H__ */

main.c

#include "mch.h"
#include "lwip/inet.h"
#include "lwip/tcp.h"
#include "lwip/ip_frag.h"
#include "lwip/netif.h"
#include "lwip/init.h"
#include "lwip/stats.h"
#include "netif/etharp.h"

struct ip_addr mch_myip_addr;

#define MCH_ARP_TIMER_INTERVAL      (ARP_TMR_INTERVAL * 1000)
#define MCH_TCP_TIMER_INTERVAL      (TCP_TMR_INTERVAL * 1000)
#define MCH_IPREASS_TIMER_INTERVAL  (IP_TMR_INTERVAL * 1000)

static mch_timestamp ts_etharp;
static mch_timestamp ts_tcp;
static mch_timestamp ts_ipreass;

// Our network interface structure
static struct netif mchdrv_netif;

// Functions from my netif driver
// Probe function (find the device, return driver private data)
extern int mchdrv_probe(struct mch_pci_dev *, void **, uint8_t *);
// Init function
extern int mchdrv_attach(struct netif *);
// Poll for received frames
extern void mchdrv_poll(struct netif *);

int mch_net_init(void)
{
    struct ip_addr gw_addr, netmask;
    struct mch_pci_dev * mchdrv_pcidev;
    void * mchdrvnet_priv;
    uint8_t mac_addr[6];
    int err = -1;

    // Hard-coded IP for my address, gateway and netmask
    if (mch_net_aton(MCH_IPADDR_BASE, &mch_myip_addr))
        return -1;
    if (mch_net_aton(MCH_IPADDR_GW, &gw_addr))
        return -1;
    if (mch_net_aton(MCH_IPADDR_NETMASK, &netmask))
        return -1;

    // Initialize LWIP
    lwip_init();

    // Initialize PCI bus structure
    mch_pci_init();

    // Search through the list of PCI devices until we find our NIC
    mchdrv_pcidev = NULL;
    while ((mchdrv_pcidev = mch_pci_next(mchdrv_pcidev)) != NULL) {
        if ((err = mchdrv_probe(mchdrv_pcidev, &mchdrvnet_priv, mac_addr)) == 0)
            break;
    }

    if (mchdrv_pcidev == NULL) {
        mch_printf("mch_net_init: network adapter not found\n");
        return -1;
    }

    // Add our netif to LWIP (netif_add calls our driver initialization function)
    if (netif_add(&mchdrv_netif, &mch_myip_addr, &netmask, &gw_addr, mchdrvnet_priv,
                mchdrv_init, ethernet_input) == NULL) {
        mch_printf("mch_net_init: netif_add (mchdrv_init) failed\n");
        return -1;
    }

    netif_set_default(&mchdrv_netif);
    netif_set_up(&mchdrv_netif);

    // Initialize timer values
    mch_timestamp_get(&ts_etharp);
    mch_timestamp_get(&ts_tcp);
    mch_timestamp_get(&ts_ipreass);

    return 0;
}

//
// Regular polling mechanism.  This should be called each time through
// the main application loop (after each interrupt, regardless of source).
//
// It handles any received packets, permits NIC device driver house-keeping
// and invokes timer-based TCP/IP functions (TCP retransmissions, delayed
// acks, IP reassembly timeouts, ARP timeouts, etc.)
//
void mch_net_poll(void)
{
    mch_timestamp now;

    // Call network interface to process incoming packets and do housekeeping
    mchdrv_poll(&mchdrv_netif);

    // Process lwip network-related timers.
    mch_timestamp_get(&now);
    if (mch_timestamp_diff(&ts_etharp, &now) >= MCH_ARP_TIMER_INTERVAL) {
        etharp_tmr();
        ts_etharp = now;
    }
    if (mch_timestamp_diff(&ts_tcp, &now) >= MCH_TCP_TIMER_INTERVAL) {
        tcp_tmr();
        ts_tcp = now;
    }
    if (mch_timestamp_diff(&ts_ipreass, &now) >= MCH_IPREASS_TIMER_INTERVAL) {
        ip_reass_tmr();
        ts_ipreass = now;
    }
}

//
// Convert address from string to internal format.
// Return 0 on success; else non-zero
//
int mch_net_aton(char * str_addr, struct ip_addr * net_addr)
{
    struct in_addr a;
    int i = inet_aton(str_addr, &net_addr->addr);
    if (!i)
        return -1;
    return 0;
}

//
// Main entry point
//
int main(void)
{
    [snip other non-lwip initializations]
    mch_timestamp_init();       // Initialize timestamp generator
    mch_net_init();
    while (1) {
        [snip other non-lwip functions]
        mch_wait_for_interrupt();   // Awakened by network, timer or other interrupt
        mch_net_poll();             // Poll network stack
    }
}
posted @ 2022-02-08 14:45  张志伟122  阅读(759)  评论(0编辑  收藏  举报