📄 mac_tx.c
字号:
* @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 + -