📄 dispatchunslottedcsmap.nc
字号:
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.10 $
* $Date: 2009/05/18 12:54:10 $
* @author Jan Hauer <hauer@tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_PHY.h"
#include "TKN154_MAC.h"
/**
* This module is responsible for the transmission/reception of DATA and
* COMMAND frames in a nonbeacon-enabled PAN. Its main tasks are initialization
* of the parameters of the unslotted CSMA-CA algorithm (NB, BE, etc.),
* initiating retransmissions and managing requests for enabling the receiver
* for a finite period of time. It does not implement the actual CSMA-CA
* algorithm, because due to its timing requirements the CSMA-CA algorithm is
* not part of the MAC implementation but of the chip-specific radio driver.
*/
module DispatchUnslottedCsmaP
{
provides
{
interface Init as Reset;
interface MLME_START;
interface FrameTx as FrameTx;
interface FrameRx as FrameRx[uint8_t frameType];
interface FrameExtracted as FrameExtracted[uint8_t frameType];
interface Notify<bool> as WasRxEnabled;
}
uses
{
interface Timer<TSymbolIEEE802154> as IndirectTxWaitTimer;
interface TransferableResource as RadioToken;
interface ResourceRequested as RadioTokenRequested;
interface GetNow<token_requested_t> as IsRadioTokenRequested;
interface GetNow<bool> as IsRxEnableActive;
interface Set<ieee154_macSuperframeOrder_t> as SetMacSuperframeOrder;
interface Set<ieee154_macPanCoordinator_t> as SetMacPanCoordinator;
interface Get<ieee154_txframe_t*> as GetIndirectTxFrame;
interface Notify<bool> as RxEnableStateChange;
interface Notify<const void*> as PIBUpdateMacRxOnWhenIdle;
interface FrameUtility;
interface UnslottedCsmaCa;
interface RadioRx;
interface RadioOff;
interface MLME_GET;
interface MLME_SET;
interface TimeCalc;
interface Leds;
}
}
implementation
{
typedef enum {
SWITCH_OFF,
WAIT_FOR_RXDONE,
WAIT_FOR_TXDONE,
DO_NOTHING,
} next_state_t;
typedef enum {
INDIRECT_TX_ALARM,
NO_ALARM,
} rx_alarm_t;
/* state / frame management */
norace bool m_lock;
norace bool m_resume;
norace ieee154_txframe_t *m_currentFrame;
norace ieee154_txframe_t *m_lastFrame;
norace ieee154_macRxOnWhenIdle_t m_macRxOnWhenIdle;
/* variables for the unslotted CSMA-CA */
norace ieee154_csma_t m_csma;
norace ieee154_macMaxBE_t m_BE;
norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs;
norace ieee154_macMaxBE_t m_macMaxBE;
norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries;
norace ieee154_status_t m_txStatus;
norace uint32_t m_transactionTime;
norace bool m_indirectTxPending = FALSE;
/* function / task prototypes */
next_state_t tryReceive();
next_state_t tryTransmit();
next_state_t trySwitchOff();
void backupCurrentFrame();
void restoreFrameFromBackup();
void updateState();
void setCurrentFrame(ieee154_txframe_t *frame);
void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error);
task void signalTxDoneTask();
task void wasRxEnabledTask();
task void startIndirectTxTimerTask();
task void signalStartConfirmTask();
command error_t Reset.init()
{
if (m_currentFrame)
signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW);
if (m_lastFrame)
signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW);
m_currentFrame = m_lastFrame = NULL;
call IndirectTxWaitTimer.stop();
return SUCCESS;
}
command ieee154_status_t MLME_START.request (
uint16_t panID,
uint8_t logicalChannel,
uint8_t channelPage,
uint32_t startTime,
uint8_t beaconOrder,
uint8_t superframeOrder,
bool panCoordinator,
bool batteryLifeExtension,
bool coordRealignment,
ieee154_security_t *coordRealignSecurity,
ieee154_security_t *beaconSecurity)
{
ieee154_status_t status;
ieee154_macShortAddress_t shortAddress = call MLME_GET.macShortAddress();
// check parameters
if ((coordRealignSecurity && coordRealignSecurity->SecurityLevel) ||
(beaconSecurity && beaconSecurity->SecurityLevel))
status = IEEE154_UNSUPPORTED_SECURITY;
else if (shortAddress == 0xFFFF)
status = IEEE154_NO_SHORT_ADDRESS;
else if (logicalChannel > 26 ||
(channelPage != IEEE154_SUPPORTED_CHANNELPAGE) ||
!(IEEE154_SUPPORTED_CHANNELS & ((uint32_t) 1 << logicalChannel)))
status = IEEE154_INVALID_PARAMETER;
else if (beaconOrder != 15)
status = IEEE154_INVALID_PARAMETER;
else {
call MLME_SET.macPANId(panID);
call MLME_SET.phyCurrentChannel(logicalChannel);
call MLME_SET.macBeaconOrder(beaconOrder);
call SetMacPanCoordinator.set(panCoordinator);
//TODO: check realignment
post signalStartConfirmTask();
status = IEEE154_SUCCESS;
}
dbg_serial("DispatchUnslottedCsmaP", "MLME_START.request -> result: %lu\n", (uint32_t) status);
return status;
}
task void signalStartConfirmTask()
{
signal MLME_START.confirm(IEEE154_SUCCESS);
}
command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame)
{
if (m_currentFrame != NULL) {
// we've not finished transmitting the current frame yet
dbg_serial("DispatchUnslottedCsmaP", "Overflow\n");
return IEEE154_TRANSACTION_OVERFLOW;
} else {
setCurrentFrame(frame);
if (call RadioToken.isOwner())
updateState();
else
call RadioToken.request();
return IEEE154_SUCCESS;
}
}
event void RadioToken.granted()
{
updateState();
}
void setCurrentFrame(ieee154_txframe_t *frame)
{
if (frame->header->mhr[MHR_INDEX_FC1] != FC1_FRAMETYPE_BEACON) {
// set the sequence number for command/data frame
ieee154_macDSN_t dsn = call MLME_GET.macDSN();
frame->header->mhr[MHR_INDEX_SEQNO] = dsn++;
call MLME_SET.macDSN(dsn);
} else {
// set the sequence number for beacon frame
ieee154_macBSN_t bsn = call MLME_GET.macBSN();
frame->header->mhr[MHR_INDEX_SEQNO] = bsn++;
call MLME_SET.macBSN(bsn);
}
m_csma.NB = 0;
m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs();
m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE();
m_csma.BE = call MLME_GET.macMinBE();
if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2)
m_csma.BE = 2;
m_BE = m_csma.BE;
if (call GetIndirectTxFrame.get() == frame)
m_macMaxFrameRetries = 0; // this is an indirect transmissions (never retransmit)
else
m_macMaxFrameRetries = call MLME_GET.macMaxFrameRetries();
m_transactionTime = IEEE154_SHR_DURATION +
(frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET; // extra 2 for CRC
if (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST)
m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod +
11 * IEEE154_SYMBOLS_PER_OCTET); // 11 byte for the ACK PPDU
// if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize)
// m_transactionTime += call MLME_GET.macMinLIFSPeriod();
// else
// m_transactionTime += call MLME_GET.macMinSIFSPeriod();
m_currentFrame = frame;
}
/**
* The updateState() function is called whenever some event happened that
* might require a state transition; it implements a lock mechanism (m_lock)
* to prevent race conditions. Whenever the lock is set a "done"-event (from
* a RadioTx/RadioRx/RadioOff interface) is pending and will "soon" unset the
* lock (and then updateState() will called again). The updateState()
* function decides about the next state by checking a list of possible
* current states ordered by priority. Calling this function more than
* necessary can do no harm.
*/
void updateState()
{
next_state_t next;
atomic {
// long atomics are bad... but in this block, once the
// current state has been determined only one branch will
// be taken (there are no loops)
if (m_lock || !call RadioToken.isOwner())
return;
m_lock = TRUE; // lock
// Check 1: was an indirect transmission successfully started
// and are we now waiting for a frame from the coordinator?
if (m_indirectTxPending) {
next = tryReceive();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -