本文为这个系列文章的第一篇.
主要是为了记录学习博创的zigbee系统时的一些笔记.这是我第一次接触产品级的代码,确实在阅读源码时学到不少东西.
ZStack 是一个片上系统,cc2530使用片内一个flash存储这些代码和数据.关于这个系统的OSAL(Operating System Abstraction Layer),网上已经有很多分析.我就不多说了,本文只关心osal的api的使用,不关心它的实现原理.附 osal API 中文版:
(竟然只找到了中文版,我在ti官方都找不到相关文件)
zStack从zmain.c开始运行.
用merge对比官方例程的zmain.c发现主要在初始化时增加了一个函数.
/*********************************************************************
* @fn zmain_ram_init
* @brief Initialize ram for stack "high-water-mark" observations.
* @return none
*********************************************************************/
static void zmain_ram_init( void )
{
uint8 *end;
uint8 *ptr;
// Initialize the call (parameter) stack
end = (uint8*)CSTK_BEG; // Lower end
ptr = (uint8*)(*( __idata uint16*)(CSTK_PTR)); // Upper end
while ( --ptr > end )
*ptr = STACK_INIT_VALUE;
// Initialize the return (address) stack
ptr = (uint8*)RSTK_END - 1; // Upper end
while ( --ptr > (uint8*)SP )
*(__idata uint8*)ptr = STACK_INIT_VALUE;
}
对比官方demo和up的sampleApp.c文件,up工程在SampleApp_Init 初始化中增加了从flash读取节点类型和设备类型
NodeHead = NULL;
gSensorMode = 0x01; //00 查询模式 01 中断模式,自动上报信息
gIntFlag = 0x00; //no interrupt
gDevType = CheckDeviceType();
gSensorType = CheckSensorType(); //在初始化的时候设置 "传感器类型" 全局变量 //add by @wei
if(gSensorType == (sensor_t)SENSOR_SHT11)
{ Sht11Init(); }
else if(gSensorType == (sensor_t)SENSOR_SET)
{
//HalLedBlink( HAL_LED_2, 4, 50, (1000 / 4) );
//HalLedBlink( HAL_LED_3, 4, 50, (1000 / 4) );
SensorSetIO();
}
else
{ SensorIO_Init(); }
MT_UartRegisterTaskID( SampleApp_TaskID ); //add by 1305106
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
// Received when a messages is received (OTA) for this endpoint
case AF_INCOMING_MSG_CMD:
HalLedBlink( HAL_LED_1, 4, 50, (1000 / 4) ); //receive message -> blink led //@wei zigbee网络
SampleApp_MessageMSGCB( MSGpkt ); //This function processes any incoming data - probably from other devices.
break;
case SPI_INCOMING_ZAPP_DATA:
SampleApp_ProcessMTMessage(MSGpkt); //receive uart data 重点
MT_UartAppFlowControl (MT_UART_ZAPP_RX_READY);
break;
// Received whenever the device changes state in the network
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)
|| (SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
HalLedSet(HAL_LED_2, HAL_LED_MODE_ON);
}
else
{
// Device is no longer in the network
}
break;
default:
break;
}
osal_msg_deallocate( (uint8 *)MSGpkt ); // Release the memory
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); // Next - if one is available
}
return (events ^ SYS_EVENT_MSG); // return unprocessed events
}
if ( events & SAMPLEAPP_SEND_SENSOR_INT_EVT )
{
SampleApp_Process_SENSOR_INT();
return ( events ^ SAMPLEAPP_SEND_SENSOR_INT_EVT);
}
if ( events & SAMPLEAPP_CMD_RESET_RSP_EVT )
{
SystemReset();
//return ( events ^ SAMPLEAPP_SEND_SENSOR_INT_EVT);
}
return 0; // Discard unknown events
}
串口数据处理函数
void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg)
{
Config_CmdProcessing((uint8*)msg); //接收来自串口的 配置命令
NodeInfo_CmdProcessing((uint8*)msg); //接收来自串口的 节点处理命令
}
//afIncomingMSGPacket_t 结构体如下
typedef struct
{
osal_event_hdr_t hdr; /* OSAL Message header */
uint16 groupId; /* Message's group ID - 0 if not set */
uint16 clusterId; /* Message's cluster ID */
afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,
it's an InterPAN message */
uint16 macDestAddr; /* MAC header destination short address */
uint8 endPoint; /* destination endpoint */
uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */
uint8 LinkQuality; /* The link quality of the received data frame */
uint8 correlation; /* The raw correlation value of the received data frame */
int8 rssi; /* The received RF power in units dBm */
uint8 SecurityUse; /* deprecated */
uint32 timestamp; /* receipt timestamp from MAC */
afMSGCommandFormat_t cmd; /* Application Data */
} afIncomingMSGPacket_t;
void Config_CmdProcessing(uint8 *pBuf)
{
uint16 cmd;
uint8 *pData = pBuf+MT_RPC_POS_CMD1;
/*************--cmd frame format--****************/
/*** | sop | cmd | len | data | fcs | ***/
/*** | 1 | 2 | 1 | len | 1 | ***/
cmd = BUILD_UINT16( pData[2], pData[1] );
switch(cmd)
{
case CONFIG_CMD_SET_DEV_TYPE_REQ:
Config_ProcessSetDevTypeReq(pData); break;
//最终调用了osal_nv_write 把接收数据保存到flash
}
其中 MT_RPC_POS_CMD1 的值为 2 .一开始很奇怪明明afIncomingMSGPacket_t 结构体的真正数据在最后一个,按一字节对齐来算怎么也不可能只是指针位置+2..我猜测可能是串口接收数据过程中,数据被保存到afIncomingMSGPacket_t 结构体,见此函数
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
每个事件数据分配的内存可能是不一样的.但是都统一当成afIncomingMSGPacket_t 指针来处理.最终处理时再强制转化为字节数组.
命令处理同理.
void NodeInfo_CmdProcessing(uint8 *pBuf)
{
uint16 cmd;
uint8 *pData = pBuf+MT_RPC_POS_CMD1;
/*************--cmd frame format--****************/
/*** | sop | cmd | len | data | fcs | ***/
/*** | 1 | 2 | 1 | len | 1 | ***/
cmd = BUILD_UINT16( pData[2], pData[1] );
switch(cmd)
{
case NODEINFO_CMD_NWK_CONNECT_REQ:
NodeInfo_ProcessNwkConnectReq(pData); break;
case NODEINFO_CMD_GET_NWK_DESP_REQ:
NodeInfo_ProcessGetNwkDespReq(pData); break;
case NODEINFO_CMD_GET_NWK_TOPO_REQ:
NodeInfo_ProcessReportOutNode(); //通过zigbee网络传递请求
NodeInfo_ProcessGetNwkTopoReq(pData); break;
//...
}
//这个函数从zigbee节点数据链表中提取每个节点短地址,并分别转发NODEINFO_CMD_GET_NWK_TOPO_REQ 请求.
//至于这个链表什么时候建立的 在后面的代码讲到
void NodeInfo_ProcessReportOutNode( void )
{
pNode p;
uint8 nwkaddr[2];
for (p = NodeHead; p!=NULL ; p = p->next)
{
if(p->status == 0x00){
p->times++; // out flag
//HalUARTWrite ( 0, "\r\nout\r\n", 7 );
}
if((p->status == 0x00)&&(p->times==3)){
p->times=0;
//MT report out node status.!!!
nwkaddr[0] = HI_UINT16(p->nwkaddr);
nwkaddr[1] = LO_UINT16(p->nwkaddr);
SampleApp_BuildAndSendZToolResponse(NODEINFO_CMD_RPT_NODEOUT_RSP, 2, nwkaddr);//建立发送请求(类似一个模板)
//Delay(5000);
}
// reset node's status
p->status = 0x00;
}
}
uint8 SampleApp_SendNwkData(uint16 nwkAddr, uint8 clusterId, uint8 *data, uint8 dataLen)
{
if(nwkAddr == 0xFFFF)
SampleApp_General_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
else
SampleApp_General_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SampleApp_General_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_General_DstAddr.addr.shortAddr =nwkAddr;
if ( AF_DataRequest( &SampleApp_General_DstAddr, &SampleApp_epDesc,//真正的发送函数.
clusterId,
dataLen,
data,
&SampleApp_TransID,// transfer id
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
//....
}