⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispatchslottedcsmap.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 2 页
字号:
/*
 * 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.7 $
 * $Date: 2009/05/14 13:20:35 $
 * @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 the CAP of beacon-enabled PANs. Its main tasks are
 * initialization of the parameters of the slotted CSMA-CA algorithm (NB, BE,
 * etc.), initiating retransmissions and dealing with broadcast transmissions.
 * 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.
 *
 * This module does slightly different things depending on whether it is the
 * CAP for an outgoing superframe (sfDirection = OUTGOING_SUPERFRAME), i.e. the
 * CAP from the perspective of a coordinator after it has transmitted its own
 * beacon; or for an incoming superframe (sfDirection = INCOMING_SUPERFRAME),
 * i.e.  the CAP from the perspective of a device after it has received a
 * beacon from its coordinator. For example, in the CAP a coordinator will
 * typically listen for incoming frames from the devices, and a device will
 * typically switch the radio off unless it has a frame to transmit.
 */

generic module DispatchSlottedCsmaP(uint8_t sfDirection)
{
  provides
  {
    interface Init as Reset;
    interface FrameTx as FrameTx;
    interface FrameRx as FrameRx[uint8_t frameType];
    interface FrameExtracted as FrameExtracted[uint8_t frameType];
    interface FrameTxNow as BroadcastTx;
    interface Notify<bool> as WasRxEnabled;
  }
  uses
  {
    interface Alarm<TSymbolIEEE802154,uint32_t> as CapEndAlarm;
    interface Alarm<TSymbolIEEE802154,uint32_t> as BLEAlarm;
    interface Alarm<TSymbolIEEE802154,uint32_t> as RxWaitAlarm;
    interface TransferableResource as RadioToken;
    interface ResourceRequested as RadioTokenRequested;
    interface SuperframeStructure; 
    interface GetNow<token_requested_t> as IsRadioTokenRequested;
    interface GetNow<bool> as IsRxEnableActive; 
    interface Get<ieee154_txframe_t*> as GetIndirectTxFrame; 
    interface Notify<bool> as RxEnableStateChange;
    interface GetNow<bool> as IsTrackingBeacons;
    interface Notify<const void*> as PIBUpdateMacRxOnWhenIdle;
    interface FrameUtility;
    interface SlottedCsmaCa;
    interface RadioRx;
    interface RadioOff;
    interface MLME_GET;
    interface MLME_SET;
    interface TimeCalc;
    interface Leds;
    interface SetNow<ieee154_cap_frame_backup_t*> as FrameBackup;
    interface GetNow<ieee154_cap_frame_backup_t*> as FrameRestore;
    interface StdControl as TrackSingleBeacon;
  }
}
implementation
{
  typedef enum {
    SWITCH_OFF,       
    WAIT_FOR_RXDONE,  
    WAIT_FOR_TXDONE,  
    DO_NOTHING,       
  } next_state_t; 

  typedef enum {
    INDIRECT_TX_ALARM,
    BROADCAST_ALARM,
    NO_ALARM,
  } rx_alarm_t;

  enum {
    COORD_ROLE = (sfDirection == OUTGOING_SUPERFRAME),
    DEVICE_ROLE = !COORD_ROLE,
    RADIO_CLIENT_CFP = COORD_ROLE ? RADIO_CLIENT_COORDCFP : RADIO_CLIENT_DEVICECFP,
  };

  /* state / frame management */
  norace bool m_lock;
  norace bool m_resume;
  norace ieee154_txframe_t *m_currentFrame;
  norace ieee154_txframe_t *m_bcastFrame;
  norace ieee154_txframe_t *m_lastFrame;
  norace uint16_t m_remainingBackoff;
  ieee154_macRxOnWhenIdle_t macRxOnWhenIdle;

  /* variables for the slotted 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;
  norace bool m_broadcastRxPending;
  norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime;

  /* function / task prototypes */
  void stopAllAlarms();
  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 setupTxBroadcastTask();
  task void wasRxEnabledTask();

#ifdef TKN154_DEBUG
  enum {
    HEADER_STR_LEN = 27,
    DBG_STR_SIZE = 250,
  };
  norace uint16_t m_dbgNumEntries;
  norace char m_dbgStr[HEADER_STR_LEN + DBG_STR_SIZE] = "updateState() transitions: ";
  void dbg_push_state(uint8_t state) {
    if (m_dbgNumEntries < DBG_STR_SIZE-3)
      m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '0' + state; 
  }
  void dbg_flush_state() {
    m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '\n'; 
    m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = 0; 
    dbg_serial("DispatchSlottedCsmaP",m_dbgStr);
    m_dbgNumEntries = 0;
  }
#else 
#define dbg_push_state(X)
#define dbg_flush_state()
#endif

  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);
    if (m_bcastFrame)
      signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW);
    m_currentFrame = m_lastFrame = m_bcastFrame = NULL;
    m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
    stopAllAlarms();
    return SUCCESS;
  }

  async event void RadioToken.transferredFrom(uint8_t fromClient)
  {
    // we got the token, i.e. CAP has just started
    uint32_t capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * 
      (uint32_t) call SuperframeStructure.sfSlotDuration();
    uint16_t guardTime = call SuperframeStructure.guardTime();

    dbg_serial("DispatchSlottedCsmaP", "Got token, remaining CAP time: %lu\n", 
        call SuperframeStructure.sfStartTime() + capDuration - guardTime - call CapEndAlarm.getNow());
    if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) {
      // very rare case: 
      // this can only happen, if we're on a beacon-enabled PAN, not tracking beacons,   
      // and searched but didn't find a beacon for aBaseSuperframeDuration*(2n+1) symbols
      // we'd actually have to transmit the current frame using unslotted CSMA-CA        
      // but we don't have that functionality available... signal FAIL...                
      m_lastFrame = m_currentFrame;
      m_currentFrame = NULL;
      m_txStatus = IEEE154_NO_BEACON;
      post signalTxDoneTask();
      return;
    } else if (capDuration < guardTime) {
      // CAP is too short to do anything practical
      dbg_serial("DispatchSlottedCsmaP", "CAP too short!\n");
      call RadioToken.transferTo(RADIO_CLIENT_CFP);
      return;
    } else {
      capDuration -= guardTime;
      if (DEVICE_ROLE)
        m_broadcastRxPending = call SuperframeStructure.isBroadcastPending();
      else { 
        // COORD_ROLE
        if (m_bcastFrame != NULL) {
          // we have to transmit a broadcast frame immediately; this
          // may require to a backup of the previously active frame 
          // and a reinitializing the CSMA parameters -> will do it 
          // in task context and then continue
          m_lock = TRUE;
          post setupTxBroadcastTask(); 
          dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast.\n");
        }
      }
      call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration);
      if (call SuperframeStructure.battLifeExtDuration() > 0)
        call BLEAlarm.startAt(call SuperframeStructure.sfStartTime(), call SuperframeStructure.battLifeExtDuration());
    }
    updateState();
  }

  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("DispatchSlottedCsmaP", "Overflow\n");
      return IEEE154_TRANSACTION_OVERFLOW;
    } else {
      setCurrentFrame(frame);
      dbg("DispatchSlottedCsmaP", "New frame to transmit, DSN: %lu\n", (uint32_t) MHR(frame)[MHR_INDEX_SEQNO]);
      // a beacon must be found before transmitting in a beacon-enabled PAN
      if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) {
        call TrackSingleBeacon.start();
        dbg_serial("DispatchSlottedCsmaP", "Tracking single beacon now\n");
        // we'll receive the Token  after a beacon was found or after
        // aBaseSuperframeDuration*(2n+1) symbols if none was found  
      }
      updateState();
      return IEEE154_SUCCESS;
    }
  }

  task void setupTxBroadcastTask()
  {
    ieee154_macDSN_t tmp;
    ieee154_txframe_t *oldFrame = m_currentFrame;
    if (COORD_ROLE) {
      if (m_bcastFrame != NULL) {
        // broadcasts should be transmitted *immediately* after the beacon,  
        // which may interrupt a pending transmit operation from the previous
        // CAP; back up the last active frame configuration (may be none)    
        // and restore it after the broadcast frame has been transmitted;    
        // do this through interfaces and don't wire them for DEVICE_ROLE,   
        // so we don't waste the RAM of devices
        backupCurrentFrame();
        setCurrentFrame(m_bcastFrame);
        if (oldFrame) {
          // now the sequence number are out of order... swap them back
          tmp = m_bcastFrame->header->mhr[MHR_INDEX_SEQNO];
          m_bcastFrame->header->mhr[MHR_INDEX_SEQNO] = 
            oldFrame->header->mhr[MHR_INDEX_SEQNO];
          oldFrame->header->mhr[MHR_INDEX_SEQNO] = tmp;
        }
      }
    }
    m_lock = FALSE;
    updateState(); 
  }

  void setCurrentFrame(ieee154_txframe_t *frame)
  {
    ieee154_macDSN_t dsn = call MLME_GET.macDSN();
    frame->header->mhr[MHR_INDEX_SEQNO] = dsn++;
    call MLME_SET.macDSN(dsn);
    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 (COORD_ROLE && 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_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
    m_currentFrame = frame;
  }
 
  void stopAllAlarms()
  {
    call CapEndAlarm.stop();
    if (DEVICE_ROLE)
      call RxWaitAlarm.stop();
    call BLEAlarm.stop();
  }

  /** 
   * The updateState() function is called whenever something 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
   * the SlottedCsmaCa/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, e.g. it first always checks
   * whether the CAP is still active. Calling this function more than necessary
   * can do no harm.
   */ 

  void updateState()
  {
    uint32_t capDuration; 
    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
      capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * 
               (uint32_t) call SuperframeStructure.sfSlotDuration();

      // Check 1: has the CAP finished?
      if ((COORD_ROLE || call IsTrackingBeacons.getNow()) && 
          (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), 
                capDuration - call SuperframeStructure.guardTime()) ||
          !call CapEndAlarm.isRunning())) {
        dbg_push_state(1);
        if (call RadioOff.isOff()) {
          stopAllAlarms();  // may still fire, but is locked through isOwner()
          if (DEVICE_ROLE && m_indirectTxPending)
            signal RxWaitAlarm.fired();
          m_broadcastRxPending = FALSE;
          if (COORD_ROLE && m_bcastFrame) {
            // didn't manage to transmit a broadcast
            restoreFrameFromBackup();
            signalTxBroadcastDone(m_bcastFrame, IEEE154_CHANNEL_ACCESS_FAILURE);
            m_bcastFrame = NULL;
          }
          m_lock = FALSE; // unlock
          dbg_flush_state();
          dbg_serial("DispatchSlottedCsmaP", "Handing over to CFP.\n");
          call RadioToken.transferTo(RADIO_CLIENT_CFP);
          return;
        } else 
          next = SWITCH_OFF;
      }

      // Check 2: should a broadcast frame be received/transmitted
      // immediately at the start of CAP?

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -