概述
由于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; //存储读RSSI和CRC信息;
#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
//读取帧校验中的RSSI和CRC相关信息;
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();
}
最后
以上就是忧郁可乐为你收集整理的BasicRF之中断接收basicRfRxFrmDoneIsr的全部内容,希望文章能够帮你解决BasicRF之中断接收basicRfRxFrmDoneIsr所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复