📄 unet.c
字号:
{
ChiPtr->Available = 1;
UnetSys.Flag.GP0 = 1;
}
goto TX_ASSO_RSP_LABEL; //在子节点链表里找到发送连接申请的节点的地址,则直接应答,不用再申请空间存储该节点信息
}
ChiPtr = ChiPtr->Next; //如果该子节点地址与收到的连接请求帧子地址不一样,则切换到下一个子节点进行比较
}
//Check CAPACITY
if(MsgPtr->Cap & 0x02) //判断该设备是否完整功能设备
{ // Router
if(UnetSys.JoinRouterCnt + UnetSys.JoinEndevCnt >= UNET_MAX_CHILD || UnetSys.JoinRouterCnt >= UNET_MAX_ROUTER)
{ //如果连接的设备个数已经超限
RsPtr->ShortAddr = 0xffff; //应答帧里分配的短地址设定为该值表示拒绝连接请求
RsPtr->AssoStatus = PAN_AT_CAPACITY;
//UnetSys.Flag.ChildFull = 1;
goto TX_ASSO_RSP_LABEL;
}
UnetSys.JoinRouterCnt++;
}
else //非完整功能设备
{ // End device
if(UnetSys.JoinRouterCnt + UnetSys.JoinEndevCnt >= UNET_MAX_CHILD)
{
RsPtr->ShortAddr = 0xffff;
RsPtr->AssoStatus = PAN_AT_CAPACITY;
//UnetSys.Flag.ChildFull = 1;
goto TX_ASSO_RSP_LABEL;
}
UnetSys.JoinEndevCnt++;
}
//Allocate address
RsPtr->ShortAddr = UnetSys.NextAddr; //分配短地址
stAddrList.MACAddress[stAddrList.ucAddrCont] = UnetSys.NextAddr; //将地址添加到地址列表中
stAddrList.LifeTime[stAddrList.ucAddrCont] = 20000; //
stAddrList.ucAddrCont ++;
RsPtr->AssoStatus = ASSOCIATION_SUCCESS; //连接成功状态
UnetSys.NextAddr += UnetSys.AddrInc;
for(i=0;i<stAddrList.ucAddrCont;i++) //判断地址是否已经被使用
{
if( UnetSys.NextAddr == stAddrList.MACAddress[i] )
{
UnetSys.NextAddr += UnetSys.AddrInc;
i = 0;
continue;
}
}
//Add new entry and update information
if(insert_node((void *) &UnetSys.ChildHead, (void *) &UnetSys.ChildTail, CHILD ) == NULL)
return FAILURE; //申请新的节点信息存储空间
//初始化新的末尾节点的数据
UnetSys.ChildTail->Cap = MsgPtr->Cap;
UnetSys.ChildTail->NetworkAddress = RsPtr->ShortAddr;
UnetSys.ChildTail->Available = 1;
UnetSys.ChildTail->Next = NULL;
MSG_Copy(UnetSys.ChildTail->MacAddr, MsgPtr->SrcAddr, 8);
TX_ASSO_RSP_LABEL: //发送连接响应命令帧
RsPtr->Header.val = 0x8c23;
RsPtr->Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
RsPtr->SrcAddr = UnetSys.NwkAddr;
RsPtr->SrcPID = UnetSys.JoinPID;
RsPtr->DstPID = UnetSys.JoinPID;
RsPtr->COMM_ID = MT_ASSO_RSP;
MSG_Copy(RsPtr->DstAddr, MsgPtr->SrcAddr, 8);
if(UzTx(RF_TX_BUFF, sizeof(MCP_ASSO_RSP)))
{
if(UnetSys.Flag.GP0)
goto TX_PBACK_LABEL;
return SUCCESS;
}
return RETRY_EXCEED;
TX_PBACK_LABEL:
UnetSys.Flag.GP0 = 0; //Clear flag
return unet_tx_pback(ChiPtr->NetworkAddress);
}
void unet_rx_asso_rsp(MCP_ASSO_RSP *RsPtr)
{
UnetSys.Flag.RecvAssoRsp = 1;
#ifdef CONSOLE
printf("Join PANid: %2x, Join Status: %x\r\n", RsPtr->SrcPID, RsPtr->AssoStatus);
#endif
if(RsPtr->AssoStatus == ASSOCIATION_SUCCESS){
//UnetSys.Status = JOIN_SUCCESS;
UnetSys.Flag.AssoSuccess = 1;
UnetSys.NwkAddr = RsPtr->ShortAddr;
#ifdef CONSOLE
printf("Parent: %2x, NwkAddr: %2x\r\n", RsPtr->SrcAddr, RsPtr->ShortAddr);
#endif
}
return;
}
UINT8 unet_check_child(UINT16 NwkAddr, struct _child_list_ **CurrPtr){
struct _child_list_ *ChildPtr;
DBG_tag();
ChildPtr = UnetSys.ChildHead;
while(ChildPtr != NULL){
if(ChildPtr->NetworkAddress == NwkAddr){
if(CurrPtr)
*CurrPtr = ChildPtr;
if(ChildPtr->Available){
return SUCCESS;
}
break;
}
ChildPtr = ChildPtr->Next;
}
return FAILURE;
}
UINT8 unet_tree_routing(MAC_DATA_PKT *MsgPtr){
UINT16 NextAddr, Cskip, A, D;
A = UnetSys.NwkAddr;
D = MsgPtr->NwkDstAddr;
Cskip = compute_Cskip(UnetSys.DevDep -1); //Cskip(d-1)
if((D > A) && (D < (A + Cskip))){ //if destination is my descendant? ( A<D<A+compute_Cskip(d-1)), 2.7.3.3
Cskip = compute_Cskip(UnetSys.DevDep);
NextAddr = (A + 1) + ((D - (A + 1)) / Cskip) * Cskip;
if(NextAddr < UnetSys.NextAddr){ // if next hop addr alread allocate?
if(unet_check_child(NextAddr, NULL)) {
MsgPtr->MHR.DstAddr = NextAddr;
return FOUND_NEXT_HOP;
}
}
return NEXT_HOP_NOT_AVAILABLE;
}
if(UnetSys.Flag.PanCoordinator)
return TREE_ROUTING_FAILED;
MsgPtr->MHR.DstAddr = UnetSys.JoinParent; // Send to parent
return SEND_TO_PARENT;
}
UINT8 unet_rx_data_ind(MAC_DATA_PKT *MsgPtr, UINT8 Length)
{
struct _broadcast_list_ *BroPtr;
UINT8 i,*TmPtr;
DBG_tag();
//Check destination
if(MsgPtr->NwkDstAddr == 0xffff)
{ // if broadcast
if(MsgPtr->NwkSrcAddr == UnetSys.NwkAddr) // This broadcast issued by devself.
return DISCARD_FRAME;
BroPtr = UnetSys.BroHead;
while(BroPtr != NULL)
{
if(BroPtr->Address == MsgPtr->NwkSrcAddr)
{
//if(MsgPtr->MHR.Seqnum > BroPtr->Sequence || (MsgPtr->MHR.Seqnum < 5 && BroPtr->Sequence >250)){ // Compare sequence number
if(MsgPtr->MHR.Seqnum != BroPtr->Sequence)
{ // Compare sequence number
BroPtr->Sequence = MsgPtr->MHR.Seqnum;
goto SEND_TO_QUEUE_LABEL;
}
return DISCARD_FRAME;
}
BroPtr = BroPtr->Next;
}
if(insert_node((void *) &UnetSys.BroHead, (void *) &UnetSys.BroTail, BROADCAST ) == NULL) // Add new entry
return FAILURE;
UnetSys.BroTail->Address = MsgPtr->NwkSrcAddr;
UnetSys.BroTail->Sequence = MsgPtr->MHR.Seqnum;
UnetSys.BroTail->Next = NULL;
goto SEND_TO_QUEUE_LABEL;
}
else if(MsgPtr->NwkDstAddr == UnetSys.NwkAddr)
{ // if devself
UnetSys.Flag.GP0 = 1; // Set flag, indicate it will do only SEND_TO_QUEUE
goto SEND_TO_QUEUE_LABEL;
}
else
{ // Both not , routing
i = unet_tree_routing(MsgPtr);
if(i == NEXT_HOP_NOT_AVAILABLE)
{ //Check the destination if allready link to devself by self-healing
MsgPtr->MHR.DstAddr = MsgPtr->NwkDstAddr; // Send to the child directly
}
else if(i == TREE_ROUTING_FAILED)
{
return DISCARD_FRAME;
}
goto TX_DATA_PKT_LABEL;
}
SEND_TO_QUEUE_LABEL:
DBG_tag();
if(UnetSys.DataCnt < 5)
{ // Max Data Packets were buffered.
if(insert_node((void *) &UnetSys.DataHead, (void *) &UnetSys.DataTail, DATA ) == NULL) // Add new entry
return FAILURE;
UnetSys.DataTail->Length = Length - sizeof(MAC_DATA_PKT) -2; // 2:FCS
if((UnetSys.DataTail->Msg = (UINT8 *) MSG_Alloc(UnetSys.DataTail->Length)) == NULL)
return FAILURE;
UnetSys.DataTail->SrcAddr = MsgPtr->NwkSrcAddr;
UnetSys.DataTail->Next = NULL;
TmPtr = (UINT8 *) MsgPtr;
MSG_Copy(UnetSys.DataTail->Msg, (TmPtr + sizeof(MAC_DATA_PKT)), UnetSys.DataTail->Length);
UnetSys.DataCnt++;
}
if(UnetSys.Flag.GP0)
{
UnetSys.Flag.GP0 = 0;
return SUCCESS;
}
TX_DATA_PKT_LABEL:
DBG_tag();
if(MsgPtr->Radius >0)
{
MsgPtr->Radius -= 1;
MsgPtr->MHR.SrcAddr = UnetSys.NwkAddr;
if(UzTx((UINT8 *) MsgPtr,Length -2))
return SUCCESS;
if(!UnetSys.Flag.PanCoordinator)
{
if(MsgPtr->MHR.DstAddr == UnetSys.JoinParent)
{
if(unet_self_healing() == SELF_HEAL_SUCCESS)
goto TX_DATA_PKT_LABEL;
return SELF_HEAL_FAILED; //Coordinator die
}
}
}
return DISCARD_FRAME;
}
void unet_active_scan(BOOL AUTO)
{
UINT8 TempChannel, i;
TempChannel = UnetSys.Channel;
UzRxOnlyBeacon();
if(AUTO)
{
for(i=11; i<=26; i++)
{ // Scan all channel
UnetSys.Channel = i;
UzSetChannel(i); // set channel
while(!unet_tx_bcn_req())
{ // Issue beacon request
WaitMS(10);
}
//WaitUS(aBaseSuperframeDuration*UnetSys.SO*16); // aBaseSuperframeDuration X 2eSO X 16us
WaitMS(UNET_SCAN_WAIT_TIME);
}
}
else
{
UzSetChannel(UnetSys.Channel); // set channel
while(!unet_tx_bcn_req()); // Issue beacon request
//WaitMS(1967); // aBaseSuperframeDuration X 2eSO (2e7 = 128) X 16us
WaitMS(UNET_SCAN_WAIT_TIME);
}
unet_proc(); //Process all beacon frame in queue
UzRxAllFrame();
UnetSys.Channel = TempChannel;
}
/*********************************** Self - Healing *******************************************/
/*
UINT8 unet_tx_rebpan(){
MAC_CMD_PKT *CmdPtr;
UINT8 i;
CmdPtr = (MAC_CMD_PKT *) RF_TX_BUFF;
CmdPtr->MHR.Header.val = 0x8803;
CmdPtr->MHR.DstAddr = 0xffff;
CmdPtr->MHR.DstPID = UnetSys.JoinPID;
CmdPtr->MHR.SrcAddr = UnetSys.NwkAddr;
CmdPtr->MHR.SrcPID = UnetSys.JoinPID;
CmdPtr->MHR.Seqnum = UnetSys.MacDSN;
//UnetSys.MacDSN++;
CmdPtr->COMM_ID = MT_REBPAN;
for(i=0; i< UNET_MAX_RETRY; i++) {
if(UzTx(RF_TX_BUFF, sizeof(MAC_CMD_PKT), 0)) return SUCCESS;
}
return RETRY_EXCEED;
}
UINT8 unet_rx_rebpan(){
}
*/
UINT8 unet_tx_disasso(UINT8 *DST_MAC){
MCP_DISASSO_NTF *DisPtr;
DBG_tag();
DisPtr = (MCP_DISASSO_NTF *) RF_TX_BUFF;
DisPtr->Header.val = 0x8c23;
DisPtr->Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
DisPtr->SrcAddr = UnetSys.NwkAddr;
DisPtr->SrcPID = UnetSys.JoinPID;
DisPtr->DstPID = UnetSys.JoinPID;
MSG_Copy(DisPtr->DstAddr, DST_MAC, 8);
DisPtr->COMM_ID = MT_DISASSO_NTF;
DisPtr->DisassoReason = 0x01; // The coordinator or router wishes the device to leave the PAN.
return UzTx(RF_TX_BUFF, sizeof(MCP_DISASSO_NTF));
}
UINT8 unet_rx_disasso(MAC_CMD_PKT *CmdPtr){
if(CmdPtr->MHR.SrcAddr == UnetSys.JoinParent){
INIT_UNET();
return JOIN_UNET(UNET_PAN_ID, UNET_CHANNEL);
}
return DISCARD_FRAME;
}
UINT8 unet_tx_ipop(UINT16 NNParent, UINT16 NParent){
MCP_IPOP *FpoPtr;
FpoPtr = (MCP_IPOP *) RF_TX_BUFF;
FpoPtr->MHR.Header.val = 0x8823;
FpoPtr->MHR.DstAddr = NNParent;
FpoPtr->MHR.DstPID = UnetSys.JoinPID;
FpoPtr->MHR.SrcAddr = UnetSys.NwkAddr;
FpoPtr->MHR.SrcPID = UnetSys.JoinPID;
FpoPtr->MHR.Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
FpoPtr->COMM_ID = MT_IPOP;
FpoPtr->Parent = NParent;
return UzTx(RF_TX_BUFF, sizeof(MCP_IPOP));
}
UINT8 unet_rx_ipop(MCP_IPOP *MsgPtr){
struct _child_list_ *Ptr = NULL;
unet_check_child(MsgPtr->Parent, &Ptr);
if(Ptr != NULL)
Ptr->Available = 0;
return SUCCESS;
}
UINT8 unet_tx_cback()
{
MCP_CBACK *CBptr;
CBptr= (MCP_CBACK *) RF_TX_BUFF;
CBptr->MHR.Header.val = 0x8823;
CBptr->MHR.DstAddr = UnetSys.JoinParent;
CBptr->MHR.DstPID = UnetSys.JoinPID;
CBptr->MHR.SrcAddr = UnetSys.NwkAddr;
CBptr->MHR.SrcPID = UnetSys.JoinPID;
CBptr->MHR.Seqnum = UnetSys.MacDSN;
CBptr->COMM_ID = MT_CBACK;
CBptr->Cap = 0xca;
MSG_Copy(CBptr->MacAddr, MAC_ADDRESS, 8);
return UzTx(RF_TX_BUFF, sizeof(MCP_CBACK));
}
UINT8 unet_rx_cback(MCP_CBACK *Msg){
UINT8 i;
struct _child_list_ *Cptr = NULL;
//Check if any other device use the same address
unet_check_child(Msg->MHR.SrcAddr, &Cptr);
if(Cptr !=NULL){ // find exist entry
unet_tx_disasso(Cptr->MacAddr);
Cptr->NetworkAddress = Msg->MHR.SrcAddr;
Cptr->Cap = Msg->Cap;
Cptr->Available = 1;
for(i=0; i<8; i++){
Cptr->MacAddr[i] = Msg->MacAddr[i];
}
}else{
if(Msg->Cap & 0x02){
UnetSys.JoinRouterCnt++;
}else{ // End device
UnetSys.JoinEndevCnt++;
}
if(insert_node((void *) &UnetSys.ChildHead, (void *) &UnetSys.ChildTail, CHILD ) == NULL) // Add new entry
return FAILURE;
UnetSys.ChildTail->Cap = Msg->Cap;
UnetSys.ChildTail->NetworkAddress = Msg->MHR.SrcAddr;
UnetSys.ChildTail->Available = 1;
UnetSys.ChildTail->Next = NULL;
MSG_Copy(UnetSys.ChildTail->MacAddr, Msg->MacAddr, 8);
UnetSys.NextAddr = Msg->MHR.SrcAddr + UnetSys.AddrInc; // Update Address allocate
}
return SUCCESS;
}
UINT8 unet_tx_pback(UINT16 NwkAddr){
MCP_PBACK *PBptr;
PBptr = (MCP_PBACK *) RF_TX_BUFF;
PBptr->MHR.Header.val = 0x8803;
PBptr->MHR.DstAddr = 0xffff;
PBptr->MHR.DstPID = UnetSys.JoinPID;
PBptr->MHR.SrcAddr = UnetSys.NwkAddr;
PBptr->MHR.SrcPID = UnetSys.JoinPID;
PBptr->MHR.Seqnum = UnetSys.MacDSN;
UnetSys.MacDSN++;
PBptr->COMM_ID = MT_PBACK;
PBptr->Parent = NwkAddr;
return UzTx(RF_TX_BUFF, sizeof(MCP_PBACK));
}
UINT8 unet_rx_pback(MCP_PBACK *Msg)
{
struct _broadcast_list_ *BroPtr;
if(UnetSys.OrigParent == Msg->Parent)
{
UnetSys.JoinParent = UnetSys.OrigParent;
BroPtr = UnetSys.BroHead;
while(BroPtr != NULL)
{
if(BroPtr->Address == UnetSys.JoinParent)
{
BroPtr->Sequence = 0;
break;
}
BroPtr = BroPtr->Next;
}
return unet_tx_cback();
}
return DISCARD_FRAME;
}
UINT8 unet_self_healing(){
UINT8 Depth, Retry = 3;
UINT16 NParent, NNParent;
Depth = UnetSys.DevDep;
NParent = UnetSys.JoinParent;
while(Depth > 1 && Retry >0){
NNParent = compute_Parent(Depth, NParent);
if(unet_tx_ipop(NNParent, NParent)){ // Send indicate parent of parent
UnetSys.OrigParent = UnetSys.JoinParent;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -