Beispiel #1
0
/**************************************************************************************************
 * @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_RxIsr
 *
 * @brief       Receive interrupt.  Reads incoming packet from radio FIFO.  If CRC passes the
 *              external function MRFI_RxCompleteISR() is called.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
BSP_ISR_FUNCTION( MRFI_RxIsr, RF_VECTOR )
{
  uint8_t numBytes;
  uint8_t i, crcOK;

  /* Clear the MCU interrupt. */
  S1CON = 0x00;

  /* Process FIFOP interrupt */
  if(RFIF & IRQ_FIFOP)
  {
    /* 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 );

    /* While there is at least one frame in the Rx FIFO */
    while(RFIF & IRQ_FIFOP)
    {
      /* Check for Rx overflow. Checking here means we may flush a valid frame */
      if ((RFSTATUS & FIFOP) && (!(RFSTATUS & FIFO)))
      {
        /* flush receive FIFO to recover from overflow (per datasheet, flush must be done twice) */
        MRFI_RADIO_FLUSH_RX_BUFFER();
        break;
      }

      /* ------------------------------------------------------------------
       *    Read packet from FIFO
       *   -----------------------
       */

      /*
       *  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).
       */
      numBytes = RFD & 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))
      {
        /* packet is too big or too small. remove it from FIFO */
        for (i=0; i<numBytes; i++)
        {
          /* read and discard bytes from FIFO */
          RFD;
        }
      }
      else
      {
        uint8_t *p, *p1;

        /* set pointer at first byte of frame storage */
        p  = &mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFFSET];
        p1 = mrfiIncomingPacket.frame;

        /* Clear out my buffer to remove leftovers in case a bogus packet gets through */
        memset(p1, 0x0, sizeof(mrfiIncomingPacket.frame));

        /*
         *  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 receive FIFO and store into incoming packet memory */
        for (i=0; i<numBytes-MRFI_RX_METRICS_SIZE; i++)
        {
          p++;
          *p = RFD;
        }

        /* read rx metrics and store to incoming packet */

        /* Add the RSSI offset to get the proper RSSI value. */
        mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] = RFD + MRFI_RSSI_OFFSET;

        /* 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 CC2430 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.
         */
        crcOK = RFD;   /* get CRC/LQI byte */

        if (crcOK & MRFI_RX_METRICS_CRC_OK_MASK)
        {
          /* CRC OK. Save LQI info */
          mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] = (crcOK & MRFI_RX_METRICS_LQI_MASK);

          /* Eliminate frames that are the correct size but we can tell are bogus
           * by their frame control fields.
           */
          if ((p1[MRFI_FCF_OFFSET] == MRFI_FCF_0_7) &&
              (p1[MRFI_FCF_OFFSET+1] == MRFI_FCF_8_15))
          {
            /* call external, higher level "receive complete" */
            MRFI_RxCompleteISR();
          }
        }
      } /* Frame fits in the buffer. */

      /* Clear the interrupt source flag. This must be done after reading
       * the frame from the buffer. Otherwise the flag remains set. If another
       * frame is sitting in the buffer, the IRQ_FIFOP will be immediately set
       * again.
       */
       RFIF &= ~IRQ_FIFOP;
    }   /* While there is at least one frame in the Rx FIFO */
  }     /* Process FIFOP interrupt */
  else
  {
    /* Don't assert here. It is possible that the MCU interrupt was set by
     * FIFOP but we processed it in the while() loop of the FIFOP handler in
     * the previous run of this ISR.
     */

    /* If any other RF interrupt is enabled, add that handler here. */
  }

  /* Bugzilla Chip Bug#297: Don't delete */
  RFIF = 0xFF;
}
Beispiel #3
0
/**************************************************************************************************
 * @fn          MRFI_RxIsr
 *
 * @brief       Receive interrupt.  Reads incoming packet from radio FIFO.  If CRC passes the
 *              external function MRFI_RxCompleteISR() is called.
 *
 *              Note : All RF interrupts use this same interrupt vector.  Normally, the interrupt
 *              enable bits and interrupt flag bits are examined to see which interrupts need to
 *              be serviced.  In this implementation, only the FIFOP interrupt is used.  This
 8              function is optimized to take advantage of that fact.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
BSP_ISR_FUNCTION( MRFI_RxIsr, RF_VECTOR )
{
  uint8_t numBytes;
  uint8_t i, crcOK;

  /* 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 );

  /* While there is stuff in the Rx FIFO... */
  do {
    /*
     * Pend on frame completion. First timne 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 (!(RFIRQF0 & IRQ_FIFOP)) ;

    /* Check for Rx overflow. Checking here means we may flush a valid frame */
    if ((FSMSTAT1 & FIFOP) && (!(FSMSTAT1 & FIFO)))
    {
      /* flush receive FIFO to recover from overflow (per datasheet, flush must be done twice) */
      MRFI_RADIO_FLUSH_RX_BUFFER();
      break;
    }

    /* clear interrupt flag so we can detect another frame later. */
    RFIRQF0 &= ~IRQ_FIFOP;

    /* ------------------------------------------------------------------
     *    Read packet from FIFO
     *   -----------------------
     */

    /*
     *  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).
     */
    numBytes = RFD & 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))
    {
      /* packet is too big or too small. remove it from FIFO */
      for (i=0; i<numBytes; i++)
      {
        /* read and discard bytes from FIFO */
        RFD;
      }
    }
    else
    {
      uint8_t *p, *p1;

      /* set pointer at first byte of frame storage */
      p  = &mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFFSET];
      p1 = mrfiIncomingPacket.frame;

      /* Clear out my buffer to remove leftovers in case a bogus packet gets through */
      memset(p1, 0x0, sizeof(mrfiIncomingPacket.frame));

      /*
       *  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 receive FIFO and store into incoming packet memory */
      for (i=0; i<numBytes-MRFI_RX_METRICS_SIZE; i++)
      {
        p++;
        *p = RFD;
      }

      /* read rx metrics and store to incoming packet */

      /* Add the RSSI offset to get the proper RSSI value. */
      mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] = RFD + MRFI_RSSI_OFFSET;

      /* 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 CC2430 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.
       */
      crcOK = RFD;   /* get CRC/LQI byte */
      if (!(crcOK & (~MRFI_RX_METRICS_LQI_MASK)))
      {
        /* bad CRC. Move on... */
        continue;
      }

      /* CRC OK. Save LQI info */
      mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] = (crcOK & MRFI_RX_METRICS_LQI_MASK);

      /* Eliminate frames that are the correct size but we can tell are bogus
       * by their frame control fields.
       */
      if ((p1[MRFI_FCF_OFFSET] == MRFI_FCF_0_7) &&
          (p1[MRFI_FCF_OFFSET+1] == MRFI_FCF_8_15))
      {
        /* call external, higher level "receive complete" */
        MRFI_RxCompleteISR();
      }
    }
  } while (RXFIFOCNT);


  /* ------------------------------------------------------------------
   *     Clean up on exit
   *   --------------------
   */

  /* Clear FIFOP interrupt:
   * This is an edge triggered interrupt. The interrupt must be first cleared
   * at the MCU before re-enabling the interrupt at the source.
   */
  S1CON = 0x00; /* Clear the interrupt at MCU. */

  RFIRQF0 &= ~IRQ_FIFOP; /* Clear the interrupt source flag. */
}
Beispiel #4
0
/**************************************************************************************************
 * @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;
}