在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
芯片精品文章合集(500篇!) 创芯人才网--重磅上线啦!
查看: 3340|回复: 1

lwip 到 lxRTOS 移植实现

[复制链接]
发表于 2007-5-21 13:25:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
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 文件中的介绍.
发表于 2007-6-22 22:08:47 | 显示全部楼层

好东西啊,一定要好好学习天天向上才对得起楼主啊

好东西啊,一定要好好学习天天向上才对得起楼主啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条


小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-1-9 22:49 , Processed in 0.020255 second(s), 12 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表