📄 mac_csp_tx.c
字号:
}
/**************************************************************************************************
* @fn macCspForceTxDoneIfPending
*
* @brief The function clears out any pending TX done logic. Used by receive logic
* to make sure its ISR does not prevent transmit from completing in a reasonable
* amount of time.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspForceTxDoneIfPending(void)
{
///////////////////////////////////////////////////////////////////////////////////////
// REV_B_WORKAROUND : work workaround for chip bug #273. The instruction DECZ might
// be incorrectly executed twice, resulting an illegal value for CSPZ.
// Delete when Rev B is obsolete.
///////////////////////////////////////////////////////////////////////////////////////
#ifndef _REMOVE_REV_B_WORKAROUNDS
if (CSPZ >= 0xF8) { CSPZ = 0; }
#endif
///////////////////////////////////////////////////////////////////////////////////////
if ((CSPZ == CSPZ_CODE_TX_DONE) && MAC_MCU_CSP_STOP_INTERRUPT_IS_ENABLED())
{
MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();
if (MAC_MCU_CSP_INT_INTERRUPT_IS_ENABLED())
{
macCspTxIntIsr();
}
macTxDoneCallback();
}
}
/**************************************************************************************************
* @fn macCspTxRequestAckTimeoutCallback
*
* @brief Requests a callback after the ACK timeout period has expired. At that point,
* the function macTxAckTimeoutCallback() is called via an interrupt.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxRequestAckTimeoutCallback(void)
{
uint8 startSymbol;
uint8 symbols;
uint8 rollovers;
MAC_ASSERT(!(RFIM & IM_CSP_STOP)); /* already an active CSP program */
/* record current symbol count */
startSymbol = CSP_WEVENT_READ_COUNT_SYMBOLS();
/* set symbol timeout from PIB */
symbols = macPib.ackWaitDuration;
/* make sure delay value is not too small for logic to handle */
MAC_ASSERT(symbols > MAC_A_UNIT_BACKOFF_PERIOD); /* symbols timeout period must be great than a backoff */
/* subtract out symbols left in current backoff period */
symbols = symbols - (MAC_A_UNIT_BACKOFF_PERIOD - startSymbol);
/* calculate rollovers needed for remaining symbols */
rollovers = symbols / MAC_A_UNIT_BACKOFF_PERIOD;
/* calculate symbols that still need counted after last rollover */
symbols = symbols - (rollovers * MAC_A_UNIT_BACKOFF_PERIOD);
/* add one to rollovers to account for symbols remaining in the current backoff period */
rollovers++;
/* set up parameters for CSP program */
CSPZ = CSPZ_CODE_TX_ACK_TIME_OUT;
CSPX = rollovers;
CSP_WEVENT_SET_TRIGGER_SYMBOLS(symbols);
/* clear the currently loaded CSP, this generates a stop interrupt which must be cleared */
CSP_STOP_AND_CLEAR_PROGRAM();
MAC_MCU_CSP_STOP_CLEAR_INTERRUPT();
/*--------------------------
* load CSP program
*/
RFST = WAITX;
RFST = WEVENT;
/*--------------------------
*/
/* run CSP program */
MAC_MCU_CSP_STOP_ENABLE_INTERRUPT();
CSP_START_PROGRAM();
/*
* For bullet proof operation, must account for the boundary condition
* where a rollover occurs after count was read but before CSP program
* was started.
*
* If current symbol count is less that the symbol count recorded at the
* start of this function, a rollover has occurred.
*/
if (CSP_WEVENT_READ_COUNT_SYMBOLS() < startSymbol)
{
/* a rollover has occurred, make sure it was accounted for */
if (CSPX == rollovers)
{
/*
* Rollover event missed, manually decrement CSPX to adjust.
*
* Note : there is a very small chance that CSPX does not
* get decremented. This would occur if CSPX were written
* at exactly the same time a timer overflow is occurring (which
* causes the CSP instruction WAITX to decrement CSPX). This
* would be extremely rare, but if it does happen, the only
* consequence is that the ACK timeout period is extended
* by one backoff.
*/
CSPX--;
}
}
}
/**************************************************************************************************
* @fn macCspTxCancelAckTimeoutCallback
*
* @brief Cancels previous request for ACK timeout callback.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxCancelAckTimeoutCallback(void)
{
MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();
CSP_STOP_AND_CLEAR_PROGRAM();
}
/**************************************************************************************************
* @fn macCspTxIntIsr
*
* @brief Interrupt service routine for handling INT type interrupts from CSP.
* This interrupt happens when the CSP instruction INT is executed. It occurs
* once the SFD signal goes high indicating that transmit has successfully
* started. The timer value has been captured at this point and timestamp
* can be stored.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxIntIsr(void)
{
///////////////////////////////////////////////////////////////////////////////////////
// REV_B_WORKAROUND : work workaround for chip bug #273. The instruction DECY might
// be incorrectly executed twice, resulting an illegal value for CSPZ.
// Delete when Rev B is obsolete.
///////////////////////////////////////////////////////////////////////////////////////
#ifndef _REMOVE_REV_B_WORKAROUNDS
if (CSPY >= 0xF8) { CSPY = 0; }
#endif
///////////////////////////////////////////////////////////////////////////////////////
MAC_MCU_CSP_INT_DISABLE_INTERRUPT();
if (CSPY == CSPY_RXTX_COLLISION)
{
macRxHaltCleanup();
}
/* execute callback function that records transmit timestamp */
macTxTimestampCallback();
}
/**************************************************************************************************
* @fn macCspTxStopIsr
*
* @brief Interrupt service routine for handling STOP type interrupts from CSP.
* This interrupt occurs when the CSP program stops by 1) reaching the end of the
* program, 2) executing SSTOP within the program, 3) executing immediate
* instruction ISSTOP.
*
* The value of CSPZ indicates if interrupt is being used for ACK timeout or
* is the end of a transmit.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macCspTxStopIsr(void)
{
MAC_MCU_CSP_STOP_DISABLE_INTERRUPT();
///////////////////////////////////////////////////////////////////////////////////////
// REV_B_WORKAROUND : work workaround for chip bug #273. The instruction DECZ might
// be incorrectly executed twice, resulting an illegal value for CSPZ.
// Delete when Rev B is obsolete.
///////////////////////////////////////////////////////////////////////////////////////
#ifndef _REMOVE_REV_B_WORKAROUNDS
if (CSPZ >= 0xF8) { CSPZ = 0; }
#endif
///////////////////////////////////////////////////////////////////////////////////////
if (CSPZ == CSPZ_CODE_TX_DONE)
{
macTxDoneCallback();
}
else if (CSPZ == CSPZ_CODE_CHANNEL_BUSY)
{
macTxChannelBusyCallback();
}
else
{
MAC_ASSERT(CSPZ == CSPZ_CODE_TX_ACK_TIME_OUT); /* unexpected CSPZ value */
macTxAckNotReceivedCallback();
}
}
/**************************************************************************************************
* Compile Time Integrity Checks
**************************************************************************************************
*/
#if ((CSPY_RXTX_COLLISION != 0) || (CSPY_NO_RXTX_COLLISION != 1))
#error "ERROR! The CSPY return values are very specific and tied into the actual CSP program."
#endif
#if ((CSPZ_CODE_TX_DONE != 0) || (CSPZ_CODE_CHANNEL_BUSY != 1))
#error "ERROR! The CSPZ return values are very specific and tied into the actual CSP program."
#endif
#if (MAC_TX_TYPE_SLOTTED_CSMA != 0)
#error "WARNING! This define value changed. It was selected for optimum performance."
#endif
#if (T2THD_TICKS_PER_SYMBOL == 0)
#error "ERROR! Timer compare will not work on high byte. Clock speed is probably too slow."
#endif
#define BACKOFFS_PER_BASE_SUPERFRAME (MAC_A_BASE_SLOT_DURATION * MAC_A_NUM_SUPERFRAME_SLOTS)
#if (((BACKOFFS_PER_BASE_SUPERFRAME - 1) & SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK) != SLOTTED_TX_BACKOFF_COUNT_ALIGN_BIT_MASK)
#error "ERROR! The specified bit mask for backoff alignment of slotted transmit does not rollover 'cleanly'."
/*
* In other words, the backoff count for the number of superframe rolls over before the
* specified number of bits rollover. For example, if backoff count for a superframe
* rolls over at 48, the binary number immediately before a rollover is 00101111.
* In this case four bits would work as an alignment mask. Five would not work though as
* the lower five bits would go from 01111 to 00000 (instead of the value 10000 which
* would be expected) because it a new superframe is starting.
*/
#endif
#if (SLOTTED_TX_MAX_BACKOFF_COUNTDOWN_NUM_BITS < 2)
#error "ERROR! Not enough backoff countdown bits to be practical."
#endif
/**************************************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -