移植lwIP至U-Boot

2023-11-11

原文地址:http://www.wl-chuang.com/blog/2011/11/04/porting-lwip-to-uboot/

U-Boot是嵌入式系統上被廣為運用的boot loader,它擁有極為活躍的開發社群,也支援許多不同類型的CPU核心架構。U-Boot目前並不支援完整的TCP/IP,僅有限度地支援TFTP,方便開發者上傳韌體或是網路開機(BOOTP)。U-Boot身為boot loader非嵌入式作業系統,依據開放原始碼社群秉持地「精簡就是美」原則,不支援TCP/IP是可以理解的。萬一真的需要網路功能,移植一套完整的TCP/IP協定堆疊的任務雖然富有挑戰性,實務上亦是可行之道。

麻雀雖小五臟俱全的「lwIP」

lightweight IP(lwIP)是一個輕巧的開放原始碼之TCP/IP通訊協定之實作。lwIP首先由Adam Dunkels發表,目前則是以Kieran Mansley為計畫主持人,帶領開放原始碼社群進行該專案的維護與開發。

目前lwIP已實做的協定如下:

  • IP (Internet Protocol) including packet forwarding over multiple network interfaces
  • ICMP (Internet Control Message Protocol) for network maintenance and debugging
  • IGMP (Internet Group Management Protocol) for multicast traffic management
  • UDP (User Datagram Protocol) including experimental UDP-lite extensions
  • TCP (Transmission Control Protocol) with congestion control, RTT estimation and fast recovery/fast retransmit
  • Raw/native API for enhanced performance
  • DNS (Domain names resolver)
  • SNMP (Simple Network Management Protocol)
  • DHCP (Dynamic Host Configuration Protocol)
  • AUTOIP (for IPv4, conform with RFC 3927)
  • PPP (Point-to-Point Protocol)
  • ARP (Address Resolution Protocol) for Ethernet
  • Optional Berkeley-like socket API

lwIP設計理念主要是希望於支援TCP/IP協定的同時,於執行時期也能精簡記憶體之運用,以達成支援小型的嵌入式裝置、平台或即時作業系統(RTOS)的目標;除此之外,lwIP也已經移植到眾多RTOS平台上,例如:eCos…等等。由此這些特性來看,使用lwIP搭配U-Boot是一個好的選擇。

lwIP移植步驟

lwIP的的核心部份由ANSI C撰寫,使用目前的GCC應該可以直接交叉編譯(cross compiling)。整體來說要將lwIP移植到不同平台上,只要完成三件工作即可。首先要決定lwIP的組態;接著,補完lwIP需要之OS抽象層的實作;最後,撰寫lwIP之網路卡驅動程式lwIP architecture

一、選擇你要的lwIP組態

移植lwIP的第一步,要先決定將要啟用之lwIP的功能。由於lwIP包含許多通訊協定堆疊的實作以及許多系統開發除錯(debug)相關的功能,有些功能可能暫時使用不到,我們可以選擇將之關閉。

首先,建立並編輯「lwipopts.h」。以下為範例:

lwipopts.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

#define NO_SYS                      1
#define MEM_LIBC_MALLOC             1
#define MEMP_MEM_MALLOC             0
#define MEMP_SEPARATE_POOLS         0
#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 LWIP_TCP                    1
#define LWIP_UDP                    1
#define LWIP_DHCP                   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                0
#define LWIP_CHKSUM_ALGORITHM       2

#define LWIP_TCP_KEEPALIVE          1

#define MEMP_NUM_SYS_TIMEOUT        5

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

extern void* dma_memory_alloc(unsigned int size);
extern void* dma_memory_calloc(unsigned int size, unsigned int number);
extern void  dma_memory_free(void* ptr);

#define mem_init()
#define mem_free                    dma_memory_free
#define mem_malloc                  dma_memory_alloc
#define mem_calloc(c, n)            dma_memory_calloc((c) * (n))
#define mem_realloc(p, sz)          (p)

#define LWIP_MEM_ALIGN(addr) ((void *)(((u32_t)(addr) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT - 1)))

#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__ */

在lwipopts.h中,我們可以選擇開啟或關閉某些lwIP的模組、決定debug訊息的層級以及lwIP執行時的記憶體配置模型。尤有甚者,U-Boot缺乏多工、多執行緒能力,僅能支援lwIP提供之Raw API,所以需要關閉BSD socket支援。關於每個選項的意義,可以交叉參考「lwip/src/include/lwip/opt.h」裡的說明。

二、移植lwIP之OS抽象層

移植之抽象層至U-Boot並不會太複雜,且U-Boot並沒有多執行緒及其衍生之關於資源競爭(race condition)的議題,移植工程的複雜度可以大幅減輕。所以在這個階段,基本上我們只要解決C compiler的互通性問題即可。lwIP將與此議題相關的選項歸納於cc.h。

cc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef __ARCH_CC_H__
#define __ARCH_CC_H__

// Includes definition of macro to do printf
extern int printf(const char *fmt, ...);

#define BYTE_ORDER               LITTLE_ENDIAN
#define LWIP_PLATFORM_BYTESWAP   0

typedef unsigned char  u8_t;
typedef char           s8_t;
typedef unsigned short u16_t;
typedef short          s16_t;
typedef unsigned int   u32_t;
typedef int            s32_t;
typedef unsigned int*  mem_ptr_t;

#define LWIP_ERR_T  int

/* Define (sn)printf formatters for these lwIP types */
#define U16_F "u"
#define S16_F "d"
#define X16_F "x"
#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 {                \
        printf(x, ##__VA_ARGS__);                   \
    } while (0)

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

#endif /* __ARCH_CC_H__ */

移植時,需指定平台的「BYTE_ORDER」,可為”LITTLE_ENDIAN”或”BIG_ENDIAN”,與此選項相依的有「LWIP_PLATFORM_BYTESWAP」。若移植平台為32-bits little-endian ARM,將BYTE_ORDER設為LITTLE_ENDIAN,LWIP_PLATFORM_BYTESWAP指定為0即可。相關設定,可以參考範例。

三、移植timer相關函式

移植工作至此,除了驅動程式的撰寫外,僅剩下timer的移植。由於lwIP之通訊協定堆疊大多仰賴timer,因此timer的移植於lwIP重要性不言而喻。以U-Boot來說,關於timer的運用並無標準之API,彈性很大,移植者可以視平台狀況啟動timer,並撰寫合適的函式。有關此類函式,可集中於sys_arch.c

sys_arch.c
1
2
3
4
5
6
7
8
9
#include "lwip/sys.h"

extern unsigned int timer2_now();
extern unsigned int timer2_interval();

u32_t sys_now(void)
{
 return timer2_now() * timer2_interval();
}

四、撰寫網路卡驅動程式

lwIP透過網路卡驅動程式由實體層收送封包,關於驅動程式的撰寫方式,可參考lwIP原始碼提供之「netif/ethernetif.c」。

結論

整體來說,移植lwIP至U-Boot並不複雜,但是相關文件不多,需要些許耐心地閱讀甚至追蹤、觀察原始碼的運作。但由於lwIP設計完備,些許心力即可換來與U-Boot的良好搭配,在在顯示open source的彈性與優點。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

