/************************************************************************************************** * @fn Mrfi_FiFoPIsr * * @brief Interrupt Service Routine for handling FIFO_P event. * * @param none * * @return none ************************************************************************************************** */ void Mrfi_FiFoPIsr(void) { uint8_t numBytes; uint8_t i; /* NOTE: Bug #2 described in the errata swrz024.pdf for CC2520: * There is a possiblity of small glitch in the fifo_p signal * (2 cycle of 32 MHz). Workaround is to make sure that fifo_p signal stays * high for longer than that. Else, it is a false alarm. */ if(!MRFI_FIFOP_STATUS()) return; if(!MRFI_FIFOP_STATUS()) return; /* Ah... it is for real... Continue processing. */ /* We should receive this interrupt only in RX state * Should never receive it if RX was turned ON only for * some internal mrfi processing like - during CCA. * Otherwise something is terribly wrong. */ MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX ); do { /* * Pend on frame rx completion. First time through this always passes. * Later, though, it is possible that the Rx FIFO has bytes but we * havn't received a complete frame yet. */ while( !MRFI_FIFOP_STATUS() ); /* Check for Rx overflow. Checking here means we may flush a valid frame */ if( MRFI_FIFOP_STATUS() && !MRFI_FIFO_STATUS() ) { /* Flush receive FIFO to recover from overflow */ MRFI_RADIO_FLUSH_RX_BUFFER(); break; } /* clear interrupt flag so we can detect another frame later. */ MRFI_CLEAR_RX_INTERRUPT_FLAG(); /* * Determine number of bytes to be read from receive FIFO. The first byte * has the number of bytes in the packet. A mask must be applied though * to strip off unused bits. The number of bytes in the packet does not * include the length byte itself but does include the FCS (generically known * as RX metrics). */ mrfiSpiReadRxFifo(&numBytes, 1); numBytes &= IEEE_PHY_PACKET_SIZE_MASK; /* see if frame will fit in maximum available buffer or is too small */ if (((numBytes + MRFI_LENGTH_FIELD_SIZE - MRFI_RX_METRICS_SIZE) > MRFI_MAX_FRAME_SIZE) || (numBytes < MRFI_MIN_SMPL_FRAME_SIZE)) { uint8_t dummy; /* packet is too big or too small. remove it from FIFO */ for (i=0; i<numBytes; i++) { /* read and discard bytes from FIFO */ mrfiSpiReadRxFifo(&dummy, 1); } } else { uint8_t *p, nextByte; /* Clear out my buffer to remove leftovers in case a bogus packet gets through */ for(i=0; i < MRFI_MAX_FRAME_SIZE; i++) { mrfiIncomingPacket.frame[i] = 0; } /* set pointer at first byte of frame storage */ p = &mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFFSET]; /* * Store frame length into the incoming packet memory. Size of rx metrics * is subtracted to get the MRFI frame length which separates rx metrics from * the frame length. */ *p = numBytes - MRFI_RX_METRICS_SIZE; /* read frame bytes from rx FIFO and store into incoming packet memory */ p++; mrfiSpiReadRxFifo(p, numBytes-MRFI_RX_METRICS_SIZE); /* The next two bytes in the rx fifo are: * - RSSI of the received frams * - CRC OK bit and the 7 bit wide correlation value. * Read this rx metrics and store to incoming packet. */ /* Add the RSSI offset to get the proper RSSI value. */ mrfiSpiReadRxFifo(&nextByte, 1); mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] = Mrfi_CalculateRssi(nextByte); /* The second byte has 7 bits of Correlation value and 1 bit of * CRC pass/fail info. Remove the CRC pass/fail bit info. * Also note that for CC2520 radio this is the correlation value and not * the LQI value. Some convertion is needed to extract the LQI value. * This convertion is left to the application at this time. */ mrfiSpiReadRxFifo(&nextByte, 1); mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] = nextByte & MRFI_RX_METRICS_LQI_MASK; /* Eliminate frames that are the correct size but we can tell are bogus * by their frame control fields OR if CRC failed. */ if( (nextByte & MRFI_RX_METRICS_CRC_OK_MASK) && (mrfiIncomingPacket.frame[MRFI_FCF_OFFSET] == MRFI_FCF_0_7) && (mrfiIncomingPacket.frame[MRFI_FCF_OFFSET+1] == MRFI_FCF_8_15)) { /* call external, higher level "receive complete" (CRC checking is done by hardware) */ MRFI_RxCompleteISR(); } } /* If the client code takes long time to process the frame, * rx fifo could overflow during this time. As soon as this condition is * reached, the radio fsm stops all activities till the rx fifo is flushed. * It also puts the fifo signal low. When we come out of this while loop, * we really don't know if it is because of overflow condition or * there is no data in the fifo. So we must check for overflow condition * before exiting the ISR otherwise it could get stuck in this "overflow" * state forever. */ } while( MRFI_FIFO_STATUS() ); /* Continue as long as there is some data in FIFO */ /* Check if we exited the loop due to fifo overflow. * and not due to no data in fifo. */ if( MRFI_FIFOP_STATUS() && !MRFI_FIFO_STATUS() ) { /* Flush receive FIFO to recover from overflow */ MRFI_RADIO_FLUSH_RX_BUFFER(); } }
/************************************************************************************************** * @fn MRFI_SyncPinRxIsr * * @brief This interrupt is called when the SYNC signal transition from high to low. * The sync signal is routed to the sync pin which is a GPIO pin. This high-to-low * transition signifies a receive has completed. The SYNC signal also goes from * high to low when a transmit completes. This is protected against within the * transmit function by disabling sync pin interrupts until transmit completes. * * @param none * * @return none ************************************************************************************************** */ static void MRFI_SyncPinRxIsr(void) { uint8_t frameLen; uint8_t rxBytes; /* ------------------------------------------------------------------ * Abort if asleep * ----------------- */ /* * If radio is asleep, abort immediately. Nothing further is required. * If radio is awake, set "receive active" flag and continue processing the receive. */ { bspIState_t s; /* critical section necessary for watertight testing and setting of state variables */ BSP_ENTER_CRITICAL_SECTION(s); /* if radio is asleep, just abort from here */ if (mrfiRadioIsSleeping) { BSP_EXIT_CRITICAL_SECTION(s); return; } /* radio is not asleep, set flag that indicates receive is active */ mrfiRxActive = 1; BSP_EXIT_CRITICAL_SECTION(s); } /* ------------------------------------------------------------------ * Get RXBYTES * ------------- */ /* * Read the RXBYTES register from the radio. * Bit description of RXBYTES register: * bit 7 - RXFIFO_OVERFLOW, set if receive overflow occurred * bits 6:0 - NUM_BYTES, number of bytes in receive FIFO * * Due a chip bug, the RXBYTES register must read the same value twice * in a row to guarantee an accurate value. */ { uint8_t rxBytesVerify; rxBytesVerify = mrfiSpiReadReg(MRFI_CC2500_SPI_REG_RXBYTES); do { rxBytes = rxBytesVerify; rxBytesVerify = mrfiSpiReadReg(MRFI_CC2500_SPI_REG_RXBYTES); } while (rxBytes != rxBytesVerify); } /* ------------------------------------------------------------------ * FIFO empty? * ------------- */ /* * See if the receive FIFIO is empty before attempting to read from it. * It is possible nothing the FIFO is empty even though the interrupt fired. * This can happen if address check is enabled and a non-matching packet is * received. In that case, the radio automatically removes the packet from * the FIFO. */ if (rxBytes == 0) { /* receive FIFO is empty - do nothing, skip to end */ } else { /* receive FIFO is not empty, continue processing */ /* ------------------------------------------------------------------ * Process frame length * ---------------------- */ /* read the first byte from FIFO - the packet length */ mrfiSpiReadRxFifo(&frameLen, MRFI_LENGTH_FIELD_SIZE); /* * Make sure that the frame length just read corresponds to number of bytes in the buffer. * If these do not match up something is wrong. * * This can happen for several reasons: * 1) Incoming packet has an incorrect format or is corrupted. * 2) The receive FIFO overflowed. Overflow is indicated by the high * bit of rxBytes. This guarantees the value of rxBytes value will not * match the number of bytes in the FIFO for overflow condition. * 3) Interrupts were blocked for an abnormally long time which * allowed a following packet to at least start filling the * receive FIFO. In this case, all received and partially received * packets will be lost - the packet in the FIFO and the packet coming in. * This is the price the user pays if they implement a giant * critical section. * 4) A failed transmit forced radio to IDLE state to flush the transmit FIFO. * This could cause an active receive to be cut short. */ if (rxBytes != (frameLen + MRFI_LENGTH_FIELD_SIZE + MRFI_RX_METRICS_SIZE)) { bspIState_t s; /* mismatch between bytes-in-FIFO and frame length */ /* * Flush receive FIFO to reset receive. Must go to IDLE state to do this. * The critical section guarantees a transmit does not occur while cleaning up. */ BSP_ENTER_CRITICAL_SECTION(s); mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SIDLE); mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SFRX); mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX); BSP_EXIT_CRITICAL_SECTION(s); /* flush complete, skip to end */ } else { /* bytes-in-FIFO and frame length match up - continue processing */ /* ------------------------------------------------------------------ * Get packet * ------------ */ /* set length field */ mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFS] = frameLen; /* get packet from FIFO */ mrfiSpiReadRxFifo(&(mrfiIncomingPacket.frame[MRFI_FRAME_BODY_OFS]), frameLen); /* get receive metrics from FIFO */ mrfiSpiReadRxFifo(&(mrfiIncomingPacket.rxMetrics[0]), MRFI_RX_METRICS_SIZE); /* ------------------------------------------------------------------ * CRC check * ------------ */ /* * Note! Automatic CRC check is not, and must not, be enabled. This feature * flushes the *entire* receive FIFO when CRC fails. If this feature is * enabled it is possible to be reading from the FIFO and have a second * receive occur that fails CRC and automatically flushes the receive FIFO. * This could cause reads from an empty receive FIFO which puts the radio * into an undefined state. */ /* determine if CRC failed */ if (!(mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] & MRFI_RX_METRICS_CRC_OK_MASK)) { /* CRC failed - do nothing, skip to end */ } else { /* CRC passed - continue processing */ /* ------------------------------------------------------------------ * Filtering * ----------- */ /* see if filtering is enabled and, if so, determine if address is a match */ if (mrfiRxFilterEnabled && memcmp(MRFI_P_DST_ADDR(&mrfiIncomingPacket), &mrfiRxFilterAddr[0], MRFI_ADDR_SIZE)) { /* packet filtered out - do nothing, skip to end */ } else { /* packet not filtered out - receive successful */ /* ------------------------------------------------------------------ * Receive succeeded * ------------------- */ /* call external, higher level "receive complete" processing routine */ MRFI_RxCompleteISR(); } } } } /* ------------------------------------------------------------------ * End of function * ------------------- */ /* clear "receive active" flag and exit */ mrfiRxActive = 0; }