lwip 移植到新平台指南
参考
https://lwip.fandom.com/wiki/Porting_for_an_OS
总则
cc.h(定义平台相关的宏) 和 sys_arch.h( sys_arch.c 里面实现 sys_arch.h 里面导出的接口) 两个头文件承担起 lwip源码 和 平台相关实现 之间 的 衔接。
cc.h
一、依赖关系
include/lwip/arch.h 里面 include 了 arch/cc.h 头文件
也只有 arch.h 里面inlucde arch/cc.h
其他地方,需要 processor and compiler 相关的参数时,请 include lwip/arch.h 它是 ”Support for different processor and compiler architectures“
二、需要提供的内容
1、Data types 数据类型
u8_t
, u16_t
, u32_t
s8_t
, s16_t
, s32_t
mem_ptr_t
: A generic pointer type. It has to be an integer type (not void*, due to some pointer arithmetics). 必须为 整形, 不能是 void * 类型,因为需要对 mem_ptr_t 做算术运算。
2、printf formatters - 格式化字符
U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F
3、Byte ordering 字节序
3.1 字节序定义
#define BYTE_ORDER LITTLE_ENDIAN or #define BYTE_ORDER BIG_ENDIAN |
3.2 如果是 小端字节序,可以自定义 字节序反转 接口
#define LWIP_PLATFORM_BYTESWAP 1 #define LWIP_PLATFORM_HTONS(x) ( (((u16_t)(x))>>8) | (((x)&0xFF)<<8) ) #define LWIP_PLATFORM_HTONL(x) ( (((u32_t)(x))>>24) | (((x)&0xFF0000)>>8) \ | (((x)&0xFF00)<<8) | (((x)&0xFF)<<24) ) |
4、Computing cheksums 计算校验和的方法
有三种计算方法
- load byte by byte, construct 16 bits word and add: not efficient for most platforms
- load first byte if odd address, loop processing 16 bits words, add last byte.
- load first byte and word if not 4 byte aligned, loop processing 32 bits words, add last word/byte.
通过宏定义选择
#define LWIP_CHKSUM_ALGORITHM 2
也可以使用自己的校验和计算方法
u16_t my_chksum(void *dataptr, u16_t len); #define LWIP_CHKSUM my_chksum |
5、Structure packing 结构体对齐
PACK_STRUCT_BEGIN, PACK_STRUCT_FIELD, PACK_STRUCT_STRUCT and PACK_STRUCT_END should be included in cc.h.
需要 4 个宏定义
Only PACK_STRUCT_STRUCT is required,
lwip/src/include/lwip/arch.h provides empty defaults for the others.
只有 PACK_STRUCT_STRUCT 是必须自己定义的。其他的三个,在 lwip/arch.h 里面,会补充定义为空。
Optionally you can also define PACK_STRUCT_USE_INCLUDES and provide bpstruct.h and epstruct.h.
可选的,你也可以 定义 PACK_STRUCT_USE_INCLUDES 宏,并提供 bpstruct.h and epstruct.h 文件。
6、Platform specific diagnostic output 调试诊断输出方法
|
sys_arch.h
一、依赖关系
如果没有定义宏 NO_SYS ,则会在
include/lwip/sys.h 中include arch/sys_arch.h
也只在这儿 include 一次,
不要在其他地方直接 include arch/sys_arch.h 。 使用 sys.h 即可,它是 os abstract layer 接口。
二、需要提供的内容
0、sys_arch.h 里面的类型和宏
类型
sys_sem_t
, sys_mbox_t
, sys_thread_t
sys_prot_t
宏定义
SYS_MBOX_NULL
, SYS_SEM_NULL
1、Preemption protection 抢占保护
lwip 中使用 下面三个宏进行 抢占保护
The macros used in lwip are:
SYS_ARCH_PROTECT(x)
: Begin a block of protection. Should generally return the previous state.SYS_ARCH_UNPROTECT(x)
: End a block of protection, restoring the protection state back to "x".SYS_ARCH_DECL_PROTECT(x)
: Declare the variable "x" to hold the protection. Used so you can specify what data type the protection will require.
在
为 lwipopts.h 中定义 宏
SYS_LIGHTWEIGHT_PROT1
.
在 sys_arch.h / sys_arch.c 中提供 1 个数据类型和2个函数
sys_prot_t 数据类型
sys_prot_t sys_arch_protect(); 函数
sys_arch_unprotect( sys_prot_t x) 函数
2、 Semaphores 信号量
数据类型 sys_sem_t,空信号
SYS_SEM_NULL
信号量操作函数
|
3、Mailboxes 邮箱
数据类型 sys_mbox_t,空邮箱
SYS_MBOX_NULL
邮箱操作函数
|
4、Threads 线程
类型
sys_thread_t
函数
sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
5、 struct sys_timeouts
结构体
struct sys_timeouts {xx};
函数
struct sys_timeouts *sys_arch_timeouts(void)
空的默认实现
struct sys_timeouts lwip_system_timeouts = NULL; // Default timeouts list for lwIP struct sys_timeouts *sys_arch_timeouts(void) { return &lwip_system_timeouts; } |
和thread 一起使用时的注意事项
If you do use threads, then you will need to give each thread its own sys_timeouts structure, and return that depending on what thread calls this function.
需要给每个 thread 一个 linked list of sys_timeouts .
函数sys_arch_timeouts(void) 需要根据调用的 thread 返回对应的 sys_timeouts list。下面是示例
struct thread_struct_wrapper { struct thread_struct_wrapper *next; MY_OS_THREAD_TYPE thread; // not a ptr in this example, but the actual space struct sys_timeo *timeouts; }; struct sys_timeouts lwip_system_timeouts = NULL; // Default timeouts list for lwIP struct thread_struct_wrapper *lwip_system_threads = NULL; // a list of all threads created by lwIP sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) { sys_thread_t newthread; SYS_ARCH_DECL_PROTECT(old_val); newthread = malloc(sizeof(struct thread_struct_wrapper)); // allocate the space for the thread wrapper if (newthread==NULL) return NULL; SYS_ARCH_PROTECT(old_val); // Need to protect this -- preemption here could be a problem! newthread.next = lwip_system_threads; lwip_system_threads = newthread; SYS_ARCH_UNPROTECT(old_val); newthread.timeouts = NULL; // initialize the linked list to NULL my_system_os_create_thread_function(&newthread.thread, thread, arg, prio); // create it, however my OS does it return newthread; } struct sys_timeouts *sys_arch_timeouts(void) { sys_thread_t thread = lwip_system_threads; MY_OS_THREAD_TYPE *self = my_system_os_get_current_thread(); // Search the threads list for the thread that is currently running for ( ; thread!=NULL; thread=thread->next) { if (thread->thread == self) return thread->timeouts; } // No match, so just return the system-wide default version return &lwip_system_timeouts; } |
6、sys_arch.c 实现注意事项
6.1 sys_sem_new()
中不要调用 mem_malloc 函数。
因为 mem_init 函数里面 调用了 了 sys_sem_new 函数,如果 sys_sem_new 中再调用 mem_malloc ,则 mem_malloc 在 mem_init 之前被调用。