移植lwIP至U-Boot 的相关文章

  • shell-test判断

    一 条件判断参数详解 对于test和 中括号 判断语句来说 判断结果为真 则退出值为0 即echo 为0 即返回为true 其他为false 1 关于文件名 文件类型 的判断 e 该 文件名 是否存在 文件和目录都会返回为真 f 该 文件名
  • 基于docker安装mongo

    1 背景 基于业务的需求 部分数据量较大 基本一天的数据量都在1亿左右 关系型数据库已经满足不了了要求 所以更换为非关系型数据库 当然非关系型数据库的种类有很多 我们选择的是mongo 要想了解熟悉mongo 不能只做书面上的功夫 必须较强
  • 微信支付JSAPI支付

    公司业务需求 在公众号中加入微信支付和支付宝支付 效果图如下 菜单的设计直接在公众号中设置就好啦 两个子菜单都是跳转网页形式直接把你服务器上的url复制上就好 一些其他的很重要的配置 微信支付中开发配置 支付测试url 这里是报错 开始以为
  • 记一次centos7 下根目录扩容操作(步骤详细!!!)

    文章目录 需求描述 具体步骤 查看本机磁盘环境 添加磁盘分区 开始扩容 同步到文件系统 参考内容 需求描述 由于测试环境需要 虚拟机根目录需要扩容至120G 具体步骤 查看本机磁盘环境 root localhost df h 文件系统 容量
  • linux中copy_to_user()和copy_from_user()函数

    由于内核空间与用户空间的内存不能直接互访 因此借助函数 copy from user 完成用户空间到内核空间的复制 函数copy to user 完成内核空间到用户空间的复制 copy from user 和 copy to user 的原
  • 从第一人称的角度去带你了解Shell脚本的编写过程及思路

    前言 最近有朋友拿了两个文本给我 里面全都是IP地址 第一个IP地址是已安装相关服务的主机地址 第二个地址则是某一区域的所有主机IP地址 其中第一个文本有部分内容与第二个文本的内容重复 说明是已经安装了的 而第一个文本除了包含第二个文本的部
  • 单节锂电池充放电及外部供电自动切换的电路--原理介绍

    目录 单节锂电池充放电及外部供电自动切换的电路 原理介绍 1 电源输入与输出 2 虚线左边的电路是充电电路 3 虚线右侧的电路是自动切换电路 4 元器件的选择 5 PCB设计建议 单节锂电池充放电及外部供电自动切换的电路 原理介绍 介绍一种
  • 利用matlab建立一个压缩机的热力学数学模型,给出具体的代码

    我不太懂你在说什么 但是我可以提供一些参考资料 可以帮助你建立压缩机的热力学数学模型 1 MATLAB编程指南 https www mathworks com help matlab programming guide html 2 MAT

随机推荐

  • WSL2 在 Windows10下的 网卡 配置问题

    网络上的大部分解决方案是 在Hyper V 的WSL的虚拟交换机中的连接类型改成外部网络 然后在用户目录 USERPROFILE 下面创建一个配置文件 wslconfig wsl2 networkingMode bridged 桥接模式 v
  • CTFHub-web(cookie注入)

    文章目录 一 解题步骤 二 关于sql中 id 多少 的说明 一 解题步骤 1 题目为cookie注入 我们首先先看一下cookie里的值有没有什么可以帮助我们思考的东西 id 1 很明显存在sql注入 2 我们抓包来一步步的进行注入会更方
  • .Net Core跨域处理

    查看官方文档 https docs microsoft com zh cn aspnet core security cors view aspnetcore 2 2 分两部分处理跨域 ConfigureServices里添加 servic
  • 【华为OD机试】模拟消息队列【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 让我们来模拟一个消息队列的运作 有一个发布者和若干消费者 发布者会在给定的时刻向消息队列发送消息若此时消息队列有消费者订阅 这个消息会被发送到订阅的消费者中优先级最高
  • awk的数组学习心得

    http bbs chinaunix net thread 2312439 1 2 html 在文本处理的工作中 awk的数组是必不可少的工具 在这里 同样以总结经验和教训的方式和大家分享下我的一些学习心得 如有错误的地方 请大家指正和补充
  • 医学图像语义分割最佳方法的全面比较:UNet和UNet++

    点击上方 AI公园 关注公众号 选择加 星标 或 置顶 作者 Sergey Kolchenko 编译 ronghuaiyang 导读 在不同的任务上对比了UNet和UNet 以及使用不同的预训练编码器的效果 介绍 语义分割是计算机视觉的一个
  • 超好用的数学公式识别软件mathpix!

    在写科研论文或者其他论文 亦或者将word里的公式搬到latex里进行排版 数学公式总是一项非常艰巨的任务 在电脑上输入的速度远远没有手写来得快 既然如此 有没有办法直接识别手写的公式呢 有 就是这个软件 mathpix 怎么使用呢 下载安
  • Linux-RPM软件包管理/dnf管理软件/源码安装教程/使用systemd管理服务

    文章目录 管理软件包 RPM软件包 Linux软件包管理概述 RPM软件包管理 RPM软件包管理的优缺点 使用RPM命令管理软件 安装 查询 升级 卸载 RPM命令常用参数 RPM命令 安装 RPM命令 卸载 RPM命令 升级 RPM 查询
  • jdbc原理与步骤

    jdbc原理 1 加载JDBC驱动 并将其注册到DriverManager 2 建立数据库连接 获取connection对象 3 建立Statement对象或PreparedStatement对象 4 执行SQL语句 5 访问结果集Resu
  • 送本书《Python 之旅》

    在线阅读 下载 在线阅读 https www bookstack cn books explore python 下载 关注公众号马上码回复 pythonzl Python 是一门面向对象 解释型的高级程序设计语言 它的语法非常简洁 优雅
  • 分析游戏《明日方舟》的成功要素

    明日方舟 这个出身并不显赫 玩法也绝非时下主流的游戏一经上线 就在一个月内连续霸榜 在正式上线一个月的时候 顺理成章地登顶App Store畅销榜榜首 简单介绍游戏信息与核心玩法 游戏名称 明日方舟 英文名称 Arknights 制作厂商
  • element-ui el-tree树形控件 默认箭头更改

    这是基础性 那么怎么修改呢 很简单只需要在css中修改 注意 vue中修改需要添加 deep el icon arrow right color 49c0ff el table el table expand icon el icon ar
  • 秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据

    秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据 多线程十大经典案例之一双线程读写队列数据 案例描述 MFC对话框中一个按钮的响应函数实现两个功能 显示数据同时处理数据 因此开两个线程 一个线程显示数据 开了一个定时器 响应W
  • jdk 16中改进的ZGC

    内存对象重定位的优化 预留堆空间 heap reserve 是堆空间中特殊的一块小空间 无法用于java线程的常规分配 而当发生gc时需要进行对象重分配时才会使用 此举确保了空的堆区域可用 即使是在java线程角度看堆空间已满 仍可进行对象
  • arch/x86/entry/syscall_64.o:(.rodata+0xa78): undefined reference to `sys_get_pid_info‘

    今天添加系统调用以后 使用make指令编译内核的时候出现了 arch x86 entry syscall 64 o rodata 0xa78 undefined reference to sys myprint 这个错误 错误原因是我使用的
  • SVN创建分支与合并分支

    SVN创建分支与合并分支 SVN忽略target文件夹 SVN创建分支 SVN合并分支 merge a range of revisions merge two different trees 合并分支总结 SVN忽略target文件夹 鼠
  • Web安全神器-Burpsuite社区版/专业版下载、安装及使用教程

    一 Burpsuite下载 Burp Suite是进行Web应用安全测试的一个集成平台 无缝融合各种安全工具并提供全面的接口适配 支持完整的Web应用测试流程 从最初的映射和应用程序的攻击面分析到发现和利用安全漏洞等领域均适用 同时还可以做
  • google浏览器chrome安装插件方法

    该方法适合安装到一台没有联网的机器上使用 1 在可联网的浏览器 可以用极速浏览器 上 打开扩展程序 搜到要安装的插件并安装 2 地址栏输入 chrome version 查看个人资料路径 该目录下的Extensions就是插件安装位置 3
  • 3D 重构的一些应用场景

    3D 重构是利用2D 照片合成3D 图像 3D重构也是人工智能领域的一个分支 因为业界有很多应用 所以记下来 供大家参考 第一次遇到3D重构的课题是老东家在物流领域的业务场景 后来发现 3D重构的应用场景还真不少 3D重构一个重要指标是精准
  • 移植lwIP至U-Boot

    原文地址 http www wl chuang com blog 2011 11 04 porting lwip to uboot U Boot是嵌入式系統上被廣為運用的boot loader 它擁有極為活躍的開發社群 也支援許多不同類型的