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(); }
/*********************************************************************************** * @fn halRfInit * * @brief Power up, sets default tuning settings, enables autoack, enables random * generator. * * @param none * * @return SUCCESS always (for interface compatibility) */ uint8 halRfInit(void) { uint8 i; // turning on power to analog part of radio and waiting for voltage regulator. RFPWR = 0x04; while( RFPWR & 0x10 ); // Setting for AUTO CRC and AUTOACK MDMCTRL0L |= (AUTO_CRC | AUTO_ACK); // Turning on AUTO_TX2RX FSMTC1 = ((FSMTC1 & (~AUTO_TX2RX_OFF & ~RX2RX_TIME_OFF)) | ACCEPT_ACKPKT); // Turning off abortRxOnSrxon. FSMTC1 &= ~0x20; // Set FIFOP threshold to maximum IOCFG0 = 0x7F; // tuning adjustments for optimal radio performance; details available in datasheet */ RXCTRL0H = 0x32; RXCTRL0L = 0xF5; // Turning on receiver to get output from IF-ADC ISRXON(); halMcuWaitUs(1); // Enable random generator ADCCON1 &= ~0x0C; for(i = 0 ; i < 32 ; i++) { RNDH = ADCTSTH; // Clock random generator ADCCON1 |= 0x04; } ISRFOFF(); // Enable CC2591 with High Gain Mode halPaLnaInit(); halRfEnableRxInterrupt(); return SUCCESS; }
/*********************************************************************************** * @fn halRfInit * * @brief Power up, sets default tuning settings, enables autoack, enables random * generator. * * @param none * * @return SUCCESS always (for interface compatibility) */ uint8 halRfInit(void) { // Enable auto ack and auto crc FRMCTRL0 |= (AUTO_ACK | AUTO_CRC); // Recommended RX settings TXFILTCFG = 0x09; AGCCTRL1 = 0x15; FSCAL1 = 0x00; // Enable random generator -> Not implemented yet // Enable CC2591 with High Gain Mode halPaLnaInit(); // Enable RX interrupt halRfEnableRxInterrupt(); return SUCCESS; }
//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 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(); }