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; }
PROCESS_THREAD(cc2420_process, ev, data) { PROCESS_BEGIN(); process_start(&cc2420_retransmit_process, NULL); while (1) { unsigned len; int s; PROCESS_YIELD(); len = rx_fifo_remaining_bytes; if (len > 0) { /* Read payload and two bytes of footer */ if ((len - 2) > (UIP_BUFSIZE - UIP_LLH_LEN) || len < 2) { PRINTF("cc2420_process too big len=%d\n", len); s = splhigh(); FASTSPI_READ_FIFO_GARBAGE(len); rx_fifo_remaining_bytes = 0; /* RX FIFO emptied! */ splx(s); len = 0; } else { u8_t footer[2]; uip_len = 0; s = splhigh(); if (len > 2) FASTSPI_READ_FIFO_NO_WAIT(&uip_buf[UIP_LLH_LEN], len - 2); FASTSPI_READ_FIFO_NO_WAIT(footer, 2); rx_fifo_remaining_bytes = 0; /* RX FIFO emptied! */ splx(s); if (footer[1] & FOOTER1_CRC_OK) { cc2420_last_rssi = footer[0]; cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; if ((h.fc0 & FC0_TYPE_MASK) == FC0_TYPE_DATA) uip_len = len - 2; } } } if (len == 2) PRINTF("recv data_ack\n"); /* Clean up in case of FIFO overflow! This happens for every full * length frame and is signaled by FIFOP = 1 and FIFO = 0. */ if (FIFOP_IS_1 && !FIFO_IS_1) { cc2420_strobe(CC2420_SFLUSHRX); cc2420_strobe(CC2420_SFLUSHRX); } if (FIFOP_IS_1) { s = splhigh(); __cc2420_intr(); /* Fake interrupt! */ splx(s); } if (len == 2) { /* A DATA ACK packet. */ if (last_dst == h.src) cc2420_ack_received = 1; neigbour_update(h.src, 0); } else if (len > 2 && uip_len > 0 && uip_len == (((u16_t)(BUF->len[0]) << 8) + BUF->len[1])) { /* * If we are the unique receiver send DATA ACK. */ if (h.dst == 0xffff && uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr)) cc2420_send_data_ack(h.src); leds_toggle(LEDS_GREEN); cc2420_is_input = 1; tcpip_input(); cc2420_is_input = 0; leds_toggle(LEDS_GREEN); } } PROCESS_END(); }
static void getrxdata(void *buf, int len) { FASTSPI_READ_FIFO_NO_WAIT(buf, len); rxptr = (rxptr + len) & 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; }