这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » [原创]lwip 到 lxRTOS 移植实现

共1条 1/1 1 跳转至

[原创]lwip 到 lxRTOS 移植实现

菜鸟
2007-05-21 05:57:25     打赏


lwip 到 lxRTOS 移植实现

一. 从 http://www.lx-rtos.com 下载 lxRTOS 最新版本, 从 http://download.savannah.nongnu.org/releases/lwip/ 下载 lwip 最新版本.
移植 lwip 需实现 cc.h cpu.h perf.h sys_arch.h 和 sys_arch.c 文件, 保存到 lwip-x.x.x/arch 目录下, 以下为这五个文件移植到 lxRTOS 上的实现.


二. cc.h 定义与体系结构环境, 编译器, 平台等相关的内容. 其中有 lwip 基本数据类型定义, 数据结构包装方法定义, 调试诊断和打印输出定义等. 通过 cc.h 使得 lwip 实现与平台无关.

#ifndef __ARCH_CC_H__
#define __ARCH_CC_H__

#include "../arch/cpu.h"
#include "../arch/sys_arch.h"

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

#define PACK_STRUCT_FIELD(x) x __attribute__((packed))
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END

extern void _dbg_print(const char* fmt, ...);

#define LWIP_PLATFORM_DIAG(x) do { _dbg_print x; } while(0)
#define LWIP_PLATFORM_ASSERT(x) do { _dbg_print("Assertion %s failed at line %d in %s\n", x, __LINE__, __FILE__); while(1); } while(0)
#define U16_F "u"
#define U32_F "u"
#define S16_F "d"
#define S32_F "d"
#define X16_F "X"
#define X32_F "X"

#endif /* __ARCH_CC_H__ */


三. cpu.h 定义与 CPU 相关的内容, 在这里定义有 CPU 的 endian.

#ifndef __ARCH_CPU_H__
#define __ARCH_CPU_H__

#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif /* BYTE_ORDER */

#endif /* __ARCH_CPU_H__ */


四. perf.h 定义特定体系结构下性能测量的操作, 在这里定义为空.

#ifndef __ARCH_PERF_H__
#define __ARCH_PERF_H__

#ifdef PERF
#else /* PERF */
#define PERF_START /* null definition */
#define PERF_STOP(x) /* null definition */
#endif /* PERF */

#endif /* __ARCH_PERF_H__ */


五. sys_arch.h 定义 lwip 线程, 轻量同步(开/关中断), 邮箱, 信号量等的数据类型.

#ifndef __ARCH_SYS_ARCH_H__
#define __ARCH_SYS_ARCH_H__

#define SYS_MBOX_NULL NULL
#define SYS_SEM_NULL NULL

typedef int sys_thread_t;
typedef int sys_prot_t;
typedef void* sys_mbox_t;
typedef void* sys_sem_t;

#endif /* __ARCH_SYS_ARCH_H__ */


六. sys_arch.c 为 lwip 移植的实现代码.

// 必要的头文件
#include "../arch/cc.h"
#include "../lwip/err.h"
#include "../lwip/sys.h"
#include "../lwip/pbuf.h"
#include "../lwip/mem.h"
#include "../lwip/memp.h"
#include "../lwip/stats.h"
#include "../lwip/ip_addr.h"
#include "../lwip/netif.h"
#include "../lwip/ip.h"
#include "../lwip/raw.h"
#include "../lwip/tcpip.h"
#include "../../lxRTOS-2.2.1/lxRTOS/lxRTOS.h"


// 网络接口与ip地址.
static struct netif _netif;
static struct ip_addr _ipaddr = { (205<<24) | (1<<16) | (168<<8) | (192<<0) };
static struct ip_addr _netmask= { (0<<24) | (255<<16) | (255<<8) | (255<<0) };
static struct ip_addr _gw = { (1<<24) | (1<<16) | (168<<8) | (192<<0) };

// 网络接口初始化和接口数据输入到lwip, 在 wip-x.x.x/netif/ethernetif.c 中实现.
extern void ethernetif_init(struct netif *netif);
extern void ethernetif_input(struct netif *netif, struct pbuf *p);

// 网卡初始化与网卡数据接收中断, 在网卡驱动程序中实现.
extern void eth_init(void);
extern void eth_rx(int irq, void *devid);

// 初始化网卡与网络接口.
err_t init_ethernetif(struct netif *netif)
{
// 初始化网卡.
eth_init();
// 初始化网络接口.
ethernetif_init(netif);
return ERR_OK;
}

// 接收网卡数据的线程.
void ethernet_rev(void *param)
{
handle_t mbox;
struct netif *netif;
struct pbuf *p;

// 将网络接口添加到lwip和设置网络接口的ip地址.
netif = netif_add(&_netif, &_ipaddr, &_netmask, &_gw,
Null, init_ethernetif, tcpip_input);

// 创建邮箱, 接收从网卡中断服务程序传过来的数据包.
mbox = (handle_t)CreateMailbox(8);
// 安装网卡中断服务程序, 第一个参数为中断向量号.
SetInterrupt(22, eth_rx, 0, (void *)mbox);

for(;;)
{
// 接收网卡数据包.
FetchMail(mbox, (void **)&p, -1);
// 数据包送到lwip处理.
ethernetif_input(netif, p);
}
}

// 初始化lwip.
void sys_init(void)
{
netif_init();
mem_init();
memp_init();
pbuf_init();
stats_init();
raw_init();
tcpip_init(Null, Null);
// 创建接收网卡数据的线程. 在这里使用单独的线程来执行 ethernetif_input().
sys_thread_new(ethernet_rev, (void *)0, TCPIP_THREAD_PRIO);
}

// 创建信号量, 调用lxRTOS直接创建信号量.
sys_sem_t sys_sem_new(u8_t count)
{
sys_sem_t sem = (sys_sem_t)CreateSemaphore(count, 1);
if(sem == Null)
{
_dbg_print("sys_sem_new() failed : %X\n", GetLastError());
return SYS_SEM_NULL;
}
return sem;
}

// 释放信号量资源, 相当于lxRTOS关闭信号量.
void sys_sem_free(sys_sem_t sem)
{
if(!CloseSemaphore((handle_t)sem))
_dbg_print("sys_sem_free() failed : %X\n", GetLastError());
}

// 使信号量发出信号, 相当于lxRTOS升起信号量.
void sys_sem_signal(sys_sem_t sem)
{
if(!UpSemaphore((handle_t)sem))
_dbg_print("sys_sem_signal() failed : %X\n", GetLastError());
}

// 等待信号量有信号, 相当于lxRTOS拉下信号量.
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
{
int result;
unsigned long wait;

// 把无穷大等待(timeout==0)从lwip形式改为lxRTOS形式.
if(timeout == 0)
timeout = (u32_t)-1;

// 等待信号量有信号.
wait = GetTickCount();
if((result = DownSemaphore((handle_t)sem, (int)timeout)) != OBJECT)
{
if(result < 0)
_dbg_print("sys_arch_sem_wait() failed : %X\n", GetLastError());
// 超时, 返回lwip形式超时.
return SYS_ARCH_TIMEOUT;
}
else
{
// 有信号, 计算已等待的时间.
// 将ticks数乘以CFG_MSEC_PER_TICK换算为ms.
wait = (GetTickCount() - wait) * CFG_MSEC_PER_TICK;
if(wait > timeout)
wait = timeout;
return (u32_t)wait;
}
}

// 创建邮箱, 调用lxRTOS直接创建邮箱.
sys_mbox_t sys_mbox_new(void)
{
// 创建邮箱
sys_mbox_t mbox = (sys_mbox_t)CreateMailbox(200);
if(mbox == Null)
{
_dbg_print("sys_mbox_new() failed : %X\n", GetLastError());
return SYS_MBOX_NULL;
}
return mbox;
}

// 释放邮箱资源, 相当于lxRTOS关闭邮箱.
void sys_mbox_free(sys_mbox_t mbox)
{
if(!CloseMailbox((handle_t)mbox))
_dbg_print("sys_mbox_free() failed : %X\n", GetLastError());
}

// 寄送消息, 相当于lxRTOS寄送消息.
void sys_mbox_post(sys_mbox_t mbox, void *msg)
{
// 第三个参数False, 指示邮箱满时, 不作强制插入.
if(!PostMail((handle_t)mbox, msg, False))
_dbg_print("sys_mbox_post() failed : %X\n", GetLastError());
}

// 提取消息, 相当于lxRTOS提取消息.
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
{
int result;
void *t_msg;
unsigned long wait;

// 把无穷大等待(timeout==0)从lwip形式改为lxRTOS形式.
if(timeout == 0)
timeout = (u32_t)-1;

// 提取消息
wait = GetTickCount();
if((result = FetchMail((handle_t)mbox, &t_msg, (int)timeout)) != OBJECT)
{
if(result < 0)
_dbg_print("sys_arch_mbox_free() failed : %X\n", GetLastError());
// 超时, 返回lwip形式超时.
return SYS_ARCH_TIMEOUT;
}
else
{
// 计算已等待的ticks数, 乘以CFG_MSEC_PER_TICK换算为ms.
wait = (GetTickCount() - wait) * CFG_MSEC_PER_TICK;
if(wait > timeout)
wait = timeout;
// 返回提取到的消息.
if(msg != Null)
*msg = t_msg;
return (u32_t)wait;
}
}

// 获得与lwip相关线程的超时链表.
struct sys_timeouts *sys_arch_timeouts(void)
{
handle_t handle;
struct sys_timeouts *timeouts;

// 获得当前线程句柄.
handle = GetCurrentThread();
// 获得线程的sys_timeouts
GetThreadData(handle, (unsigned int*)&timeouts);
if(timeouts == Null)
{
// 如果线程还没有sys_timeouts, 则分配一个.
timeouts = GlobalAlloc(sizeof(struct sys_timeouts));
timeouts->next = Null;
// 保存到线程中去.
SetThreadData(handle, (unsigned int)timeouts);
}
if(timeouts == Null)
_dbg_print("sys_arch_timeouts() failed : %X\n", GetLastError());
return timeouts;
}

// 创建lwip线程函数.
sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)
{
// 创建线程.
handle_t handle = CreateThread(8*1024, prio, (thread_t)thread, arg, False);

if(handle == Null)
// 创建失败.
return (sys_thread_t)-1;
// 创建成功.
return (sys_thread_t)handle;
}

#if SYS_LIGHTWEIGHT_PROT
// 关中断
sys_prot_t sys_arch_protect(void)
{
return (sys_prot_t)DisableInt();
}

// 开中断
void sys_arch_unprotect(sys_prot_t pval)
{
EnableInt((int)pval);
}
#endif


七. 在 lwip-x.x.x/netif/ethernetif.c 文件中添加网卡驱动程序.


八. lwip 的移植也可参见 lwip-x.x.x/doc/sys_arch.txt 文件中的介绍.




关键词: 原创     lxRTOS     移植     实现     #define     #    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]