导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→UcIP移植到ARM7上的体会[tomchen]

 *第47387篇: UcIP移植到ARM7上的体会

  
楼 主:tomchen 2007年4月24日14:16
 UcIP移植到ARM7上的体会

点击浏览该文件
uC/IP移植到ARM7+uCOS上的体会
                      深圳 陈小勇
uC/IP是由Guy Lancaster编写的一套基于uC/OS且开放源码的TCP/IP协议栈,是一套完全免费的、可供研究的TCP/IP协议栈。uC/IP具有如下一些特点:带身份验证和报头压缩支持的PPP协议,优化的单一请求/回复交互过程,支持 IP/TCP/UDP协议,可实现的网络功能较为强大,并可裁减。UCIP协议栈被设计为一个带最小化用户接口及可应用串行链路网络模块。根据采用CPU、编译器和系统所需实现协议的多少,协议栈需要的代码容量空间在30-60KB之间。本文介绍uC/IP移植到ARM7内核CPU上的一些体会。
本项目硬件使用ARM7 内核的CPU,通过串口连接GPRS通讯模块,使用PPP协议拨号上网,与主站软件之间使用TCP/IP通讯。硬件框架如图1。

                      UART接口

     图1

软件框架如图2。

图2

上网过程为:CPU通过UART接口与GPRS通讯模块通讯,通过拨号(例如:*99***1#)与移动通信运营商接入服务器连接,连接使用PPP协议;连接成功后,采用SOCKET接口,与主站软件之间使用TCP/IP协议通讯。大部分GPRS通讯模块内置TCP/IP协议栈,但采用uC/IP协议栈,可以使用所有GPRS通讯模块,也可以应用MODEM拨号的情况。
uC/IP协议栈的移植,主要有两个方面,一是与硬件驱动的接口,二是与应用程序的接口。先说与硬件驱动的接口。uC/IP应用于串口模式时,使用nGet()函数接收数据,nPut()函数发送数据,所以移植时要把修改这两个函数。例如这两个函数做如下修改:
void nGet(int fd, NBuf **returnHere, long delay)
{
// long time=mtime();
 int l,c;
// struct timeval timeout;
 NBuf *curNBuf,*head;

 nGET(curNBuf);
 if(!curNBuf)
  return ; 

 curNBuf->  len = 0;
 curNBuf->  nextBuf = NULL;
 head=curNBuf;

 l = 0;
 while(1)
 {
  if(GetUartOneByte(&curNBuf->  data[l]) != 0)
   break;
  l++;
  if(l >  = NBUFSZ)
   break;
 }
 
 if(l >   0)
 {
  curNBuf->  len=l;
  c=l;  
 }
 
 head->  chainLen=c;
 *returnHere=head;

 return;
}

void nPut(int fd, NBuf *head)
{
 NBuf *nb;

 for(nb=head; nb; nb=nFree(nb))
 {
  SendUartBytes (nb->  data, nb->  len);  
 }
}
其中int GetUartOneByte(unsigned char *pByte) 函数从串口缓冲区读一个字节数据,成功时返回0,不成功返回1。Void SendUartBytes(unsigned char *pBuf, int len)函数向串口发送指定字节的数据。
uC/IP协议栈工作于多任务模式时,定时检查要使用void timerCheck(void);函数。在uCOS系统中,需要在TimeTick中断中调用timeCheck()。可以将timeCheck()添加于OSTimeTickHook()函数中,如下
void OSTimeTickHook (void)
{
 timerCheck();
}

与应用程序的接口部份,首先是使用uC/IP之前的初始化。例如下面的代码就是做初试化的工作。
Interface myInterface; 

#define LOCAL_ADDRS   "192.168.0.10"
#define NETWORK_MASK  "255.255.255.0"
#define DEFAULT_ROUTE "210.22.12.56"

void StartupNet(const char *user, const char *password)
{    
 myInterface.addrs.localAddr = ntohl(inet_addr(LOCAL_ADDRS));    
 myInterface.addrs.subnetMask = ntohl(inet_addr(NETWORK_MASK)); 
 myInterface.addrs.gatewayAddr = ntohl(inet_addr(DEFAULT_ROUTE));    
myInterface.addrs.networkAddr
= myInterface.addrs.localAddr&myInterface.addrs.subnetMask;
 myInterface.BaseAddrs = 0x300;    
 myInterface.IRQNum = 10;          
 myInterface.arpExpire = 600;
 
 
    nBufInit();
 netInit(&myInterface);
    socketInit();
    

 netSetLogin(user, password);   
}
nBufInit()函数对uC/IP协议栈缓冲区初试化,netInit()对网络接口初始化,socketInit()对Socket接口初始化,netSetLogin()设置PPP拨号时的用户名与密码。
拨号成功后,GPRS通讯模块或Modem返回CONNECT字符,这样就可以调用pppOpen()函数进行PPP连接。PPP连接成功后,就可以调用Socket接口函数进行TCP/IP连接与通信。
Socket接口函数需要做修改,修改如下:
SOCKET socket(long af, short type, short protocol)
{
    int  i;
    int sd;
 
    for (i = 0; i   < MAX_SOCKET; i++) {
        if (allSocks[i].state == 0) {
            allSocks[i].protocol = protocol;
            allSocks[i].type = type;
            allSocks[i].af = af;
            allSocks[i].state = 1;
  switch(allSocks[i].type)
  {
   case SOCK_STREAM:
    sd = tcpOpen();
    if(sd >  = 0)
    {
     allSocks[i].sd = sd;
     return i;
    }
    break;
    
   case SOCK_DGRAM:
    sd = udpOpen();
    if(sd >  = 0)
    {
     allSocks[i].sd = sd;
     return i;
    }
    break;
   default:
    break;
  }
            
        }
    }
    return -1;
}
连接类型为TCP时,调用tcpOpen()函数,连接类型为UDP时,调用udpOpen ()函数。其它连接、发送、接收函数可以这样修改。
int  connect(SOCKET s, const struct sockaddr FAR *name, short namelen)
{
 int retval = 0;
 
 
    if (s >  = 0 && s   < MAX_SOCKET) 
    {
 if(allSocks[s].state == 1)
 {
        if (namelen == sizeof(struct sockaddr_in)) 
  {
              struct sockaddr_in FAR * sin = (struct sockaddr_in FAR *)name;
              CopyIP((InternetAdress FAR *)&sin->  ipAddr, &allSocks[s].hisIPAddr); 
              allSocks[s].hisPort = sin->  sin_port;
              allSocks[s].myPort = nextSourcePort++;
     
   switch(allSocks[s].type)
   {
    case SOCK_STREAM:
     retval = tcpConnectJiffy(allSocks[s].sd, sin, 0, allSocks[s].timeout);
     return retval;
    case SOCK_DGRAM:
     retval = udpConnect(allSocks[s].sd, sin, 0);
     return retval;
    default:
     break;
   }
        }
        }
    }
    return SOCKET_ERROR;
}

int  send(SOCKET s, const char FAR *buf, short len, short flags)
{
    int retval = 0;


    if (len   < 0) len = strlen(buf);
    if (s >  = 0 && s   < MAX_SOCKET) {
        switch (allSocks[s].type) {
        case SOCK_STREAM:
  retval = tcpWriteJiffy(allSocks[s].sd, buf, len, allSocks[s].timeout);
            break;
        case SOCK_DGRAM:
  retval = udpWrite(allSocks[s].sd, buf, len);
            break;
        default:
            break;
        }
    }
    return retval;
}


int  recv(SOCKET s, char FAR *buf, short len, short flags)
{
 int retval = 0;

    if (len   < 0) len = strlen(buf);
    if (s >  = 0 && s   < MAX_SOCKET) {
        switch (allSocks[s].type) {
        case SOCK_STREAM:
  retval = tcpReadJiffy(allSocks[s].sd, buf, len, allSocks[s].timeout);
            break;
        case SOCK_DGRAM:
  retval = udpRead(allSocks[s].sd, buf, len);
            break;
        default:
            break;
        }
    }
    return retval;
}

int  closesocket(SOCKET s)
{
 int retval = 0;
 
    if (s >  = 0 && s   < MAX_SOCKET) {
        allSocks[s].state = 0;
 switch (allSocks[s].type) {
        case SOCK_STREAM:
  retval = tcpClose(allSocks[s].sd);
  tcpStop(allSocks[s].sd);
            break;
        case SOCK_DGRAM:
  retval = udpClose(allSocks[s].sd);
            break;
        default:
            break;
        }
        return retval;
    }
    return SOCKET_ERROR;
}

  
2楼:gcc312628 2008年12月10日15:28
 hao

>>>>>>对该主题发表你的看法

本主题贴数2,分页: [第1页]


[上一篇主题]:招聘:深圳医疗设备公司招嵌入式/单片机软件开发工程师 多名

[下一篇主题]:赠送USB键盘、USB鼠标源代码