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
}
}
|
浙公网安备 33010602011771号