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 } } |