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

📄 framerm.nc

📁 传感器网络中的嵌入式操作系统源代码
💻 NC
字号:
// $Id: FramerM.nc,v 1.1.2.5 2003/08/26 09:08:16 cssharp Exp $/* -*- Mode: C; c-basic-indent: 2; indent-tabs-mode: nil -*- */ /*									 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By *  downloading, copying, installing or using the software you agree to *  this license.  If you do not agree to this license, do not download, *  install, copy or use the software. * *  Intel Open Source License  * *  Copyright (c) 2002 Intel Corporation  *  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 Intel Corporation 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 INTEL OR ITS *  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. *  * Author: Phil Buonadonna * Revision: $Revision: 1.1.2.5 $ *  *//* * FramerM *  * This modules provides framing for TOS_Msg's using PPP-HDLC-like framing  * (see RFC 1662).  When sending, a TOS_Msg is encapsulated in an HLDC frame. * Receiving is similar EXCEPT that the component expects a special token byte * be received before the data payload. The purpose of the token is to feed back * an acknowledgement to the sender which serves as a crude form of flow-control. * This module is intended for use with the Packetizer class found in * tools/java/net/packet/Packetizer.java. *  *//** * @author Phil Buonadonna */includes AM;includes crc;module FramerM {  provides {    interface StdControl;    interface TokenReceiveMsg;    interface ReceiveMsg;    interface BareSendMsg;  }  uses {    interface ByteComm;    interface StdControl as ByteControl;  }}implementation {  enum {    HDLC_QUEUESIZE	   = 2,    HDLC_MTU		   = (sizeof(TOS_Msg)),    HDLC_FLAG_BYTE	   = 0x7e,    HDLC_CTLESC_BYTE	   = 0x7d,    PROTO_ACK              = 64,    PROTO_PACKET_ACK       = 65,    PROTO_PACKET_NOACK     = 66,    PROTO_UNKNOWN          = 255  };  enum {    RXSTATE_NOSYNC,    RXSTATE_PROTO,    RXSTATE_TOKEN,    RXSTATE_INFO,    RXSTATE_ESC  };  enum {    TXSTATE_IDLE,    TXSTATE_PROTO,    TXSTATE_INFO,    TXSTATE_ESC,    TXSTATE_FCS1,    TXSTATE_FCS2,    TXSTATE_ENDFLAG,    TXSTATE_FINISH,    TXSTATE_ERROR  };  enum {    FLAGS_TOKENPEND = 0x2,    FLAGS_DATAPEND  = 0x4,    FLAGS_UNKNOWN   = 0x8  };  TOS_Msg gMsgRcvBuf[HDLC_QUEUESIZE];  typedef struct _MsgRcvEntry {    uint8_t Proto;    uint8_t Token;	// Used for sending acknowledgements    uint16_t Length;	// Does not include 'Proto' or 'Token' fields    TOS_MsgPtr pMsg;  } MsgRcvEntry_t ;  MsgRcvEntry_t gMsgRcvTbl[HDLC_QUEUESIZE];  uint8_t * gpRxBuf;      uint8_t * gpTxBuf;  uint8_t  gFlags;  // Flags variable protects atomicity  norace uint8_t  gTxState;  norace uint8_t  gPrevTxState;  norace uint8_t  gTxProto;  norace uint16_t gTxByteCnt;  norace uint16_t gTxLength;  norace uint16_t gTxRunningCRC;  uint8_t  gRxState;  uint8_t  gRxHeadIndex;  uint8_t  gRxTailIndex;  uint16_t gRxByteCnt;    uint16_t gRxRunningCRC;    TOS_MsgPtr gpTxMsg;  uint8_t gTxTokenBuf;  uint8_t gTxUnknownBuf;  norace uint8_t gTxEscByte;  task void PacketSent();  result_t StartTx() {    result_t Result = SUCCESS;    bool fInitiate = FALSE;    atomic {      if (gTxState == TXSTATE_IDLE) {        if (gFlags & FLAGS_TOKENPEND) {          gpTxBuf = (uint8_t *)&gTxTokenBuf;          gTxProto = PROTO_ACK;          gTxLength = sizeof(gTxTokenBuf);          fInitiate = TRUE;          gTxState = TXSTATE_PROTO;        }        else if (gFlags & FLAGS_DATAPEND) {          gpTxBuf = (uint8_t *)gpTxMsg;          gTxProto = PROTO_PACKET_NOACK;          gTxLength = gpTxMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);          fInitiate = TRUE;          gTxState = TXSTATE_PROTO;        }        else if (gFlags & FLAGS_UNKNOWN) {          gpTxBuf = (uint8_t *)&gTxUnknownBuf;          gTxProto = PROTO_UNKNOWN;          gTxLength = sizeof(gTxUnknownBuf);          fInitiate = TRUE;          gTxState = TXSTATE_PROTO;        }      }    }        if (fInitiate) {      atomic {        gTxRunningCRC = 0; gTxByteCnt = 0;      }      Result = call ByteComm.txByte(HDLC_FLAG_BYTE);      if (Result != SUCCESS) {        atomic gTxState = TXSTATE_ERROR;        post PacketSent();      }    }        return Result;  }        task void PacketUnknown() {    atomic {      gFlags |= FLAGS_UNKNOWN;    }        StartTx();  }  task void PacketRcvd() {    MsgRcvEntry_t *pRcv = &gMsgRcvTbl[gRxTailIndex];    TOS_MsgPtr pBuf = pRcv->pMsg;    // Does the rcvd frame actually have a meaningful message??    if (pRcv->Length >= offsetof(struct TOS_Msg,data)) {      switch (pRcv->Proto) {      case PROTO_ACK:        break;      case PROTO_PACKET_ACK:        pBuf->crc = 1;  // Easier to set here... 	pBuf = signal TokenReceiveMsg.receive(pBuf,pRcv->Token);	break;      case PROTO_PACKET_NOACK:        pBuf->crc = 1;	pBuf = signal ReceiveMsg.receive(pBuf);	break;      default:        gTxUnknownBuf = pRcv->Proto;        post PacketUnknown();	break;      }    }    atomic {      if (pBuf) {	pRcv->pMsg = pBuf;      }      pRcv->Length = 0;       pRcv->Token = 0;       gRxTailIndex++;      gRxTailIndex %= HDLC_QUEUESIZE;    }  }  task void PacketSent() {    result_t TxResult = SUCCESS;    atomic {      if (gTxState == TXSTATE_ERROR) {	TxResult = FAIL;        gTxState = TXSTATE_IDLE;      }    }    if (gTxProto == PROTO_ACK) {      atomic gFlags ^= FLAGS_TOKENPEND;    }    else{      atomic gFlags ^= FLAGS_DATAPEND;      signal BareSendMsg.sendDone((TOS_MsgPtr)gpTxMsg,TxResult);      atomic gpTxMsg = NULL;    }    // Trigger transmission in case something else is pending    StartTx();  }  void HDLCInitialize() {    int i;    atomic {      for (i = 0;i < HDLC_QUEUESIZE; i++) {        gMsgRcvTbl[i].pMsg = &gMsgRcvBuf[i];        gMsgRcvTbl[i].Length = 0;        gMsgRcvTbl[i].Token = 0;      }      gTxState = TXSTATE_IDLE;      gTxByteCnt = 0;      gTxLength = 0;      gTxRunningCRC = 0;      gpTxMsg = NULL;            gRxState = RXSTATE_NOSYNC;      gRxHeadIndex = 0;      gRxTailIndex = 0;      gRxByteCnt = 0;      gRxRunningCRC = 0;      gpRxBuf = (uint8_t *)gMsgRcvTbl[gRxHeadIndex].pMsg;    }  }  command result_t StdControl.init() {    HDLCInitialize();    return call ByteControl.init();  }  command result_t StdControl.start() {    HDLCInitialize();    return call ByteControl.start();  }    command result_t StdControl.stop() {    return call ByteControl.stop();  }    command result_t BareSendMsg.send(TOS_MsgPtr pMsg) {    result_t Result = SUCCESS;    atomic {      if (!(gFlags & FLAGS_DATAPEND)) {       gFlags |= FLAGS_DATAPEND;        gpTxMsg = pMsg;       //gTxLength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);       //gTxProto = PROTO_PACKET_NOACK;      }      else {        Result = FAIL;      }    }    if (Result == SUCCESS) {      Result = StartTx();    }    return Result;  }  command result_t TokenReceiveMsg.ReflectToken(uint8_t Token) {    result_t Result = SUCCESS;    atomic {      if (!(gFlags & FLAGS_TOKENPEND)) {        gFlags |= FLAGS_TOKENPEND;        gTxTokenBuf = Token;      }      else {        Result = FAIL;      }    }    if (Result == SUCCESS) {      Result = StartTx();    }    return Result;  }  async event result_t ByteComm.rxByteReady(uint8_t data, bool error, uint16_t strength) {    switch (gRxState) {    case RXSTATE_NOSYNC:       if ((data == HDLC_FLAG_BYTE) && (gMsgRcvTbl[gRxHeadIndex].Length == 0)) {        gMsgRcvTbl[gRxHeadIndex].Token = 0;	gRxByteCnt = gRxRunningCRC = 0;        gpRxBuf = (uint8_t *)gMsgRcvTbl[gRxHeadIndex].pMsg;    	gRxState = RXSTATE_PROTO;      }      break;    case RXSTATE_PROTO:      if (data == HDLC_FLAG_BYTE) {        break;      }      gMsgRcvTbl[gRxHeadIndex].Proto = data;      gRxRunningCRC = crcByte(gRxRunningCRC,data);      switch (data) {      case PROTO_PACKET_ACK:	gRxState = RXSTATE_TOKEN;	break;      case PROTO_PACKET_NOACK:	gRxState = RXSTATE_INFO;	break;      default:  // PROTO_ACK packets are not handled	gRxState = RXSTATE_NOSYNC;	break;      }      break;    case RXSTATE_TOKEN:      if (data == HDLC_FLAG_BYTE) {        gRxState = RXSTATE_NOSYNC;      }      else if (data == HDLC_CTLESC_BYTE) {        gMsgRcvTbl[gRxHeadIndex].Token = 0x20;      }      else {        gMsgRcvTbl[gRxHeadIndex].Token ^= data;        gRxRunningCRC = crcByte(gRxRunningCRC,gMsgRcvTbl[gRxHeadIndex].Token);        gRxState = RXSTATE_INFO;      }      break;    case RXSTATE_INFO:      if (gRxByteCnt > HDLC_MTU) {	gRxByteCnt = gRxRunningCRC = 0;	gMsgRcvTbl[gRxHeadIndex].Length = 0;	gMsgRcvTbl[gRxHeadIndex].Token = 0;	gRxState = RXSTATE_NOSYNC;      }      else if (data == HDLC_CTLESC_BYTE) {	gRxState = RXSTATE_ESC;      }      else if (data == HDLC_FLAG_BYTE) {	if (gRxByteCnt >= 2) {	  uint16_t usRcvdCRC = (gpRxBuf[(gRxByteCnt-1)] & 0xff);	  usRcvdCRC = (usRcvdCRC << 8) | (gpRxBuf[(gRxByteCnt-2)] & 0xff);	  if (usRcvdCRC == gRxRunningCRC) {	    gMsgRcvTbl[gRxHeadIndex].Length = gRxByteCnt - 2;	    post PacketRcvd();	    gRxHeadIndex++; gRxHeadIndex %= HDLC_QUEUESIZE;          }          else {            gMsgRcvTbl[gRxHeadIndex].Length = 0;            gMsgRcvTbl[gRxHeadIndex].Token = 0;          }          if (gMsgRcvTbl[gRxHeadIndex].Length == 0) {             gpRxBuf = (uint8_t *)gMsgRcvTbl[gRxHeadIndex].pMsg;            gRxState = RXSTATE_PROTO;          }          else {            gRxState = RXSTATE_NOSYNC;	  }	}	else {	  gMsgRcvTbl[gRxHeadIndex].Length = 0;          gMsgRcvTbl[gRxHeadIndex].Token = 0;	  gRxState = RXSTATE_NOSYNC;	}	gRxByteCnt = gRxRunningCRC = 0;      }      else {	gpRxBuf[gRxByteCnt] = data;	if (gRxByteCnt >= 2) {	  gRxRunningCRC = crcByte(gRxRunningCRC,gpRxBuf[(gRxByteCnt-2)]);	}	gRxByteCnt++;      }      break;    case RXSTATE_ESC:      if (data == HDLC_FLAG_BYTE) {	// Error case, fail and resync	gRxByteCnt = gRxRunningCRC = 0;	gMsgRcvTbl[gRxHeadIndex].Length = 0;	gMsgRcvTbl[gRxHeadIndex].Token = 0;	gRxState = RXSTATE_NOSYNC;      }      else {	data = data ^ 0x20;        gpRxBuf[gRxByteCnt] = data;	if (gRxByteCnt >= 2) {	  gRxRunningCRC = crcByte(gRxRunningCRC,gpRxBuf[(gRxByteCnt-2)]);	}	gRxByteCnt++;	gRxState = RXSTATE_INFO;      }      break;    default:      gRxState = RXSTATE_NOSYNC;      break;    }    return SUCCESS;  }  result_t TxArbitraryByte(uint8_t Byte) {    if ((Byte == HDLC_FLAG_BYTE) || (Byte == HDLC_CTLESC_BYTE)) {      atomic {        gPrevTxState = gTxState;        gTxState = TXSTATE_ESC;        gTxEscByte = Byte;      }      Byte = HDLC_CTLESC_BYTE;    }        return call ByteComm.txByte(Byte);  }      async event result_t ByteComm.txByteReady(bool LastByteSuccess) {    result_t TxResult = SUCCESS;    uint8_t nextByte;    if (LastByteSuccess != TRUE) {      atomic gTxState = TXSTATE_ERROR;      post PacketSent();      return SUCCESS;    }    switch (gTxState) {    case TXSTATE_PROTO:      gTxState = TXSTATE_INFO;      gTxRunningCRC = crcByte(gTxRunningCRC,gTxProto);      TxResult = call ByteComm.txByte(gTxProto);      break;          case TXSTATE_INFO:      nextByte = gpTxBuf[gTxByteCnt];            gTxRunningCRC = crcByte(gTxRunningCRC,nextByte);      gTxByteCnt++;      if (gTxByteCnt >= gTxLength) {	gTxState = TXSTATE_FCS1;      }            TxResult = TxArbitraryByte(nextByte);      break;          case TXSTATE_ESC:      TxResult = call ByteComm.txByte((gTxEscByte ^ 0x20));      gTxState = gPrevTxState;      break;	    case TXSTATE_FCS1:      nextByte = (uint8_t)(gTxRunningCRC & 0xff); // LSB      gTxState = TXSTATE_FCS2;      TxResult = TxArbitraryByte(nextByte);      break;    case TXSTATE_FCS2:      nextByte = (uint8_t)((gTxRunningCRC >> 8) & 0xff); // MSB      gTxState = TXSTATE_ENDFLAG;      TxResult = TxArbitraryByte(nextByte);      break;    case TXSTATE_ENDFLAG:      gTxState = TXSTATE_FINISH;      TxResult = call ByteComm.txByte(HDLC_FLAG_BYTE);      break;    case TXSTATE_FINISH:    case TXSTATE_ERROR:    default:      break;    }    if (TxResult != SUCCESS) {      gTxState = TXSTATE_ERROR;      post PacketSent();    }    return SUCCESS;  }  async event result_t ByteComm.txDone() {    if (gTxState == TXSTATE_FINISH) {      gTxState = TXSTATE_IDLE;      post PacketSent();    }        return SUCCESS;  }  default event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr Msg) {    return Msg;  }  default event TOS_MsgPtr TokenReceiveMsg.receive(TOS_MsgPtr Msg,uint8_t Token) {    return Msg;  }}

⌨️ 快捷键说明

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