📄 dispatchslottedcsmap.nc
字号:
else if (DEVICE_ROLE && m_broadcastRxPending) {
// receive a broadcast from coordinator
dbg_push_state(2);
next = tryReceive();
} else if (COORD_ROLE && m_bcastFrame) {
dbg_push_state(2);
next = tryTransmit();
}
// Check 3: was an indirect transmission successfully started
// and are we now waiting for a frame from the coordinator?
else if (DEVICE_ROLE && m_indirectTxPending) {
dbg_push_state(3);
next = tryReceive();
}
// Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending?
else if (call IsRadioTokenRequested.getNow()) {
dbg_push_state(4);
if (call RadioOff.isOff()) {
stopAllAlarms(); // may still fire, but is locked through isOwner()
// nothing more to do... just release the Token
m_lock = FALSE; // unlock
dbg_serial("DispatchSlottedCsmaP", "Token requested: Handing over to CFP.\n");
call RadioToken.release();
return;
} else
next = SWITCH_OFF;
}
// Check 5: is battery life extension (BLE) active and
// has the BLE period expired?
else if (call SuperframeStructure.battLifeExtDuration() > 0 &&
call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(),
call SuperframeStructure.battLifeExtDuration()) &&
!call IsRxEnableActive.getNow() && !macRxOnWhenIdle) {
dbg_push_state(5);
next = trySwitchOff();
}
// Check 6: is there a frame ready to transmit?
else if (m_currentFrame != NULL) {
dbg_push_state(6);
next = tryTransmit();
}
// Check 7: should we be in receive mode?
else if (COORD_ROLE || call IsRxEnableActive.getNow() || macRxOnWhenIdle) {
dbg_push_state(7);
next = tryReceive();
if (next == DO_NOTHING) {
// if there was an active MLME_RX_ENABLE.request then we'll
// inform the next higher layer that radio is now in Rx mode
post wasRxEnabledTask();
}
}
// Check 8: just make sure the radio is switched off
else {
dbg_push_state(8);
next = trySwitchOff();
}
// if there is nothing to do, then we must clear the lock
if (next == DO_NOTHING)
m_lock = FALSE;
} // atomic
// put next state in operation (possibly keeping the lock)
switch (next)
{
case SWITCH_OFF: ASSERT(call RadioOff.off() == SUCCESS); break;
case WAIT_FOR_RXDONE: break;
case WAIT_FOR_TXDONE: break;
case DO_NOTHING: break;
}
}
next_state_t tryTransmit()
{
// tries to transmit m_currentFrame
uint32_t capDuration = (uint32_t) call SuperframeStructure.numCapSlots() *
(uint32_t) call SuperframeStructure.sfSlotDuration();
next_state_t next;
if (!call RadioOff.isOff())
next = SWITCH_OFF;
else {
uint32_t dtMax = capDuration - call SuperframeStructure.guardTime() - m_transactionTime;
// round to backoff boundary
dtMax = dtMax + (IEEE154_aUnitBackoffPeriod - (dtMax % IEEE154_aUnitBackoffPeriod));
if (dtMax > capDuration)
dtMax = 0;
if (call SuperframeStructure.battLifeExtDuration() > 0) {
// battery life extension
uint16_t bleLen = call SuperframeStructure.battLifeExtDuration();
if (bleLen < dtMax)
dtMax = bleLen;
}
if (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), dtMax))
next = DO_NOTHING; // frame doesn't fit in the remaining CAP
else {
error_t res;
res = call SlottedCsmaCa.transmit(m_currentFrame, &m_csma,
call SuperframeStructure.sfStartTimeRef(), dtMax, m_resume, m_remainingBackoff);
dbg("DispatchSlottedCsmaP", "SlottedCsmaCa.transmit() -> %lu\n", (uint32_t) res);
next = WAIT_FOR_TXDONE; // this will NOT clear the lock
}
}
return next;
}
next_state_t tryReceive()
{
next_state_t next;
if (call RadioRx.isReceiving())
next = DO_NOTHING;
else if (!call RadioOff.isOff())
next = SWITCH_OFF;
else {
call RadioRx.enableRx(0, 0);
next = WAIT_FOR_RXDONE;
}
return next;
}
next_state_t trySwitchOff()
{
next_state_t next;
if (call RadioOff.isOff())
next = DO_NOTHING;
else
next = SWITCH_OFF;
return next;
}
async event void RadioOff.offDone()
{
m_lock = FALSE;
updateState();
}
async event void RadioRx.enableRxDone()
{
if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending))
call RxWaitAlarm.start(m_macMaxFrameTotalWaitTime);
m_lock = FALSE;
updateState();
}
async event void CapEndAlarm.fired() {
dbg_serial("DispatchSlottedCsmaP", "CapEndAlarm.fired()\n");
updateState();
}
async event void BLEAlarm.fired() { updateState();}
event void RxEnableStateChange.notify(bool whatever) { updateState();}
event void PIBUpdateMacRxOnWhenIdle.notify( const void* val ) {
atomic macRxOnWhenIdle = *((ieee154_macRxOnWhenIdle_t*) val);
updateState();
}
async event void RxWaitAlarm.fired()
{
if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending))
atomic {
if (m_indirectTxPending) {
m_indirectTxPending = FALSE;
post signalTxDoneTask();
} else if (m_broadcastRxPending) {
m_broadcastRxPending = FALSE;
updateState();
}
}
}
async event void SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma,
bool ackPendingFlag, uint16_t remainingBackoff, error_t result)
{
bool done = TRUE;
dbg("DispatchSlottedCsmaP", "SlottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result);
m_resume = FALSE;
switch (result)
{
case SUCCESS:
// frame was successfully transmitted, if ACK was requested
// then a matching ACK was successfully received as well
m_txStatus = IEEE154_SUCCESS;
if (DEVICE_ROLE && frame->payload[0] == CMD_FRAME_DATA_REQUEST &&
((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD) {
// this was a data request frame
m_txStatus = IEEE154_NO_DATA; // pessimistic
if (ackPendingFlag) {
// the coordinator has data for us; switch to Rx
// to complete the indirect transmission
m_indirectTxPending = TRUE;
m_lastFrame = m_currentFrame;
m_currentFrame = NULL;
ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS);
return;
}
}
break;
case FAIL:
// The CSMA-CA algorithm failed: the frame was not transmitted,
// because channel was never idle
m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE;
break;
case ENOACK:
// frame was transmitted, but we didn't receive an ACK (although
// we requested an one). note: coordinator never retransmits an
// indirect transmission (see above)
if (m_macMaxFrameRetries > 0) {
// retransmit: reinitialize CSMA-CA parameters
done = FALSE;
m_csma.NB = 0;
m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs;
m_csma.macMaxBE = m_macMaxBE;
m_csma.BE = m_BE;
m_macMaxFrameRetries -= 1;
} else
m_txStatus = IEEE154_NO_ACK;
break;
case EINVAL: // DEBUG!!!
dbg_serial("DispatchSlottedCsmaP", "EINVAL returned by transmitDone()!\n");
// fall through
case ERETRY:
// frame was not transmitted, because the transaction does not
// fit in the remaining CAP (in beacon-enabled PANs only)
dbg_serial("DispatchSlottedCsmaP", "Transaction didn't fit, current BE: %lu\n", (uint32_t) csma->BE);
m_resume = TRUE;
m_remainingBackoff = remainingBackoff;
done = FALSE;
m_lock = FALSE; // debug! problem: if CAP endalarm has fired it's a deadlock!
if (!call CapEndAlarm.isRunning())
updateState();
return;
break;
default:
ASSERT(0);
break;
}
if (COORD_ROLE && frame == m_bcastFrame) {
// always signal result of broadcast transmissions immediately
restoreFrameFromBackup();
signalTxBroadcastDone(m_bcastFrame, (!done) ? IEEE154_CHANNEL_ACCESS_FAILURE : m_txStatus);
m_bcastFrame = NULL;
} else if (done) {
m_lastFrame = m_currentFrame;
m_currentFrame = NULL;
post signalTxDoneTask();
}
m_lock = FALSE;
updateState();
}
task void signalTxDoneTask()
{
ieee154_txframe_t *lastFrame = m_lastFrame;
ieee154_status_t status = m_txStatus;
m_indirectTxPending = FALSE;
m_lastFrame = NULL; // only now can the next transmission can begin
if (lastFrame) {
dbg("DispatchSlottedCsmaP", "Transmit done, DSN: %lu, result: 0x%lx\n",
(uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status);
signal FrameTx.transmitDone(lastFrame, status);
}
updateState();
}
event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp)
{
// received a frame -> find out frame type and
// signal it to responsible client component
uint8_t *payload = (uint8_t *) frame->data;
uint8_t *mhr = MHR(frame);
uint8_t frameType = mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK;
if (frameType == FC1_FRAMETYPE_CMD)
frameType += payload[0];
dbg("DispatchSlottedCsmaP", "Received frame, DSN: %lu, type: 0x%lu\n",
(uint32_t) mhr[MHR_INDEX_SEQNO], (uint32_t) frameType);
atomic {
if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending)) {
message_t* frameBuf;
call RxWaitAlarm.stop();
// TODO: check the following:
// is this frame from our coordinator? hmm... we cannot say/ with
// certainty, because we might only know either the coordinator
// extended or short address (and the frame could/ have been sent
// with the other addressing mode) ??
m_txStatus = IEEE154_SUCCESS;
if (m_indirectTxPending)
frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); // indirect tx from coord
else
frameBuf = signal FrameRx.received[frameType](frame); // broadcast from coordinator
signal RxWaitAlarm.fired();
return frameBuf;
} else
return signal FrameRx.received[frameType](frame);
}
}
void backupCurrentFrame()
{
ieee154_cap_frame_backup_t backup = {m_currentFrame, m_csma, m_transactionTime};
call FrameBackup.setNow(&backup);
}
void restoreFrameFromBackup()
{
ieee154_cap_frame_backup_t *backup = call FrameRestore.getNow();
if (backup != NULL) {
m_currentFrame = backup->frame;
memcpy(&m_csma, &backup->csma, sizeof(ieee154_csma_t));
m_transactionTime = backup->transactionTime;
}
}
async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame)
{
// if this command is called then it is (MUST be) called only just before
// the token is transferred to this component and it is then called
// only once per CAP (max. one broadcast is allowed after a beacon
// transmission)
atomic {
if (!call RadioToken.isOwner() && m_bcastFrame == NULL) {
m_bcastFrame = frame;
return IEEE154_SUCCESS;
} else {
ASSERT(0);
return IEEE154_TRANSACTION_OVERFLOW;
}
}
}
void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error)
{
signal BroadcastTx.transmitNowDone(frame, error);
}
task void wasRxEnabledTask()
{
signal WasRxEnabled.notify(TRUE);
}
event void RadioToken.granted()
{
ASSERT(0); // should never happen
}
default event void FrameTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status) {}
default event message_t* FrameRx.received[uint8_t client](message_t* data) {return data;}
default async command bool IsRxEnableActive.getNow() {return FALSE;}
default async command void RxWaitAlarm.start(uint32_t dt) {ASSERT(0);}
default async command void RxWaitAlarm.stop() {ASSERT(0);}
default async command void RxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
default async command bool SuperframeStructure.isBroadcastPending() { return FALSE;}
default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status) {}
default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame) {return msg;}
default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val) {return FAIL;}
default async command ieee154_cap_frame_backup_t* FrameRestore.getNow() {return NULL;}
default command error_t TrackSingleBeacon.start() {return FAIL;}
command error_t WasRxEnabled.enable() {return FAIL;}
command error_t WasRxEnabled.disable() {return FAIL;}
async event void RadioTokenRequested.requested(){ updateState(); }
async event void RadioTokenRequested.immediateRequested(){ updateState(); }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -