📄 mac_tx_engine.c
字号:
case MTX_STATUS_ACK_HANDLER_CREATED:
// Keep the current status/state
return;
case MTX_STATUS_CHANNEL_ACCESS_FAILURE:
// Increment the number of backoffs
mtxInfo.nb++;
// Fail because of "channel access failure"?
if (mtxInfo.nb > mpib.macMaxCsmaBackoffs) {
#if MAC_OPT_FFD
// For indirect packets with one or more retries left...
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
// Or retry?
} else {
// Update counters
pPacket->slotted = !((mpib.macBeaconOrder == 15) || (pPacket->txMode & MTX_MODE_FORCE_UNSLOTTED_BM));
mtxInfo.be = MIN(mtxInfo.be + 1, aMaxBE);
// Random delay before the next attempt
pTask->state = MTX_STATE_SET_STARTUP_TIME;
}
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--;
#if MAC_OPT_FFD
// Indirect packets don't retry autmatically!
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_INIT_CSMACA;
}
#else
pTask->state = MTX_STATE_INIT_CSMACA;
#endif
}
break;
case MTX_STATUS_ACK_RECEIVED:
case MTX_STATUS_TX_FINISHED:
mtxFinishTransmission(SUCCESS, pPacket, pTask);
break;
}
mtxInfo.status = MTX_STATUS_FINISHED;
break;
}
} // mtxScheduleTransmission
//-------------------------------------------------------------------------------------------------------
// mtxStartTransmission(MAC_TASK_INFO *pTask)
//
// DESCRIPTION:
// This task is responsible for transmitting a packet when the time has come. The task turns on RX,
// performs CCA-checking, issues the STXON(CCA) command strobe, and writes to the TX FIFO.
//
// The FIFOP interrupt is disabled throughout this process, and the RX engine is cleaned up
// afterwards, if necessary.
//-------------------------------------------------------------------------------------------------------
void mtxStartTransmission(MAC_TASK_INFO *pTask) {
BYTE temp;
BOOL sfdWasActiveBeforeStrobe;
MAC_TX_PACKET *pPacket = (MAC_TX_PACKET*) pTask->taskData;
#if MAC_OPT_SECURITY
BYTE *pCounters;
#endif
switch (pTask->state) {
case MTX_STATE_TURN_ON_RX:
// Make sure that the FIFOP interrupt is off during the CSMA-CA procedure and the timing-critical TX FIFO access
mrxInfo.keepFifopIntOff = TRUE;
// Turn on RX to be able to do the CCA check in the CSMA-CA algorithm
if (pPacket->txMode & MTX_MODE_USE_CSMACA_BM) {
mrxIncrOnCounter();
if (pPacket->slotted) {
pTask->state = MTX_STATE_CCA;
} else {
pTask->state = MTX_STATE_START_TRANSMISSION;
}
} else {
mrxAutoIncrOnCounter();
pTask->state = MTX_STATE_START_TRANSMISSION;
}
// Flush the TX FIFO
DISABLE_GLOBAL_INT();
FASTSPI_STROBE(CC2420_SFLUSHTX);
ENABLE_GLOBAL_INT();
#if MAC_OPT_SECURITY
// Write key and nonce to RAM (this will not interfere with RX)
pCounters = (BYTE*) pPacket->pPayload + (pPacket->securitySetup.clearTextLength - pPacket->headerLength);
msecSetupCC2420KeyAndNonce(TRUE, &pPacket->securitySetup, pPacket->pSecurityMaterial->pSymmetricKey, pCounters);
#endif
break;
case MTX_STATE_CCA:
// CCA check on the backoff slot boundary
DISABLE_GLOBAL_INT();
WAIT_FOR_BOUNDARY();
if (CCA_IS_ACTIVE()) {
pTask->state = MTX_STATE_START_TRANSMISSION;
} else {
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_RESERVED_BM | MSCH_KEEP_TASK_IN_PROGRESS_BM);
mtxInfo.status = MTX_STATUS_CHANNEL_ACCESS_FAILURE;
mrxDecrOnCounter();
mrxInfo.keepFifopIntOff = FALSE;
}
ENABLE_GLOBAL_INT();
break;
case MTX_STATE_START_TRANSMISSION:
#if MAC_OPT_SECURITY
// Write to the SECCTRL registers (this could interfere with RX, however SFD_IS_1 should
// have indicated that RX has started, and the coming CCA check should handle the case where RX is
// just about to start (the security registers are written after the header has been received)
msecSetupCC2420Regs(&pPacket->securitySetup);
#endif
// Start TX
DISABLE_GLOBAL_INT();
if (pPacket->txMode & MTX_MODE_USE_CSMACA_BM) {
// Wait for the backoff slot boundary before transmitting ...
if (pPacket->slotted) {
WAIT_FOR_BOUNDARY();
// ... or just wait for the RSSI value to become valid?
} else {
do {
FASTSPI_UPD_STATUS(temp);
} while (!(temp & CC2420_RSSI_VALID_BM));
}
// Start TX if the CCA check passes
#if MAC_OPT_TRANSMIT_POWER
msupSetTransmitPower();
#endif
sfdWasActiveBeforeStrobe = SFD_IS_ACTIVE();
FASTSPI_STROBE(CC2420_STXONCCA);
// Was TX started?
FASTSPI_UPD_STATUS(temp);
if (!(temp & CC2420_TX_ACTIVE_BM)) {
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_RESERVED_BM | MSCH_KEEP_TASK_IN_PROGRESS_BM);
mtxInfo.status = MTX_STATUS_CHANNEL_ACCESS_FAILURE;
mrxDecrOnCounter();
mrxInfo.keepFifopIntOff = FALSE;
ENABLE_GLOBAL_INT();
break;
}
} else {
// Wait for the backoff slot boundary before transmitting?
if (pPacket->slotted) {
WAIT_FOR_BOUNDARY();
}
// Start TX without any CCA check
#if MAC_OPT_TRANSMIT_POWER
msupSetTransmitPower();
#endif
sfdWasActiveBeforeStrobe = SFD_IS_ACTIVE();
FASTSPI_STROBE(CC2420_STXON);
}
ENABLE_GLOBAL_INT();
// Set the TX finished / no acknowledgment timeout
// An additional backoff period has been added to take
mtimSetCallback(mtxPacketTimeout, pPacket->duration + 1);
// Write length and header to the TX FIFO
msupWriteFifo((BYTE*)&pPacket->length, pPacket->headerLength + 1);///
// Calculate the payload length, and write the payload to the TX FIFO
#if MAC_OPT_SECURITY
temp = pPacket->length - pPacket->headerLength - pPacket->securitySetup.micLength - MAC_FCS_LENGTH;
#else
temp = pPacket->length - pPacket->headerLength - MAC_FCS_LENGTH;
#endif
msupWriteFifo((BYTE*)pPacket->pPayload, temp);///
// Clean up the RX engine if necessary
if (sfdWasActiveBeforeStrobe) {
mrxResetRxEngine();
}
mrxInfo.keepFifopIntOff = FALSE;
// Done :)
//Need to verify that it is actualy the data frame and not a becon we are sendig. If it is a beacon
//it will bypass the mtxSchedueleTransmission task and send frame at once. If a nother packet is queed while
//we are sending beacon it need to continue after beacon is finished. This check solved this.
if (pPacket == mtxInfo.pPacket)
mtxInfo.status = MTX_STATUS_TRANSMISSION_STARTED;
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_RESERVED_BM | MSCH_KEEP_TASK_IN_PROGRESS_BM);
break;
}
} // mtxStartTransmission
/*******************************************************************************************************
* Revision history:
*
* $Log: mac_tx_engine.c,v $
* Revision 1.17 2005/02/04 14:15:41 thl
* removed flushing of rx buffer after seting cc2420 to tx
*
* Revision 1.16 2005/02/04 13:16:06 thl
* Fixed problem with oncounter and CC2420 when disabling RX
*
* Revision 1.15 2005/01/05 10:45:29 thl
* Added full suport for ppib.phyTransmitPower, will also now adjust the transmit power
* of the radio chip. to include set compile switch MAC_OPT_TRANSMIT_POWER=1 in
* make file.
*
* Revision 1.14 2004/12/07 09:47:50 thl
* Fixed potential coruption of memmory when max payload is recived.
*
* Revision 1.13 2004/11/18 15:07:58 thl
* Added support for pending frame bit in outgoing data frames.
* Only apply to outgoing data frames and wherer the address matches
* one or more packet in the indirect packet quee.
*
* Revision 1.12 2004/11/10 09:33:16 thl
* Fixed a number of bugs according to: MAC software check lists.xls
*
* Revision 1.11 2004/08/13 13:04:48 jol
* CC2420 MAC Release v0.7
*
*
*******************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -