BasicRF之中断接收basicRfRxFrmDoneIsr

由于appLight()的主循环一直在等待 接收中断完成,一旦有接收中断并接收完成则进行后续的数据处理,因此这里主要介绍一下接收中断服务子函数basicRfRxFrmDoneIsr(该函数指针在basicRfInit()被声明,详细介绍参看上一篇),具体代码如下:

 

 /***********************************************************************************

* @fn          basicRfRxFrmDoneIsr

*

* @brief       Interrupt service routine for received frame from radio

*              (either data or acknowlegdement)

*              //当无线信号有接收帧时执行中断服务子程序;

* @param      rxi - file scope variable info extracted from the last incoming

*                    frame

*              //最近一次接收帧信息;

*              txState - file scope variable that keeps tx state info

*              //发送状态信息,在中断服务子程序中主要在接收ACK中涉及;

* @return      none

*/

static void basicRfRxFrmDoneIsr(void)

{

    basicRfPktHdr_t *pHdr;  //帧头结构体指针;

    uint8 *pStatusWord;     //存储读RSSICRC信息;

    #ifdef SECURITY_CCM

    uint8 authStatus=0;

    #endif

 

// Map header to packet buffer

//帧头指针指向 所接收的MPDU数据单元;

//结构体间的强制类型转换,起始地址的指向;

    pHdr= (basicRfPktHdr_t*)rxMpdu;

 

// Clear interrupt and disable new RX frame done interrupt

//关闭通用RF中断  RXPKTDONE中断;

    halRfDisableRxInterrupt();

 

// Enable all other interrupt sources (enables interrupt nesting)

//始能总中断;(考虑默认优先级 其他中断)

    halIntOn();

 

// Read payload length.

//读取长度域的值;

    halRfReadRxBuf(&pHdr->packetLength,1);

pHdr->packetLength &= BASIC_RF_PLD_LEN_MASK; // Ignore MSB

                                     //最大程度为127字节,故忽略最高有效位;

   

// Is this an acknowledgment packet?

// Only ack packets may be 5 bytes in total.

//由于只有ACK帧的数据长度为5,所以可以通过  长度来判断该帧的类型:数据帧 or 应答帧;

    if (pHdr->packetLength == BASIC_RF_ACK_PACKET_SIZE) {

 

        // Read the packet

        //将接收数据 通过RFD从缓存中一个字节一个字节读出;

        halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength);

 

        // Make sure byte fields are changed from network to host byte order

        //将网络参数的高4位和低4位交换 ,由 无线网络格式 转换为 本地格式;

           UINT16_NTOH(pHdr->panId);

           UINT16_NTOH(pHdr->destAddr);

           UINT16_NTOH(pHdr->srcAddr);

        #ifdef SECURITY_CCM

        UINT32_NTOH(pHdr->frameCounter);

        #endif

 

        //读取应答帧帧的应答位信息,对于应答帧的FCF该位应该为0

        rxi.ackRequest = !!(pHdr->fcf0 & BASIC_RF_FCF_ACK_BM_L);

 

        // Read the status word and check for CRC OK

        //指向该帧的FCS;

        pStatusWord= rxMpdu + 4;

 

        // Indicate the successful ACK reception if CRC and sequence number OK

        //CRC校验位和帧序号无误,则将txState.ackReceived 设置为 TRUE,表示数据发送及对方节点接收完成;

        if ((pStatusWord[1] & BASIC_RF_CRC_OK_BM) && (pHdr->seqNumber == txState.txSeqNumber)) {

            txState.ackReceived = TRUE;

        }

 

        // No, it is data

    } else {

 

        // It is assumed that the radio rejects packets with invalid length.

        // Subtract the number of bytes in the frame overhead to get actual payload.

        //在灯开关例程中,默认 非应答帧长度的数据 皆为有效数据,即:假定非有效数据都被拒绝(假定很恶劣= =!);如果传输的数据长度是固定的可以更换 固定的长度条件,其他 长度的无线数据都不进行处理;

        //长度域的值减去(MHR+MFR)获得有效负载长度;

 

        rxi.length = pHdr->packetLength - BASIC_RF_PACKET_OVERHEAD_SIZE;

 

        #ifdef SECURITY_CCM

        rxi.length -= (BASIC_RF_AUX_HDR_LENGTH + BASIC_RF_LEN_MIC);

        authStatus = halRfReadRxBufSecure(&rxMpdu[1], pHdr->packetLength, rxi.length,

                                        BASIC_RF_LEN_AUTH, BASIC_RF_SECURITY_M);

        #else

        halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength); //将接收数据 通过RFD从缓存中一个字节一个字节读出;

        #endif

 

        // Make sure byte fields are changed from network to host byte order

        //将网络参数的高4位和低4位交换 ,由 无线网络格式 转换为 本地格式;

           UINT16_NTOH(pHdr->panId);

           UINT16_NTOH(pHdr->destAddr);

           UINT16_NTOH(pHdr->srcAddr);

        #ifdef SECURITY_CCM

        UINT32_NTOH(pHdr->frameCounter);

        #endif

 

        //读取该帧的应答位信息;

        rxi.ackRequest = !!(pHdr->fcf0 & BASIC_RF_FCF_ACK_BM_L);

 

        // Read the source address

        //读取源地址;

        rxi.srcAddr= pHdr->srcAddr;

 

        // Read the packet payload

        //读取净载荷数据;

        rxi.pPayload = rxMpdu + BASIC_RF_HDR_SIZE;

 

        // Read the FCS to get the RSSI and CRC

        //读取帧校验中的RSSICRC相关信息;

        pStatusWord= rxi.pPayload+rxi.length;

        #ifdef SECURITY_CCM

        pStatusWord+= BASIC_RF_LEN_MIC;

        #endif

       

        //读取RSSI的值;

        rxi.rssi = pStatusWord[0];

 

        // Notify the application about the received data packet if the CRC is OK

        // Throw packet if the previous packet had the same sequence number

        //根据CRC校验位来判定是否 为有效数据帧;

