📄 unet.c
字号:
/*******************************************************************************
UBEC (Uniband Electronic Corp.)
Project: U-NET01, Ubiquitous network platform
File: unet.c
Version: 0.1.2
Usage: Unet api & unet sub function
Platform: U-NET01 DK with IAR 8051 C compiler
Reference:
Silicon Laboratories: C8051F124
UBEC: UZ2400
Note :
Copyright (C) 2007 Uniband Electronic Corporation, All rights reserved
********************************************************************************/
#include ".\zigbee\unet.h"
UNET_SYS UnetSys;
UINT8 MAC_ADDRESS[8] = {0x11, 0x11, 0x18, 0x11, 0xaa, 0xbb, 0xcc, 0xdd};
MSG_QUEUE CommQueue; // Mac command queue
MSG_QUEUE DataQueue; // Mac data queue
UINT8 RF_RX_BUFF[128+16]; // RF receive buffer
UINT8 RF_TX_BUFF[128]; // RF transmit buffer
/*******************************************************************************/
void unet_active_scan(BOOL AUTO);
UINT8 unet_tx_bcn_req(void);
UINT8 unet_tx_asso_req(void);
UINT16 compute_Cskip(INT8 depth);
UINT16 compute_Parent(INT8 depth, UINT16 Parent);
void unet_init();
UINT8 unet_check_child(UINT16 NwkAddr, struct _child_list_ **CurrPtr);
UINT8 unet_tree_routing(MAC_DATA_PKT *MsgPtr);
INT8 unet_queue_proc(UINT8 frequency, MSG_QUEUE *QueuePtr);
void unet_proc(void);
UINT8 unet_self_healing();
UINT8 unet_tx_pback(UINT16 NwkAddr);
void clear_table(void **HeadAddr);
void *insert_node(void **HeadAddr, void **TailAddr, UINT8 Type);
/*******************************************************************************
Unet Function
********************************************************************************/
void INIT_UNET(){
#ifdef CONSOLE
// InitUART(); // Uart Initial
#endif
InitSPI(); //SPI Initial
UzInit(); //RF Initial
#ifdef PAOPEN
UzEnablePA();
#endif
UzSetMacAddress(MAC_ADDRESS); //MAC Address
unet_init(); //UNET Initial
// EnabMcuInt(); //Interrupt
}
UINT8 ESTABLISH_UNET(UINT16 PanId, UINT8 Channel)
{
struct _beacon_list_ *TmPtr;
if(PanId > 0x3fff)
return PANID_INVALID;
if(Channel > 26 || Channel < 11)
return CHANNEL_INVALID;
UnetSys.JoinPID = PanId;
UnetSys.Channel = Channel;
unet_active_scan(0); // Active Scan
TmPtr = UnetSys.BcnHead;
while(TmPtr != NULL){ // Check received beacon
if(TmPtr->Channel == Channel && TmPtr->PID == PanId)
return PAN_ID_CONFLICT;
TmPtr = TmPtr->Next;
}
UnetSys.NwkAddr = UNET_COORD_ADDRESS; // Coordinator default address
UnetSys.DevDep = 0;
UnetSys.NextAddr = UnetSys.NwkAddr + 1;
UnetSys.AddrInc = compute_Cskip(UnetSys.DevDep);
UnetSys.BcnPayload.DevDep = UnetSys.DevDep;
UnetSys.BcnPayload.EndevCap = 1;
UnetSys.BcnPayload.ProtID = 0;
UnetSys.BcnPayload.ProtVer = 0x01;
UnetSys.BcnPayload.StackPro = 0;
UnetSys.BcnPayload.RouterCap = 1;
UnetSys.BcnPayload.Rvd0 = 0;
UnetSys.Flag.JoinNetwork = 1;
UnetSys.Flag.PanCoordinator = 1;
UnetSys.Coordinator = 1;
clear_table((void *) &UnetSys.BcnHead);
UzSetPanId(PanId);
UzSetChannel(Channel);
UzSetNwkAddr(UnetSys.NwkAddr);
UzSetCoordinator();
return SUCCESS;
}
UINT8 JOIN_UNET(UINT16 PanId, UINT8 Channel)
{
struct _beacon_list_ *BcnPtr;
UINT8 rssi = 0, count = 0, State;
if(PanId > 0x3fff)
return PANID_INVALID;
if(Channel > 26 || Channel < 11)
return CHANNEL_INVALID;
UnetSys.JoinPID = PanId;
UnetSys.Channel = Channel;
UzSetPanId(PanId);
//UzSetChannel(Channel);
while(1)
{
unet_active_scan(0); // Active Scan
BcnPtr = UnetSys.BcnHead;
while(BcnPtr != NULL)
{
if(BcnPtr->Channel == Channel && BcnPtr->PID == PanId && (BcnPtr->SfSpec & 0x8000) && BcnPtr->LinkQuality > rssi && BcnPtr->DevDep < UNET_MAX_DEPTH)
{
rssi = BcnPtr->LinkQuality;
UnetSys.JoinParent = BcnPtr->Addr;
UnetSys.DevDep = BcnPtr->DevDep + 1;
UnetSys.Flag.FindNetwork = 1;
}
BcnPtr = BcnPtr->Next;
}
if(UnetSys.Flag.FindNetwork)
{
UnetSys.Flag.FindNetwork = 0; //Clear flag
clear_table((void *) &UnetSys.BcnHead);
//UzSetPanId(PanId);
UzSetChannel(Channel);
while(!unet_tx_asso_req()) // Send association request
WaitMS(20);
while(!UnetSys.Flag.RecvAssoRsp) // Wait association response
unet_proc();
UnetSys.Flag.RecvAssoRsp = 0; // Clear flag
if(UnetSys.Flag.AssoSuccess)
{ //Check associate result
UnetSys.Flag.AssoSuccess = 0; // Clear flag
UnetSys.NextAddr = UnetSys.NwkAddr + 1;
UnetSys.AddrInc = compute_Cskip(UnetSys.DevDep);
UnetSys.BcnPayload.DevDep = UnetSys.DevDep;
UnetSys.BcnPayload.EndevCap = 1;
UnetSys.BcnPayload.ProtID = 0;
UnetSys.BcnPayload.ProtVer = 0x01;
UnetSys.BcnPayload.StackPro = 0;
UnetSys.BcnPayload.RouterCap = 1;
UnetSys.BcnPayload.Rvd0 = 0;
UnetSys.Flag.JoinNetwork = 1;
UnetSys.Flag.Router = 1;
UnetSys.Coordinator = 0;
UzSetNwkAddr(UnetSys.NwkAddr);
return SUCCESS;
}
return FAILURE;
}
else
{
count ++;
if(count > 5)
{
State = ESTABLISH_UNET( PanId, Channel );
if(State != SUCCESS)
{
return State;
}
break;
}
}
}
return SUCCESS;
}
UINT8 SEND_TO_UNET(UINT16 DstAddr, UINT8 *DataPtr, UINT8 Length)
{
MAC_DATA_PKT *TxPtr;
UINT8 i;
TX_DATA_LABEL:
if(Length > MAC_MAX_DATA_PAYLOAD_LENGTH -3)
return DATA_TOO_LONG; // 3: Radius, Network Source address and Destination address
TxPtr = (MAC_DATA_PKT *) RF_TX_BUFF;
TxPtr->MHR.Header.val = 0x8801;
TxPtr->MHR.Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
TxPtr->MHR.DstPID = UnetSys.JoinPID;
TxPtr->MHR.SrcPID = UnetSys.JoinPID;
TxPtr->MHR.SrcAddr = UnetSys.NwkAddr;
TxPtr->Radius = UNET_MAX_DEPTH*2;
TxPtr->NwkDstAddr = DstAddr;
TxPtr->NwkSrcAddr = UnetSys.NwkAddr;
if(DstAddr == 0xffff)
{
TxPtr->MHR.DstAddr = 0xffff; //广播地址
}
else if(DstAddr == UnetSys.NwkAddr)
{
return DEST_IS_DEVSELF;
}
else
{
i = unet_tree_routing(TxPtr);
if(i == NEXT_HOP_NOT_AVAILABLE)
{ //Check the destination if allready link to devself by self-healing
//if(!unet_check_child(TxPtr->NwkDstAddr, NULL))
// return NEXT_HOP_NOT_AVAILABLE; // The destination does not link to devself
TxPtr->MHR.DstAddr = TxPtr->NwkDstAddr; // Send to the child directly
}
else if(i == TREE_ROUTING_FAILED)
{
return TREE_ROUTING_FAILED;
}
TxPtr->MHR.Header.val |= 0x0020;
}
MSG_Copy(&RF_TX_BUFF[sizeof(MAC_DATA_PKT)], DataPtr, Length);
if(UzTx(RF_TX_BUFF, sizeof(MAC_DATA_PKT) + Length)) return SUCCESS;
#ifndef I_Am_Coordinator
if(TxPtr->MHR.DstAddr == UnetSys.JoinParent)
{
if(unet_self_healing() == SELF_HEAL_SUCCESS)
goto TX_DATA_LABEL;
return SELF_HEAL_FAILED; //Coordinator die
}
#endif
return NEXT_HOP_NOT_AVAILABLE;
}
UINT8 RECV_FROM_UNET(UINT8 *Buff){
struct _data_list_ *TmPtr;
UINT8 Length;
if(UnetSys.DataCnt >0)
{
TmPtr = UnetSys.DataHead;
Length = TmPtr->Length;
MSG_Copy(Buff, TmPtr->Msg, Length);
UnetSys.DataHead = TmPtr->Next;
UnetSys.DataCnt -= 1;
MSG_Free(TmPtr->Msg);
MSG_Free(TmPtr);
return Length;
}
return 0;
}
UINT8 CHECK_UNET_DATA(){
unet_proc();
return UnetSys.DataCnt;
}
/*******************************************************************************
Unet Sub Function
********************************************************************************/
void unet_init(){
void *Temp;
UINT8 *p;
UnetSys.JoinPID = 0xffff; //Join pan id
UnetSys.Channel = 0xff; // Join channel
UnetSys.JoinParent = 0xffff; // Join parent address
UnetSys.OrigParent = 0xffff;
UnetSys.JoinRouterCnt = 0; // Join router count
UnetSys.JoinEndevCnt = 0; // Join end device count
UnetSys.NwkAddr = 0xffff; // Network address (short address)
UnetSys.DevDep = 0xff; // Device depth
UnetSys.NextAddr = 0xff; // Next available short address
UnetSys.AddrInc = 0xff; // Address increment
UnetSys.MacBSN = 0; // Mac broadcast sequence number
UnetSys.MacDSN = 0; // Mac packet (Data or Command) sequence number
*((UINT8 *) &UnetSys.IntFlag) = 0; // Interrupt Flag
// *((UINT16 *) &UnetSys.Flag) = 0; // System Flag
p = ((UINT8 *) &UnetSys.Flag); // System Flag
*p = 0; // System Flag
*(p+1) = 0;
MSG_Init(&CommQueue);
MSG_Init(&DataQueue);
UnetSys.BcnHead = NULL;
clear_table((void *) &UnetSys.BcnHead);
clear_table((void *) &UnetSys.ChildHead);
UnetSys.ChildHead = NULL;
clear_table((void *) &UnetSys.BroHead);
UnetSys.BroHead = NULL;
while(UnetSys.DataHead != NULL){
Temp = (void *) UnetSys.DataHead; // Temp = Head->Next
UnetSys.DataHead = ((struct _data_list_ *) Temp)->Next; // Head = Temp-Next
MSG_Free(((struct _data_list_ *) Temp)->Msg);
MSG_Free(Temp);
}
UnetSys.DataHead = NULL;
UnetSys.DataCnt = 0;
stAddrList.ucAddrCont = 0;
stCommandCFM.val = 0;
}
UINT8 unet_tx_bcn(){
MAC_BCN_PKT *BcnPtr;
//if(UnetSys.Flag.ChildFull)
// return DISCARD_FRAME;
BcnPtr = (MAC_BCN_PKT *) RF_TX_BUFF;
BcnPtr->Header.val = 0x8000;
BcnPtr->SrcAddr = UnetSys.NwkAddr;
BcnPtr->SrcPID = UnetSys.JoinPID;
BcnPtr->Seqnum = UnetSys.MacBSN;
UnetSys.MacBSN++;
BcnPtr->GTSF = 0;
BcnPtr->PASF = 0;
MSG_Copy(&BcnPtr->PAYLOAD, &UnetSys.BcnPayload, sizeof(MAC_BP));
if(UnetSys.Flag.PanCoordinator){
BcnPtr->SFS = 0xc00f;
}else if(UnetSys.Flag.Router){
BcnPtr->SFS = 0x800f;
}
if(UzTx(RF_TX_BUFF, sizeof(MAC_BCN_PKT)))
return SUCCESS;
return RETRY_EXCEED;
}
UINT8 unet_tx_bcn_req(void){
MCP_BCN_REQ *CmdPtr;
CmdPtr = (MCP_BCN_REQ *) RF_TX_BUFF;
CmdPtr->Header.val = 0x0803;
CmdPtr->DstAddr = 0xffff;
CmdPtr->DstPID = 0xffff;
CmdPtr->Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
CmdPtr->COMM_ID = MT_BEACON_REQ;
if(UzTx(RF_TX_BUFF, sizeof(MCP_BCN_REQ)))
return SUCCESS;
return RETRY_EXCEED;
}
UINT8 unet_rx_bcn_ind(MAC_BCN_PKT *BcnPkt, UINT8 Length){
UINT8 *TmPtr;
//if(UnetSys.Flag.JoinNetwork){
// if realiment??
//}
TmPtr = (UINT8 *) BcnPkt;
DBG_tag();
if(insert_node((void *) &UnetSys.BcnHead ,(void *) &UnetSys.BcnTail, BEACON ) == NULL)
return FAILURE;
UnetSys.BcnTail->PID = BcnPkt->SrcPID;
UnetSys.BcnTail->Addr = BcnPkt->SrcAddr;
UnetSys.BcnTail->Channel = UnetSys.Channel;
UnetSys.BcnTail->SfSpec = BcnPkt->SFS;
UnetSys.BcnTail->DevDep = BcnPkt->PAYLOAD.DevDep;
//// UnetSys.BcnTail->LinkQuality = *(TmPtr+ sizeof(MAC_BCN_PKT) + 3); // 2 + 1 = FCS + LQI, (LinkQuality = RSSI)
UnetSys.BcnTail->LinkQuality = UzReadRSSI();
UnetSys.BcnTail->Next = NULL;
return SUCCESS;
}
UINT8 unet_tx_asso_req(void){
MCP_ASSO_REQ *AssoPtr;
DBG_tag();
AssoPtr = (MCP_ASSO_REQ *) RF_TX_BUFF;
AssoPtr->Header.val = 0xc823;
AssoPtr->SrcPID = UnetSys.JoinPID;
MSG_Copy(AssoPtr->SrcAddr, MAC_ADDRESS, 8);
AssoPtr->DstAddr = UnetSys.JoinParent;
AssoPtr->DstPID = UnetSys.JoinPID;
AssoPtr->Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
AssoPtr->COMM_ID = MT_ASSO_REQ;
//AssoPtr->Cap.val = 0xca;
AssoPtr->Cap = 0xca;
if(UzTx(RF_TX_BUFF, sizeof(MCP_ASSO_REQ)))
return SUCCESS;
return RETRY_EXCEED;
}
/****************************************************************************************
* Function:
* Description: 处理连接请求命令帧
* Syntax:
* Modify:
* parameter: 无
* Returns: 无
* Notes:
* Date: 2007-04-03
* Author: ZijianWang
****************************************************************************************/
UINT8 unet_rx_asso_req(MCP_ASSO_REQ *MsgPtr)
{
struct _child_list_ *ChiPtr;
MCP_ASSO_RSP *RsPtr;
UINT8 i;
DBG_tag();
RsPtr = (MCP_ASSO_RSP *) RF_TX_BUFF;
ChiPtr = UnetSys.ChildHead;
while(ChiPtr != NULL) //如果当前子节点指针里有东西,(即存在子节点)
{
if(memcmp(ChiPtr->MacAddr, MsgPtr->SrcAddr, 8) == 0) //且该子节点地址与收到的连接请求帧子地址一样
{
RsPtr->ShortAddr = ChiPtr->NetworkAddress;
RsPtr->AssoStatus = ASSOCIATION_SUCCESS;
if(ChiPtr->Available == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -