void halRfFlushRx(void) { /* Flush RX FIFO twice instead of once. See bug #1 in * http://www.ti.com/lit/er/swrz024/swrz024.pdf */ halRfDisableRxInterrupt(); CC2520_RXBUF8(); CC2520_INS_STROBE(CC2520_INS_SFLUSHRX); CC2520_INS_STROBE(CC2520_INS_SFLUSHRX); halRfEnableRxInterrupt(); }
/*********************************************************************************** * @fn halRfReceiveOn * * @brief Turn receiver on * * @param none * * @return none */ void halRfReceiveOn(void) { /* Flush RX FIFO if needed. * See bug #1 in http://www.ti.com/lit/er/swrz024/swrz024.pdf */ halRfDisableRxInterrupt(); CC2520_INS_STROBE(CC2520_INS_SFLUSHRX); uint8_t rx_fifo_cnt = CC2520_REGRD8(CC2520_RXFIFOCNT); CC2520_INS_STROBE(CC2520_INS_SRXON); if (rx_fifo_cnt != CC2520_REGRD8(CC2520_RXFIFOCNT)) { CC2520_INS_STROBE(CC2520_INS_SFLUSHRX); } halRfEnableRxInterrupt(); }
/*********************************************************************************** * @fn halRfReceiveOff * * @brief Turn receiver off * * @param none * * @return none */ void halRfReceiveOff(void) { /* Flush RX FIFO if needed. * See bug #1 in http://www.ti.com/lit/er/swrz024/swrz024.pdf */ halRfDisableRxInterrupt(); CC2520_INS_STROBE(CC2520_INS_SFLUSHRX); uint8_t rx_fifo_cnt = CC2520_REGRD8(CC2520_RXFIFOCNT); CC2520_INS_STROBE(CC2520_INS_SRFOFF); if (rx_fifo_cnt != CC2520_REGRD8(CC2520_RXFIFOCNT)) { CC2520_INS_STROBE(CC2520_INS_SFLUSHRX); // Software clean-up // Reset software for frame reception... } halRfEnableRxInterrupt(); }
//RF ISR void GPABC_IRQHandler(void){ if(GPIOB_ISRC&0x00000200UL){ disable_rf_int(); uz2400_isr_handler(); enable_rf_int(); } GPIOB_ISRC = GPIOB_ISRC; #if 0 if (EXTI_GetITStatus(EXTI_Line4) != RESET){ #ifdef SELECT_CC2520 halRfDisableRxInterrupt(); cc2520_isr_handler(); halRfEnableRxInterrupt(); #else //disable_rf_int(); uz2400_isr_handler(); //enable_rf_int(); #endif EXTI4_ClearBit(); } #endif }
/*********************************************************************************** * @fn halRfInit * * @brief Power up, sets default tuning settings, enables autoack and configures * chip IO * * @param none * * @return SUCCESS if the radio has started, FAILURE otherwise */ uint8 halRfInit(void) { regVal_t* p; uint8 val; // Avoid GPIO0 interrupts during reset halRfDisableRxInterrupt(); // Make sure to pull the CC2520 RESETn pin low CC2520_RESET_OPIN(0); CC2520_SPI_END(); chThdSleepMilliseconds(2); // Make sure MISO is configured as output. CC2520_MISO_DIR_OUT(); // Release reset CC2520_RESET_OPIN(1); // Wait for XOSC stable to be announced on the MISO pin if (halRfWaitRadioReady() == FAILED) { return FAILED; } // Write non-default register values p = regval; while (p->reg != 0) { CC2520_MEMWR8(p->reg, p->val); p++; } // ISR Thread chThdCreateStatic(waIsrTx, sizeof(waIsrTx), NORMALPRIO + 2, isrThread, NULL ); // Verify a register val = CC2520_MEMRD8(CC2520_MDMCTRL0); return val == 0x85 ? SUCCESS : FAILED; }
/*********************************************************************************** * @fn basicRfSendPacket * * @brief Send packet * * @param destAddr - destination short address * pPayload - pointer to payload buffer. This buffer must be * allocated by higher layer. * length - length of payload * txState - file scope variable that keeps tx state info * mpdu - file scope variable. Buffer for the frame to send * * @return basicRFStatus_t - SUCCESS or FAILED */ uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length) { uint8 mpduLength; uint8 status; // Turn on receiver if its not on if(!txState.receiveOn) { halRfReceiveOn(); } // Check packet length length = min(length, BASIC_RF_MAX_PAYLOAD_SIZE); // Wait until the transceiver is idle halRfWaitTransceiverReady(); // Turn off RX frame done interrupt to avoid interference on the SPI interface halRfDisableRxInterrupt(); mpduLength = basicRfBuildMpdu(destAddr, pPayload, length); #ifdef SECURITY_CCM halRfWriteTxBufSecure(txMpdu, mpduLength, length, BASIC_RF_LEN_AUTH, BASIC_RF_SECURITY_M); txState.frameCounter++; // Increment frame counter field #else halRfWriteTxBuf(txMpdu, mpduLength); #endif // Turn on RX frame done interrupt for ACK reception halRfEnableRxInterrupt(); // Send frame with CCA. return FAILED if not successful if(halRfTransmit() != SUCCESS) { status = FAILED; } // Wait for the acknowledge to be received, if any if (pConfig->ackRequest) { txState.ackReceived = FALSE; // We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished // The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small margin halMcuWaitUs((12 * BASIC_RF_SYMBOL_DURATION) + (BASIC_RF_ACK_DURATION) + (2 * BASIC_RF_SYMBOL_DURATION) + 10); // If an acknowledgment has been received (by RxFrmDoneIsr), the ackReceived flag should be set status = txState.ackReceived ? SUCCESS : FAILED; } else { status = SUCCESS; } // Turn off the receiver if it should not continue to be enabled if (!txState.receiveOn) { halRfReceiveOff(); } if(status == SUCCESS) { txState.txSeqNumber++; } #ifdef SECURITY_CCM halRfIncNonceTx(); // Increment nonce value #endif return status; }
/*********************************************************************************** * @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 * * @return none */ static void basicRfRxFrmDoneIsr(void) { basicRfPktHdr_t *pHdr; uint8 *pStatusWord; #ifdef SECURITY_CCM uint8 authStatus=0; #endif // Map header to packet buffer pHdr= (basicRfPktHdr_t*)rxMpdu; // Clear interrupt and disable new RX frame done interrupt 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 // Is this an acknowledgment packet? // Only ack packets may be 5 bytes in total. if (pHdr->packetLength == BASIC_RF_ACK_PACKET_SIZE) { // Read the packet halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength); // Make sure byte fields are changed from network to host byte order 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 status word and check for CRC OK pStatusWord= rxMpdu + 4; // Indicate the successful ACK reception if CRC and sequence number OK 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. 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); #endif // Make sure byte fields are changed from network to host byte order 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 pStatusWord= rxi.pPayload+rxi.length; #ifdef SECURITY_CCM pStatusWord+= BASIC_RF_LEN_MIC; #endif 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 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; } #endif } rxi.seqNumber = pHdr->seqNumber; } // Enable RX frame done interrupt again halIntOff(); halRfEnableRxInterrupt(); }