//其中,还要求对 帧序号 进行验证,如果该数据帧 要求有应答的情况下 在数据帧发送接收流程上不完整,帧序号连续两次相同的那么不对重复数据帧进行后续的处理,需要被丢弃;

//另外如果发送节点 确定数据被正确接收 可以采用连续发送两次,并根据 应答是否成功 来判断程序是否进行二次重复发送;

        if( (pStatusWord[1] & BASIC_RF_CRC_OK_BM) && (rxi.seqNumber != pHdr->seqNumber) ) {

            // If security is used check also that authentication passed

            #ifdef SECURITY_CCM

            if( authStatus==SUCCESS ) {

                if ( (pHdr->fcf0 & BASIC_RF_FCF_BM_L) ==

                    (BASIC_RF_FCF_NOACK_L | BASIC_RF_SEC_ENABLED_FCF_BM_L)) {

                        rxi.isReady = TRUE;

                }

            }

            #else

            if ( ((pHdr->fcf0 & (BASIC_RF_FCF_BM_L)) == BASIC_RF_FCF_NOACK_L) ) {

                rxi.isReady = TRUE;  //如果接收到的FCF满足无ACK位的条件,说明正确接收,将接收节点状态 设置为TRUE

                                    //其中BASIC_RF_FCF_NOACK_L = 0x61表示PANID一致而且该帧类型为 数据帧;

                                    //数据帧的通过验证的判断条件:1.CRC = OK 2.SeqNumber和上一次的不同;3.保持PANID  帧类型 一致;

            }             

            #endif

        }

 

        //帧序号在灯开关例程作用:

        //数据帧要求有应答的情况,应答成功→下一帧SeqNumber自加→(PANID  帧类型一致的条件下)下一帧进行的后期操作;然而 应答不成功→下一帧SeqNumber保持→rxi.isReady始终为FALSE下一帧无法进行后期处理,表现现象为对应节点发送的数据始终无法接收!

        //数据帧要求无应答的情况,下一帧SeqNumber始终自加,不会造成对应节点发送的数据无法接收的问题;

        //SeqNumber在灯开关例程作用始终是 ACK的成功与否来决定的,因此应该善于利用  ACK是否成功完成的条件!

        rxi.seqNumber = pHdr->seqNumber;  

    }

 

// Enable RX frame done interrupt again

//关闭总中断,会在 basicRfReceive() 复制完接收数据 后重新始能;

halIntOff();  //调用函数HAL_INT_OFF()

//#define HAL_INT_OFF(x)      st( EA = 0; )

//x的指向可以是空?

 

//始能通用RF中断  RXPKTDONE中断;

    halRfEnableRxInterrupt();

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值