📄 mac_tx_engine.c
字号:
mrxDecrOnCounter();
mtxInfo.beaconSearchEnabled = FALSE;
mtxInfo.beaconSearchTimeout = FALSE;
mtimCancelCallback(mtxBeaconSearchTimeout);
}
// Go ahead if there's sufficient CAP left (otherwise remain in the OUT_OF_CAP state)
if (T2_IS_CAP_ACTIVE()) {
mtxInfo.waitForBeacon = FALSE;
mtxInfo.status = MTX_STATUS_WAITING;
mtxInfo.cspTimeout = mtxCalcCspTimeout();
if (mtxInfo.cspTimeout) {
mtxCreateStartTask();
mtxInfo.status = MTX_STATUS_WAITING;
} else {
mtxInfo.status = MTX_STATUS_OUT_OF_CAP;
}
}
}
} // mtxResumeAfterBeacon
void mtxResetBosCounter(void) NEAR {
// New CAP begins
T2_SET_OVERFLOW_COUNTER(0x00000);
T2_SET_OVERFLOW_COUNTER_COMPARE_VALUE(msupCalcCapDuration());
T2_SET_CAP_ACTIVE();
// Schedule the next beacon handler
if (mpib.macBeaconOrder != 15) {
mtimSetCallback(mbcnTxPeriodicalBeacon, msupCalcBeaconInterval() - MBCN_TX_STARTUP_OVERHEAD - MBCN_TX_PREPARE_TIME);
}
}
//-------------------------------------------------------------------------------------------------------
// void mtxAckTimeout(void)
//
// DESCRIPTION:
//-------------------------------------------------------------------------------------------------------
void mtxAckTimeout(void) NEAR {
mrxDecrOnCounter();
FSMTC1 &= ~FSMTC1_ACCEPT_ACKPKT_BM;
if (mtxInfo.status == MTX_STATUS_WAITING_FOR_ACK) {
mtxInfo.status = MTX_STATUS_ACK_TIMEOUT;
}
} // mtxAckTimeout
//-------------------------------------------------------------------------------------------------------
// void mtxScheduleTransmission(MAC_TASK_INFO *pTask)
//
// DESCRIPTION:
// This task is created to start a transmission. The task is responsible for setting up the CSMA-CA
// mechanism, scheduling the transmission, and handle the result when the packet timeout is trigged.
// Note: Periodically transmitted beacons bypass this task and uses mtxStartTransmission directly.
//-------------------------------------------------------------------------------------------------------
void mtxScheduleTransmission(MAC_TASK_INFO *pTask) NEAR {
MAC_TX_PACKET *pPacket = (MAC_TX_PACKET *) pTask->taskData;
switch (pTask->state) {
case MTX_STATE_INIT_TRANSMISSION:
// Reschedule this task if we're in scan mode and the "scan related" flag is not set on this packet
if ((macInfo.state & MAC_STATE_SCAN_BM) && !(pPacket->txMode & MTX_MODE_SCAN_RELATED_BM)) {
mschRescheduleTask(pTask, MTX_STATE_INIT_TRANSMISSION);
return;
}
// Set the TX engine packet pointer
mtxInfo.pPacket = pPacket;
// No break here!
case MTX_STATE_PROCESS_SECURITY:
pTask->state = MTX_STATE_PREPARE_STARTUP;
break;
case MTX_STATE_RETRY_TRANSMISSION:
case MTX_STATE_PREPARE_STARTUP:
// Bail out if beacon transmission is in progress
#if MAC_OPT_FFD
if (mtxInfo.beaconTransmissionInProgress) {
if ((pPacket->txOptions & TX_OPT_INDIRECT)) {
miqSetRequested(pPacket, FALSE);
pPacket->transmissionStarted = FALSE;
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
}
break;
}
#endif
// Reset CSMA-CA parameters
mtxInfo.nb = mpib.macMaxCsmaBackoffs;
mtxInfo.be = mpib.macMinBE;
pPacket->slotted = !(BYTE)((mpib.macBeaconOrder == 15) || (pPacket->txMode & MTX_MODE_FORCE_UNSLOTTED_BM));
if (pPacket->slotted && mpib.macBattLifeExt) {
mtxInfo.be = (BYTE)(MIN(2, mtxInfo.be));
}
// No break here!
case MTX_STATE_SWITCHED_TO_UNSLOTTED:
mtxInfo.randomBackoff = msupGetRandomByte() & (BM(mtxInfo.be) - 1);
mtxInfo.beaconSearchEnabled = FALSE;
// Calculate the CSP timeout constant for slotted/unslotted transmissions, and go ahead if OK
mtxInfo.cspTimeout = mtxCalcCspTimeout();
if (mtxInfo.cspTimeout) {
mtxCreateStartTask();
mtxInfo.status = MTX_STATUS_WAITING;
} else
{
#if MAC_OPT_FFD
if ((pPacket->txOptions & TX_OPT_INDIRECT)) {
miqSetRequested(pPacket, FALSE);
pPacket->transmissionStarted = FALSE;
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
} else {
mtxInfo.status = MTX_STATUS_OUT_OF_CAP;
}
#else
mtxInfo.status = MTX_STATUS_OUT_OF_CAP;
#endif
}
pTask->state = MTX_STATE_WAIT;
break;
case MTX_STATE_WAIT:
switch (mtxInfo.status) {
case MTX_STATUS_WAITING:
case MTX_STATUS_WAIT_FOR_NEXT_BEACON:
case MTX_STATUS_TRANSMISSION_STARTED:
case MTX_STATUS_WAITING_FOR_ACK:
case MTX_STATUS_ACK_HANDLER_CREATED:
// Keep the current status/state
break;
case MTX_STATUS_CHANNEL_ACCESS_FAILURE:
// For indirect packets with one or more retries left...
#if MAC_OPT_FFD
if ((pPacket->txOptions & TX_OPT_INDIRECT) && pPacket->retriesLeft) {
pPacket->retriesLeft--;
miqSetRequested(pPacket, FALSE);
pPacket->transmissionStarted = FALSE;
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
// Otherwise...
} else {
mtxFinishTransmission(CHANNEL_ACCESS_FAILURE, pPacket, pTask);
}
#else
mtxFinishTransmission(CHANNEL_ACCESS_FAILURE, pPacket, pTask);
#endif
break;
case MTX_STATUS_ACK_TIMEOUT:
// Fail because of "no acknowledgment"?
if (pPacket->retriesLeft == 0) {
mtxFinishTransmission(NO_ACK, pPacket, pTask);
// Or retry?
} else {
pPacket->retriesLeft--;
// Indirect packets don't retry autmatically!
#if MAC_OPT_FFD
if (pPacket->txOptions & TX_OPT_INDIRECT) {
miqSetRequested(pPacket, FALSE);
pPacket->transmissionStarted = FALSE;
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
} else {
pTask->state = MTX_STATE_RETRY_TRANSMISSION;
}
#else
pTask->state = MTX_STATE_RETRY_TRANSMISSION;
#endif
}
break;
case MTX_STATUS_OUT_OF_CAP:
mtxInfo.waitForBeacon = TRUE;
// When searching for the beacon...
if (mtxInfo.beaconSearchEnabled) {
// Switch to unslotted transmission when the timeout is reached
if (mtxInfo.beaconSearchTimeout) {
mtxInfo.beaconSearchEnabled = FALSE;
mtxInfo.beaconSearchTimeout = FALSE;
mtxInfo.waitForBeacon = FALSE;
mrxDecrOnCounter();
mtxInfo.nb = 0;
mtxInfo.be = mpib.macMinBE;
mtxInfo.pPacket->slotted = FALSE;
pTask->state = MTX_STATE_SWITCHED_TO_UNSLOTTED;
}
// Just wait when we're tracking the beacon or transmitting beacons
} else if (mbcnInfo.trackBeacon || GET_MF(MF_TRANSMIT_BEACON)) {
mtxInfo.status = MTX_STATUS_WAIT_FOR_NEXT_BEACON;
// Otherwise, start searching for the beacon
} else {
// Come back later if there's a temporary resource shortage
if (mtimSetCallback(mtxBeaconSearchTimeout, (INT32) msupCalcBeaconInterval() + (INT32)(aBaseSuperframeDuration / aUnitBackoffPeriod))) {
mtxInfo.beaconSearchEnabled = TRUE;
mtxInfo.beaconSearchTimeout = FALSE;
mrxIncrOnCounter();
}
mtxInfo.status = MTX_STATUS_WAIT_FOR_NEXT_BEACON;
}
break;
case MTX_STATUS_ACK_RECEIVED:
case MTX_STATUS_TX_FINISHED:
mtxFinishTransmission(SUCCESS, pPacket, pTask);
mtxInfo.status = MTX_STATUS_FINISHED;
break;
}
break;
}
} // mtxScheduleTransmission
void mtxBeaconSearchTimeout(void) NEAR {
mtxInfo.beaconSearchTimeout = TRUE;
}
//-------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------
ROOT void mtxCspStopped(BOOL txStarted) {
if (txStarted) {
if (!mtxInfo.beaconTransmissionInProgress) {
// Set the accept acknowledgment bit in good time
if (mtxInfo.pPacket->txOptions & TX_OPT_ACK_REQ) FSMTC1 |= FSMTC1_ACCEPT_ACKPKT_BM;
mtxInfo.status = MTX_STATUS_TRANSMISSION_STARTED;
}
if (FSMTC1 & FSMTC1_RX_INTERRUPTED_BM) {
mrxResetRxEngine();
}
mrxAutoIncrOnCounter();
} else {
if (CSPT != 0) {
mtxInfo.status = MTX_STATUS_CHANNEL_ACCESS_FAILURE;
} else {
mtxInfo.status = MTX_STATUS_OUT_OF_CAP;
ReadCsmaParams (&mtxInfo.be, &mtxInfo.nb, &mtxInfo.randomBackoff);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -