之前将UIP0.9移植到CC2530上,是裸机移植的,由于项目需要,前几天将UIP0.9移植到Z-STACK中,并且系统能稳定运行,即实现了一个简单的TCP/IP+ZIGBEE的网关或者无线接入点。下面简要阐述下移植过程及运行结果。
说明一下,我的Z-STACK版本ZStack-CC2530-2.2.2-1.3.0,用的是SimpleApp例程,在移植之前需要熟悉SimpleApp中的SimpleCollector和SimpleSensor实验,以及UIP0.9的cc2530裸机移植实验。最重要的是要熟悉
Z-STACK中事件驱动OSAL的运行机制和流程,这样才知道在哪些地方添加需要的代码。
首先,在该项目的source目录里面添加uip和uip_app目录,并在这两个目录分别添加一下源文件
uip目录中的文件均为uip0.9源码包里面的文件,uip_app目录中两个文件自己添加,然后分别将这些文件添加到工程。将enc28j60的驱动程序文件命名为hal_net.c,为了和Z-STACK中的驱动文件名字保持一致,相应添加一个头文件
hal_net.h,这两个文件在之前移植过程都有,只不过改了名字,略做修改而已。再分别将这两个文件添加进Z-STACK的驱动目录中,即driver目录中,相应路径为
C:\Texas Instruments\ZStack-CC2530-2.2.2-1.3.0\Components\hal\target\CC2530EB
然后打开SimpleCollectorEB工程,如下图所示
然后在相关文件中做一些修改。在一个大工程项目中,条件编译用的很多,为了和Z-STACK中保持一致,在
hal_board_cfg.h添加如下代码
#ifndef HAL_NET
#define HAL_NET TRUE
#endif
#ifndef UIP
#define UIP TRUE
#endif
当不需要网络功能就可以将这写注释掉。
然后在sapi.c文件SAPI_Init函数添加如下代码
void SAPI_Init( byte task_id )
{
uint8 startOptions;
#if (defined UIP)&&(UIP == TRUE)
uip_init(); //uip初始化
example1_init(); //uip应用程序初始化
#endif
sapi_TaskID = task_id;
sapi_bindInProgress = 0xffff;
sapi_epDesc.endPoint = zb_SimpleDesc.EndPoint;
sapi_epDesc.task_id = &sapi_TaskID;
.....
}
当然别忘了添加头文件
#if (defined UIP)&&(UIP == TRUE)
#include "uip.h"
#include "app.h"
#endif
在hal_driver.c文件HalDriverInit()函数中末尾添加如下代码(记住是末尾添加,不能在开始添加,否则会有问题,我刚开始是放在开头的,结果出现调试不出结果,这个问题我也找了半天原因,先不说哈!)
#if (defined HAL_NET) && (HAL_NET == TRUE)
HalNetInit(); //网络芯片驱动的初始化
#endif
需要在这个HalNetInit()中添加 HalSpiInit()函数,因为我用的是enc28j60网络芯片,其与cc2530的IO相连接,用的IO模拟SPI接口,所以这里面要初始化这几个IO。
同样在该文件 Hal_ProcessPoll ()函数中添加如下代码:(这个最好在开头添加,因为网络数据包处理要及时)
/* Net data Poll */
#if (defined HAL_NET) && (HAL_NET == TRUE)
HalNetDataPoll();
#endif
这个 HalNetDataPoll()函数是什么呢?我在里面添加了如下代码
uint8 i;
uint16 j;
uip_len = dev_poll();
for(j=0;j<500;j++);
if(uip_len==0)
{
for(i = 0; i < UIP_CONNS; i++)
{
uip_periodic(i);
if(uip_len>0)
{
uip_arp_out();
dev_send();
}
}
if(++arptimer == 20)
{
uip_arp_timer();
arptimer = 0;
}
}
else
{
if(BUF->type == htons(UIP_ETHTYPE_IP))
{
uip_arp_ipin();
uip_input();
if(uip_len > 0)
{
uip_arp_out();
dev_send();
}
}
else if(BUF->type == htons(UIP_ETHTYPE_ARP))
{
uip_arp_arpin();
if(uip_len>0)
{
dev_send();
}
}
}
其实大家对这部分代码应该相当熟悉了,对!这就是移植uip到cc2530中main函数里面的大while(1)循环里面的代码。 因为Hal_ProcessPoll ()函数是系统轮询用的,每次for循环都会调用这个函数,所以HalNetDataPoll()每次都会得到调用以进行网络数据包的及时处理。这个是移植过程的关键部分。我之前试过用事件驱动机制将这个while循环的内容分解掉,将其放在Z-stack中的不同部分,但是发现效果极差,什么看不到想要的结果!可能是哪儿拆分的不合理!但是这种方式使能看到网络通信的结果的。
另外就是数据类型的定义,在uip和z-stack中的定义是不同,这个很容易处理!还有就是头文件,这个在编译出错时进行相应添加!
最后就是uip.c文件,这个需要自己写,我的代码如下
void example1_init()
{
uip_listen(HTONS(1234));
}
#if 1
void example1_appcall()
{
switch(uip_conn->lport) {
case HTONS(1234):
if(uip_timedout()||uip_aborted()||uip_closed()){
/*reconnect to server*/
//delay_sec(5);
}else if(uip_connected()){
#if 1
/*is connected ok*/
uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
"Hello,I connected to you! thanks."));
#endif
}else if(uip_rexmit()){
#if 1
/*need retransmission last packet*/
uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
"this is retransmission packet"));
#endif
}else if(uip_poll()){
/*poll connecte is idle*/
#if 1
// uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
// "Hi, we are idle"));
//uip_send("idle",4);
uip_send(buf,32);
#endif
}else if(uip_acked()){
/*get a ack for send packet ok*/
#if 0
uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
"this is a second packet."));
#endif
if(uip_newdata()){
goto newdata_with_acked;
}
}else if(uip_newdata()){
newdata_with_acked:
#if 1
/*receving a new data*/
uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
"this is a second packet."));
#endif
}else{
/*error*/
}
break;
default:
/*discard packet*/
break;
}
}
#endif
上面代码中有一个数组buf,这个是在SimpleCollector.c文件中定义的,因为buf为zigbee网络中的数据接收缓冲区,一旦接收到数据,就将这些数据发送以太网中。然后编译链接,这其中不乏出现各种问题,需要自己去一一解决。
接下来看一下实验运行的结果
这是一个ZigBee模块打开时出现的结果,因为此时zigbee网络中还没有数据,所以此时buf一直为Battery:(我将buf初始化为Battery:),所以看到了以上结果。然后打开另一个zigbee模块,可以看到这个运行结果:
看到了么,结果发生变化了,网络调试助手接收到了从无线网络中发过来的数据,这是cc2530内部温度传感器的数据!同时将串口助手打开看到:
看到这个结果说明移植是成功的!哈哈!离完成项目又进了一步!
PS:在之前裸机移植uIP0.9到cc2530上,发现移植web服务器时出了一个很怪异的问题!这个问题困扰了很久了!从理论上分析根本不会出现这个问题,但是实践中可能会漏洞百出。等解决了这个问题再贴出来!相信很多同学都遇到了这个问题!