コード例 #1
0
/**************************************************************************************************
 * @fn          macTxDoneCallback
 *
 * @brief       -
 *
 * @param       -
 *
 * @return      none
 **************************************************************************************************
 */
void macTxDoneCallback(uint8 status)
{
  if (status == MAC_TXDONE_SUCCESS)
  {
    /* see if ACK was requested */
    if (!txAckReq)
    {
      /* ACK was not requested, transmit is complete */
      txComplete(MAC_SUCCESS);
    }
    else
    {
      /*
       *  ACK was requested - must wait to receive it.  A timer is set
       *  to expire after the timeout duration for waiting for an ACK.
       *  If an ACK is received, the function macTxAckReceived() is called.
       *  If an ACK is not received within the timeout period,
       *  the function macTxAckTimeoutCallback() is called.
       */
      macTxListenForAck = TRUE;
      MAC_RADIO_TX_REQUEST_ACK_TIMEOUT_CALLBACK();
    }
  }
  else if (status == MAC_TXDONE_CHANNEL_BUSY)
  {
    MAC_ASSERT((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) || (macTxType == MAC_TX_TYPE_UNSLOTTED_CSMA));

    /*  clear channel assement failed, follow through with CSMA algorithm */
    nb++;
    if (nb > macPib.maxCsmaBackoffs)
    {
      txComplete(MAC_CHANNEL_ACCESS_FAILURE);
    }
    else
    {
      macTxBe = MIN(macTxBe+1, macPib.maxBe);
      txCsmaPrep();
      txCsmaGo();
    }
  }
  else
  {
    MAC_ASSERT(status == MAC_TXDONE_INSUFFICIENT_TIME);

    txComplete(MAC_NO_TIME);
  }
}
コード例 #2
0
ファイル: mac_tx.c プロジェクト: LILCMU/WRATIOT
/**************************************************************************************************
 * @fn          macTxAckReceivedCallback
 *
 * @brief       This function is called by the receive logic when an ACK is received and
 *              transmit logic is listening for an ACK.
 *
 * @param       seqn        - sequence number of received ACK
 * @param       pendingFlag - set if pending flag of ACK is set, cleared otherwise
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macTxAckReceivedCallback(uint8 seqn, uint8 pendingFlag)
{
  halIntState_t  s;

  /* only process if listening for an ACK; critical section prevents race condition problems */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
  {
    macTxActive = MAC_TX_ACTIVE_POST_ACK;
    MAC_RADIO_TX_CANCEL_ACK_TIMEOUT_CALLBACK();
    HAL_EXIT_CRITICAL_SECTION(s);

    /* see if the sequence number of received ACK matches sequence number of packet just sent */
    if (seqn == txSeqn)
    {
      /*
       *  Sequence numbers match so transmit is successful.  Return appropriate
       *  status based on the pending flag of the received ACK.
       */
      if (pendingFlag)
      {
        txComplete(MAC_ACK_PENDING);
      }
      else
      {
        txComplete(MAC_SUCCESS);
      }
    }
    else
    {
      /* sequence number did not match; per spec, transmit failed at this point */
      txComplete(MAC_NO_ACK);
    }
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}
コード例 #3
0
/**************************************************************************************************
 * @fn          macTxAckTimeoutCallback
 *
 * @brief       This function is called if ACK is not received within timeout period.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macTxAckTimeoutCallback(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxListenForAck)
  {
    macTxListenForAck = FALSE;
    HAL_EXIT_CRITICAL_SECTION(s);
    txComplete(MAC_NO_ACK);
  }
  HAL_EXIT_CRITICAL_SECTION(s);
}
コード例 #4
0
/**************************************************************************************************
 * @fn          macTxAckReceived
 *
 * @brief       Function called by interrupt routine when an ACK is received.
 *
 * @param       seqn        - sequence number of received ACK
 * @param       pendingFlag - set to TRUE if pending flag of ACK is set, FALSE otherwise
 *
 * @return      none
 **************************************************************************************************
 */
void macTxAckReceived(uint8 seqn, uint8 pendingFlag)
{
  halIntState_t  s;

  /* only process the received ACK if the macTxListenForAck flag is set */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxListenForAck)
  {
    macTxListenForAck = FALSE;
    HAL_EXIT_CRITICAL_SECTION(s);

    /* cancel the ACK callback */
    MAC_RADIO_TX_CANCEL_ACK_TIMEOUT_CALLBACK();

    /* see if the sequence number of received ACK matches sequence number of packet just sent */
    if (seqn == txSeqn)
    {
      /*
       *  Sequence numbers match so transmit is successful.  Return appropriate
       *  status based on the pending flag of the received ACK.
       */
      if (pendingFlag)
      {
        txComplete(MAC_ACK_PENDING);
      }
      else
      {
        txComplete(MAC_SUCCESS);
      }
    }
    else
    {
      /* sequence number did not match; per spec, transmit failed at this point */
      txComplete(MAC_NO_ACK);
    }
  }

  HAL_EXIT_CRITICAL_SECTION(s);
}
コード例 #5
0
/*=================================================================================================
 * @fn          txCsmaGo
 *
 * @brief       -
 *
 * @param       none
 *
 * @return      none
 *=================================================================================================
 */
static void txCsmaGo(void)
{
  if (macTxType == MAC_TX_TYPE_SLOTTED_CSMA)
  {
    if (macTxCsmaBackoffDelay >= macDataTxTimeAvailable())
    {
      txComplete(MAC_NO_TIME);
      return;
    }
  }

  MAC_RADIO_TX_GO_CSMA();
}
コード例 #6
0
ファイル: mac_tx.c プロジェクト: LILCMU/WRATIOT
/**************************************************************************************************
 * @fn          macTxDoneCallback
 *
 * @brief       This callback is executed when transmit completes.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macTxDoneCallback(void)
{
  halIntState_t  s;

  /*
   *  There is a small chance this function could be called twice for a single transmit.
   *  To prevent logic from executing twice, the state variable macTxActive is used as
   *  a gating mechanism to guarantee single time execution.
   */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_GO)
  {
    if (macRxActive)
    {
      /* RX was partly done just before TX. Reset the RX state. */
      macTxCollisionWithRxCallback();
    }
    
    /* see if ACK was requested */
    if (!txAckReq)
    {
      macTxActive = MAC_TX_ACTIVE_DONE;
      HAL_EXIT_CRITICAL_SECTION(s);

      /* ACK was not requested, transmit is complete */
      txComplete(MAC_SUCCESS);
    }
    else
    {
      /*
       *  ACK was requested - must wait to receive it.  A timer is set
       *  to expire after the timeout duration for waiting for an ACK.
       *  If an ACK is received, the function macTxAckReceived() is called.
       *  If an ACK is not received within the timeout period,
       *  the function macTxAckNotReceivedCallback() is called.
       */
      macTxActive = MAC_TX_ACTIVE_LISTEN_FOR_ACK;
      MAC_RADIO_TX_REQUEST_ACK_TIMEOUT_CALLBACK();
      HAL_EXIT_CRITICAL_SECTION(s);
    }
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}
コード例 #7
0
ファイル: mac_tx.c プロジェクト: LILCMU/WRATIOT
/**************************************************************************************************
 * @fn          macTxAckNotReceivedCallback
 *
 * @brief       This function is called by the receive logic when transmit is listening
 *              for an ACK but something else is received.  It is also called if the
 *              listen-for-ACK timeout is reached.
 *
 * @brief
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macTxAckNotReceivedCallback(void)
{
  halIntState_t  s;

  /* only process if listening for an ACK; critical section prevents race condition problems */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_LISTEN_FOR_ACK)
  {
    macTxActive = MAC_TX_ACTIVE_POST_ACK;
    MAC_RADIO_TX_CANCEL_ACK_TIMEOUT_CALLBACK();
    HAL_EXIT_CRITICAL_SECTION(s);

    /* a non-ACK was received when expecting an ACK, per spec transmit is over at this point */
    txComplete(MAC_NO_ACK);
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}
コード例 #8
0
ファイル: mac_tx.c プロジェクト: LILCMU/WRATIOT
/**************************************************************************************************
 * @fn          macTxChannelBusyCallback
 *
 * @brief       This callback is executed if a CSMA transmit was attempted but the channel
 *              was busy.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macTxChannelBusyCallback(void)
{
  MAC_ASSERT((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) || (macTxType == MAC_TX_TYPE_UNSLOTTED_CSMA));

  /* turn off receiver if allowed */
  macTxActive = MAC_TX_ACTIVE_CHANNEL_BUSY;
  macRxOffRequest();

  /*  clear channel assement failed, follow through with CSMA algorithm */
  nb++;
  if (nb > pMacPib->maxCsmaBackoffs)
  {
    txComplete(MAC_CHANNEL_ACCESS_FAILURE);
  }
  else
  {
    macTxBe = MIN(macTxBe+1, pMacPib->maxBe);
    txCsmaPrep();
    macTxActive = MAC_TX_ACTIVE_GO;
    txCsmaGo();
  }
}
コード例 #9
0
ファイル: mac_tx.c プロジェクト: LILCMU/WRATIOT
/**************************************************************************************************
 * @fn          macTxFrame
 *
 * @brief       Transmit the frame pointed to by pMacDataTx with the specified type.
 *              NOTE! It is not legal to call this function from interrupt context.
 *
 * @param       txType - type of transmit
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macTxFrame(uint8 txType)
{
  MAC_ASSERT(!macTxActive);            /* transmit on top of transmit */

  /* mark transmit as active */
  macTxActive = MAC_TX_ACTIVE_INITIALIZE;

  /*
   *  The MAC will not enter sleep mode if there is an active transmit.  However, if macSleep() is
   *  ever called from interrupt context, it possible to enter sleep state after a transmit is
   *  intiated but before macTxActive is set.  To recover from this, the transmit must be aborted
   *  and proper notificiation given to high-level.
   */
  if (macSleepState != MAC_SLEEP_STATE_AWAKE)
  {
    /* notify high-level that transmit had to be aborted */
    txComplete(MAC_TX_ABORTED);

    /* exit from transmit logic */
    return;
  }

  /* save transmit type */
  macTxType = txType;

  /*-------------------------------------------------------------------------------
   *  Prepare for transmit.
   */
  if (macTxType == MAC_TX_TYPE_SLOTTED)
  {
    MAC_RADIO_TX_PREP_SLOTTED();
  }

#ifdef FEATURE_GREEN_POWER
  else if (macTxType == MAC_TX_TYPE_GREEN_POWER)
  {
    txGreenPowerPrep();
  }
#endif /* #ifdef FEATURE_GREEN_POWER */

  else
  {
    MAC_ASSERT((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) || (macTxType == MAC_TX_TYPE_UNSLOTTED_CSMA));

    nb = 0;
    macTxBe = (pMacDataTx->internal.txOptions & MAC_TXOPTION_ALT_BE) ? pMacPib->altBe : pMacPib->minBe;

    if ((macTxType == MAC_TX_TYPE_SLOTTED_CSMA) && (pMacPib->battLifeExt))
    {
      macTxBe = MIN(2, macTxBe);
    }

    txCsmaPrep();
  }

  /*-------------------------------------------------------------------------------
   *  Load transmit FIFO unless this is a retransmit.  No need to write
   *  the FIFO again in that case.
   */
  if (!txRetransmitFlag)
  {
    uint8 * p;
    uint8   lenMhrMsdu;

    MAC_ASSERT(pMacDataTx != NULL); /* must have data to transmit */

    /* save needed parameters */
    txAckReq = MAC_ACK_REQUEST(pMacDataTx->msdu.p);
    txSeqn   = MAC_SEQ_NUMBER(pMacDataTx->msdu.p);

    /* set length of frame (note: use of term msdu is a misnomer, here it's actually mhr + msdu) */
    lenMhrMsdu = pMacDataTx->msdu.len;

    /* calling code guarantees an unused prepended byte  */
    p = pMacDataTx->msdu.p - PREPENDED_BYTE_LEN;

    /* first byte of buffer is length of MPDU */
    *p = lenMhrMsdu + MFR_LEN;

    /*
     *  Flush the TX FIFO.  This is necessary in case the previous transmit was never
     *  actually sent (e.g. CSMA failed without strobing TXON).  If bytes are written to
     *  the FIFO but not transmitted, they remain in the FIFO to be transmitted whenever
     *  a strobe of TXON does happen.
     */
    MAC_RADIO_FLUSH_TX_FIFO();

    /* write bytes to FIFO, prepended byte is included, MFR is not (it's generated by hardware) */
    MAC_RADIO_WRITE_TX_FIFO(p, PREPENDED_BYTE_LEN + lenMhrMsdu);
  }

  /*-------------------------------------------------------------------------------
   *  If not receiving, start the transmit.  If receive is active
   *  queue up the transmit.
   *
   *  Critical sections around the state change prevents any sort of race condition
   *  with  macTxStartQueuedFrame().  This guarantees function txGo() will only be
   *  called once.
   */
  {
    halIntState_t  s;

    HAL_ENTER_CRITICAL_SECTION(s);
    if (!macRxActive && !macRxOutgoingAckFlag)
    {
      macTxActive = MAC_TX_ACTIVE_GO;
      HAL_EXIT_CRITICAL_SECTION(s);
      txGo();
    }
    else
    {
      macTxActive = MAC_TX_ACTIVE_QUEUED;
      HAL_EXIT_CRITICAL_SECTION(s);
    }
  }
}