static void flushrx(void) { uint8_t dummy; FASTSPI_READ_FIFO_BYTE(dummy); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); rxptr = 0; }
int8_t rf_polling_rx_packet() { uint8_t tmp; #ifdef RADIO_PRIORITY_CEILING nrk_sem_pend(radio_sem); #endif if(FIFOP_IS_1 ) { uint16_t frameControlField; int8_t length; uint8_t pFooter[2]; uint8_t checksum,rx_checksum,i; last_pkt_encrypted=0; // FASTSPI_STROBE(CC2420_SRXON); // FASTSPI_STROBE(CC2420_SFLUSHRX); // while(!SFD_IS_1); // XXX Need to make sure SFD has gone down to be sure packet finished! // while(SFD_IS_1); // Clean up and exit in case of FIFO overflow, which is indicated by FIFOP = 1 and FIFO = 0 if((FIFOP_IS_1) && (!(FIFO_IS_1))) { // always read 1 byte before flush (data sheet pg 62) FASTSPI_READ_FIFO_BYTE(tmp); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return -1; } // Payload length FASTSPI_READ_FIFO_BYTE(length); length &= RF_LENGTH_MASK; // Ignore MSB // Ignore the packet if the length is too short if(length<=0) { // always read 1 byte before flush (data sheet pg 62) FASTSPI_READ_FIFO_BYTE(tmp); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return -2; } if (length < (RF_PACKET_OVERHEAD_SIZE + CHECKSUM_OVERHEAD)/*RF_ACK_PACKET_SIZE*/ || (length-RF_PACKET_OVERHEAD_SIZE)> rfSettings.pRxInfo->max_length) { FASTSPI_READ_FIFO_GARBAGE(length); FASTSPI_READ_FIFO_BYTE(tmp); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return -3; //printf_u( "Bad length: %d %d\n",length, rfSettings.pRxInfo->max_length ); // Otherwise, if the length is valid, then proceed with the rest of the packet } else { // Register the payload length rfSettings.pRxInfo->length = length - RF_PACKET_OVERHEAD_SIZE - CHECKSUM_OVERHEAD; // Read the frame control field and the data sequence number FASTSPI_READ_FIFO_NO_WAIT((uint8_t*) &frameControlField, 2); rfSettings.pRxInfo->ackRequest = !!(frameControlField & RF_FCF_ACK_BM); FASTSPI_READ_FIFO_BYTE(rfSettings.pRxInfo->seqNumber); // Is this an acknowledgment packet? /* if ((length == RF_ACK_PACKET_SIZE) && (frameControlField == RF_ACK_FCF) && (rfSettings.pRxInfo->seqNumber == rfSettings.txSeqNumber)) { // Read the footer and check for CRC OK FASTSPI_READ_FIFO_NO_WAIT((uint8_t*) pFooter, 2); // Indicate the successful ack reception (this flag is polled by the transmission routine) if (pFooter[1] & RF_CRC_OK_BM) rfSettings.ackReceived = TRUE; // Too small to be a valid packet? } else if (length < RF_PACKET_OVERHEAD_SIZE) { FASTSPI_READ_FIFO_GARBAGE(length - 3); // Receive the rest of the packet } else { */ // Skip the destination PAN and address (that's taken care of by harware address recognition!) FASTSPI_READ_FIFO_GARBAGE(4); // Read the source address FASTSPI_READ_FIFO_NO_WAIT((uint8_t*) &rfSettings.pRxInfo->srcAddr, 2); if(frameControlField & RF_SEC_BM) { uint8_t n; // READ rx_ctr and set it FASTSPI_READ_FIFO_NO_WAIT((uint8_t*) &rx_ctr, 4); FASTSPI_WRITE_RAM(&rx_ctr[0],(CC2420RAM_RXNONCE+9),2,n); FASTSPI_WRITE_RAM(&rx_ctr[2],(CC2420RAM_RXNONCE+11),2,n); FASTSPI_STROBE(CC2420_SRXDEC); // if packet is encrypted then decrypt last_pkt_encrypted=1; rfSettings.pRxInfo->length -= 4; } // Read the packet payload FASTSPI_READ_FIFO_NO_WAIT(rfSettings.pRxInfo->pPayload, rfSettings.pRxInfo->length); FASTSPI_READ_FIFO_NO_WAIT(&rx_checksum, 1 ); // Read the footer to get the RSSI value FASTSPI_READ_FIFO_NO_WAIT((uint8_t*) pFooter, 2); rfSettings.pRxInfo->rssi = pFooter[0]; checksum=0; for(i=0; i<rfSettings.pRxInfo->length; i++ ) { checksum+=rfSettings.pRxInfo->pPayload[i]; //printf( "%d ", rfSettings.pRxInfo->pPayload[i]); } if(checksum!=rx_checksum) { //printf( "Checksum failed %d %d\r",rx_checksum, checksum ); // always read 1 byte before flush (data sheet pg 62) FASTSPI_READ_FIFO_BYTE(tmp); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return -4; } if (pFooter[1] & RF_CRC_OK_BM) { //rfSettings.pRxInfo = rf_rx_callback(rfSettings.pRxInfo); rx_ready++; #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return 1; } else { // always read 1 byte before flush (data sheet pg 62) FASTSPI_READ_FIFO_BYTE(tmp); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return -5; } // } } } #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return 0; }
//------------------------------------------------------------------------------------------------------- // BYTE rf_tx_packet(RF_TX_INFO *pRTI) // // DESCRIPTION: // Transmits a packet using the IEEE 802.15.4 MAC data packet format with short addresses. CCA is // measured only once before backet transmission (not compliant with 802.15.4 CSMA-CA). // The function returns: // - When pRTI->ackRequest is FALSE: After the transmission has begun (SFD gone high) // - When pRTI->ackRequest is TRUE: After the acknowledgment has been received/declared missing. // The acknowledgment is received through the FIFOP interrupt. // // ARGUMENTS: // RF_TX_INFO *pRTI // The transmission structure, which contains all relevant info about the packet. // // RETURN VALUE: // uint8_t // Successful transmission (acknowledgment received) //------------------------------------------------------------------------------------------------------- uint8_t rf_tx_packet(RF_TX_INFO *pRTI) { uint16_t frameControlField; uint8_t packetLength, length; uint8_t success; uint8_t spiStatusByte; uint8_t checksum,i; #ifdef RADIO_PRIORITY_CEILING nrk_sem_pend(radio_sem); #endif #ifdef CC2420_OSC_OPT FASTSPI_STROBE(CC2420_SXOSCON); nrk_spin_wait_us(OSC_STARTUP_DELAY); #endif if(security_enable) FASTSPI_STROBE(CC2420_STXENC); checksum=0; for(i=0; i<pRTI->length; i++ ) { // lets do our own payload checksum because we don't trust the CRC checksum+=pRTI->pPayload[i]; } // Write the packet to the TX FIFO (the FCS is appended automatically when AUTOCRC is enabled) // These are only the MAC AGNOSTIC parameters... // Slots for example are at a slighly higher later since they assume TDMA packetLength = pRTI->length + RF_PACKET_OVERHEAD_SIZE + CHECKSUM_OVERHEAD; if(security_enable) packetLength+=4; // for CTR counter // XXX 2 below are hacks... FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); // Wait until the transceiver is idle while (FIFOP_IS_1 || SFD_IS_1); // Turn off global interrupts to avoid interference on the SPI interface DISABLE_GLOBAL_INT(); // Flush the TX FIFO just in case... FASTSPI_STROBE(CC2420_SFLUSHTX); FASTSPI_STROBE(CC2420_SFLUSHTX); /* // Turn on RX if necessary if (!rfSettings.receiveOn) { FASTSPI_STROBE(CC2420_SRXON); } // Wait for the RSSI value to become valid do { FASTSPI_UPD_STATUS(spiStatusByte); } while (!(spiStatusByte & BM(CC2420_RSSI_VALID))); // TX begins after the CCA check has passed do { FASTSPI_STROBE(CC2420_STXONCCA); FASTSPI_UPD_STATUS(spiStatusByte); halWait(100); } while (!(spiStatusByte & BM(CC2420_TX_ACTIVE))); */ FASTSPI_WRITE_FIFO((uint8_t*)&packetLength, 1); // Packet length frameControlField = RF_FCF_NOACK; // default if(auto_ack_enable) frameControlField |= RF_ACK_BM; if(security_enable) frameControlField |= RF_SEC_BM; FASTSPI_WRITE_FIFO((uint8_t*) &frameControlField, 2); // Frame control field FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.txSeqNumber, 1); // Sequence number FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.panId, 2); // Dest. PAN ID FASTSPI_WRITE_FIFO((uint8_t*) &pRTI->destAddr, 2); // Dest. address FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.myAddr, 2); // Source address if(security_enable) FASTSPI_WRITE_FIFO((uint8_t*) &tx_ctr, 4); // CTR counter FASTSPI_WRITE_FIFO((uint8_t*) pRTI->pPayload, pRTI->length); // Payload FASTSPI_WRITE_FIFO((uint8_t*) &checksum, 1); // Checksum if (pRTI->cca == TRUE) { uint8_t cnt; if (!rfSettings.receiveOn) { FASTSPI_STROBE (CC2420_SRXON); } // Wait for the RSSI value to become valid do { FASTSPI_UPD_STATUS (spiStatusByte); } while (!(spiStatusByte & BM (CC2420_RSSI_VALID))); // TX begins after the CCA check has passed cnt = 0; do { FASTSPI_STROBE (CC2420_STXONCCA); FASTSPI_UPD_STATUS (spiStatusByte); cnt++; if (cnt > 100) { ENABLE_GLOBAL_INT (); nrk_sem_post(radio_sem); return FALSE; } halWait (100); } while (!(spiStatusByte & BM (CC2420_TX_ACTIVE))); } else FASTSPI_STROBE (CC2420_STXON); ENABLE_GLOBAL_INT(); // Wait for the transmission to begin before exiting (makes sure that this function cannot be called // a second time, and thereby cancelling the first transmission (observe the FIFOP + SFD test above). while (!SFD_IS_1); success = TRUE; // Turn interrupts back on // ENABLE_GLOBAL_INT(); while (SFD_IS_1); // wait for packet to finish // Wait for the acknowledge to be received, if any if (auto_ack_enable) { // rfSettings.ackReceived = FALSE; // Wait for the SFD to go low again // while (SFD_IS_1); // 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 halWait((12 * RF_SYMBOL_DURATION) + (RF_ACK_DURATION) + (2 * RF_SYMBOL_DURATION) + 100); if(FIFO_IS_1) { FASTSPI_READ_FIFO_BYTE(length); length &= RF_LENGTH_MASK; // Ignore MSB success = TRUE; } else { FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); success = FALSE; } } // Turn off the receiver if it should not continue to be enabled DISABLE_GLOBAL_INT(); //FASTSPI_STROBE(CC2420_SFLUSHRX); //FASTSPI_STROBE(CC2420_SFLUSHRX); //FASTSPI_STROBE(CC2420_SFLUSHTX); //FASTSPI_STROBE(CC2420_SFLUSHTX); #ifdef CC2420_OSC_OPT FASTSPI_STROBE(CC2420_SXOSCOFF); #endif FASTSPI_STROBE(CC2420_SRFOFF); // shut off radio ENABLE_GLOBAL_INT(); // agr XXX hack to test time issue //rf_rx_on(); // Increment the sequence number, and return the result rfSettings.txSeqNumber++; // while (SFD_IS_1); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return success; }
static void getrxbyte(uint8_t *byte) { FASTSPI_READ_FIFO_BYTE(*byte); rxptr = (rxptr + 1) & 0x7f; }
/* * Interrupt either leaves frame intact in FIFO or reads *only* the * MAC header and sets rx_fifo_remaining_bytes. * * In order to quickly empty the FIFO ack processing is done at * interrupt priority rather than poll priority. */ int __cc2420_intr(void) { u8_t length; const u8_t *const ack_footer = (u8_t *)&h.dst_pan; CLEAR_FIFOP_INT(); if (spi_busy || rx_fifo_remaining_bytes > 0) { /* SPI bus hardware is currently used elsewhere (UART0 or I2C bus) * or we already have a packet in the works and will have to defer * interrupt processing of this packet in a fake interrupt. */ process_poll(&cc2420_process); return 1; } FASTSPI_READ_FIFO_BYTE(length); if (length > MAX_PACKET_LEN) { /* Oops, we must be out of sync. */ FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); return 0; } h.len = length; if (length < ACK_PACKET_LEN) { FASTSPI_READ_FIFO_GARBAGE(length); /* Rubbish */ return 0; } FASTSPI_READ_FIFO_NO_WAIT(&h.fc0, 5); /* fc0, fc1, seq, dst_pan */ /* Is this an ACK packet? */ if (length == ACK_PACKET_LEN && (h.fc0 & FC0_TYPE_MASK) == FC0_TYPE_ACK) { if (ack_footer[1] & FOOTER1_CRC_OK) { if (h.seq == last_used_seq) { /* Matching ACK number? */ cc2420_ack_received = 1; process_poll(&cc2420_retransmit_process); #if 0 cc2420_last_rssi = ack_footer[0]; cc2420_last_correlation = ack_footer[1] & FOOTER1_CORRELATION; #endif } } return 1; } if (length < (MAC_HDR_LEN + 2)) { FASTSPI_READ_FIFO_GARBAGE(length - 5); return 0; } FASTSPI_READ_FIFO_NO_WAIT(&h.dst, 4); /* dst and src */ /* The payload and footer is now left in the RX FIFO and will be * picked up asynchronously at poll priority in the cc2420_process * below. */ rx_fifo_remaining_bytes = length - MAC_HDR_LEN; process_poll(&cc2420_process); return 1; }