⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mac_tx.c

📁 Zigbee2006入门(源代码+文档讲解+系统推荐)
💻 C
📖 第 1 页 / 共 2 页
字号:
 * @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();
}


/**************************************************************************************************
 * @fn          macTxFrameRetransmit
 *
 * @brief       Retransmit the last frame.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macTxFrameRetransmit(void)
{
  txRetransmitFlag = 1;
  macTxFrame(macTxType);
}


/**************************************************************************************************
 * @fn          macTxStartQueuedFrame
 *
 * @brief       See if there is a queued frame waiting to transmit.  If so, initiate
 *              the transmit now.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macTxStartQueuedFrame(void)
{
  halIntState_t  s;

  MAC_ASSERT(!macRxActive && !macRxOutgoingAckFlag); /* queued frames should not transmit in middle of a receive */
  
  /*
   *  Critical sections around the state change prevents any sort of race condition
   *  with macTxFrame().  This guarantees function txGo() will only be be called once.
   */
  HAL_ENTER_CRITICAL_SECTION(s);
  if (macTxActive == MAC_TX_ACTIVE_QUEUED)
  {
    macTxActive = MAC_TX_ACTIVE_GO;
    HAL_EXIT_CRITICAL_SECTION(s);
    txGo();
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}


/**************************************************************************************************
 * @fn          macTxChannelBusyCallback
 *
 * @brief       This callback is executed if a CSMA transmit was attempted but the channel
 *              was busy.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macTxChannelBusyCallback(void)
{
  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();
  }
}


/**************************************************************************************************
 * @fn          macTxDoneCallback
 *
 * @brief       This callback is executed when transmit completes.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
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)
  {
    /* 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 macTxAckTimeoutCallback() 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);
  }
}


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


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


/*=================================================================================================
 * @fn          txComplete
 *
 * @brief       Transmit has completed.  Perform needed maintenance and return status of
 *              the transmit via callback function.
 *
 * @param       status - status of the transmit that just went out
 *
 * @return      none
 *=================================================================================================
 */
static void txComplete(uint8 status)
{
  /* reset the retransmit flag */
  txRetransmitFlag = 0;

  /* update tx state; turn off receiver if nothing is keeping it on */
  macTxActive = MAC_TX_ACTIVE_NO_ACTIVITY;

  /* turn off receive if allowed */
  macRxOffRequest();

  /* update transmit power in case there was a change */
  macRadioUpdateTxPower();

  /*
   *  Channel cannot change during transmit so update it here.  (Channel *can* change during
   *  a receive.  The update function resets receive logic and any partially received
   *  frame is purged.)
   */
  macRadioUpdateChannel();

  /* return status of transmit via callback function */
  macTxCompleteCallback(status);
}


/**************************************************************************************************
 * @fn          macTxTimestampCallback
 *
 * @brief       This callback function records the timestamp into the receive data structure.
 *              It should be called as soon as possible after there is a valid timestamp.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macTxTimestampCallback(void)
{
  MAC_ASSERT(pMacDataTx != NULL); /* transmit structure must be there */

  pMacDataTx->internal.timestamp  = macBackoffTimerCapture();
  pMacDataTx->internal.timestamp2 = MAC_RADIO_TIMER_CAPTURE();
}


/**************************************************************************************************
 * @fn          macTxCollisionWithRxCallback
 *
 * @brief       Function called if transmit strobed on top of a receive.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macTxCollisionWithRxCallback(void)
{
  macRxHaltCleanup();
}



/**************************************************************************************************
 *                                  Compile Time Integrity Checks
 **************************************************************************************************
 */
#if (MAC_TX_ACTIVE_NO_ACTIVITY != 0x00)
#error "ERROR! Zero is reserved value of macTxActive. Allows boolean operations, e.g !macTxActive."
#endif

/**************************************************************************************************
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -