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

📄 serialp.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 2 页
字号:
/*									
 *  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.
 * 
 * Revision: $Revision: 1.5 $
 * 
 */

/*
 * 
 * This modules provides framing for TOS_Msgs using PPP-HDLC-like
 * framing (see RFC 1662).  When sending, a TOS_Msg is encapsulated in
 * an HDLC 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.
 *
 * @author Phil Buonadonna
 * @author Lewis Girod
 * @author Ben Greenstein
 * @date   August 7 2005
 */


#include "AM.h"
#include "crc.h"

module SerialP {

  provides {
    interface Init;
    interface SplitControl;
    interface SendBytePacket;
    interface ReceiveBytePacket;
  }

  uses {
    interface SerialFrameComm;
    interface Leds;
    interface StdControl as SerialControl;
    interface SerialFlush;
  }
}
implementation {
#define NO_TX_SEQNO

  enum {
    RX_DATA_BUFFER_SIZE = 2,
    TX_DATA_BUFFER_SIZE = 4,
    SERIAL_MTU = 255,
    SERIAL_VERSION = 1,
    ACK_QUEUE_SIZE = 5,
  };

  enum {
    RXSTATE_NOSYNC,
    RXSTATE_PROTO,
    RXSTATE_TOKEN,
    RXSTATE_INFO,
    RXSTATE_INACTIVE
  };

  enum {
    TXSTATE_IDLE,
    TXSTATE_PROTO,
    TXSTATE_SEQNO,
    TXSTATE_INFO,
    TXSTATE_FCS1,
    TXSTATE_FCS2,
    TXSTATE_ENDFLAG,
    TXSTATE_ENDWAIT,
    TXSTATE_FINISH,
    TXSTATE_ERROR,
    TXSTATE_INACTIVE
  };

  typedef enum {
    BUFFER_AVAILABLE,
    BUFFER_FILLING,
    BUFFER_COMPLETE,
  } tx_data_buffer_states_t;

  enum {
    TX_ACK_INDEX = 0,
    TX_DATA_INDEX = 1,
    TX_BUFFER_COUNT = 2,
  };


  typedef struct {
    uint8_t writePtr;
    uint8_t readPtr;
    uint8_t buf[RX_DATA_BUFFER_SIZE+1]; // one wasted byte: writePtr == readPtr means empty
  } rx_buf_t;

  typedef struct {
    uint8_t state;
    uint8_t buf;    
  } tx_buf_t;
  
  typedef struct {
    uint8_t writePtr;
    uint8_t readPtr;
    uint8_t buf[ACK_QUEUE_SIZE+1]; // one wasted byte: writePtr == readPtr means empty    
  } ack_queue_t;

  /* Buffers */

  rx_buf_t rxBuf;
  tx_buf_t txBuf[TX_BUFFER_COUNT];

  /* Receive State */

  uint8_t  rxState;
  uint8_t  rxByteCnt;
  uint8_t  rxProto;
  uint8_t  rxSeqno;
  uint16_t rxCRC;

  /* Transmit State */

  norace uint8_t  txState;
  norace uint8_t  txByteCnt;
  norace uint8_t  txProto;
  norace uint8_t  txSeqno;
  norace uint16_t txCRC;
  uint8_t  txPending;
  norace uint8_t txIndex;
  
  /* Ack Queue */
  ack_queue_t ackQ;

  bool offPending = FALSE;

  // Prototypes

  inline void txInit();
  inline void rxInit();
  inline void ackInit();

  inline bool ack_queue_is_full(); 
  inline bool ack_queue_is_empty(); 
  inline void ack_queue_push(uint8_t token);
  inline uint8_t ack_queue_top();
  uint8_t ack_queue_pop();

  inline void rx_buffer_init();
  inline bool rx_buffer_is_full();
  inline bool rx_buffer_is_empty();
  inline void rx_buffer_push(uint8_t data);
  inline uint8_t rx_buffer_top();
  inline uint8_t rx_buffer_pop();
  inline uint16_t rx_current_crc();

  void rx_state_machine(bool isDelimeter, uint8_t data);
  void MaybeScheduleTx();
  task void RunTx();
  


  inline void txInit(){
    uint8_t i;
    atomic for (i = 0; i < TX_BUFFER_COUNT; i++) txBuf[i].state = BUFFER_AVAILABLE;
    txState = TXSTATE_IDLE;
    txByteCnt = 0;
    txProto = 0;
    txSeqno = 0;
    txCRC = 0; 
    txPending = FALSE;
    txIndex = 0;
  }

  inline void rxInit(){
    rxBuf.writePtr = rxBuf.readPtr = 0;
    rxState = RXSTATE_NOSYNC;
    rxByteCnt = 0;
    rxProto = 0;
    rxSeqno = 0;
    rxCRC = 0;
  }

  inline void ackInit(){
    ackQ.writePtr = ackQ.readPtr = 0;
  }

  command error_t Init.init() {

    txInit();
    rxInit();
    ackInit();

    return SUCCESS;
  }


  /*
   *  buffer and queue manipulation
   */

  inline bool ack_queue_is_full(){ 
    uint8_t tmp, tmp2;
    atomic {
      tmp = ackQ.writePtr;
      tmp2 = ackQ.readPtr;
    }
    if (++tmp > ACK_QUEUE_SIZE) tmp = 0;
    return (tmp == tmp2);
  }

  inline bool ack_queue_is_empty(){
    bool ret;
    atomic ret = (ackQ.writePtr == ackQ.readPtr); 
    return ret;
  }

  inline void ack_queue_push(uint8_t token) {
    if (!ack_queue_is_full()){
      atomic {
        ackQ.buf[ackQ.writePtr] = token;
        if (++ackQ.writePtr > ACK_QUEUE_SIZE) ackQ.writePtr = 0;
      }
      MaybeScheduleTx();
    }
  }

  inline uint8_t ack_queue_top() {
    uint8_t tmp = 0;
    atomic {
      if (!ack_queue_is_empty()){
        tmp =  ackQ.buf[ackQ.readPtr];
      }
    }
    return tmp;
  }

  uint8_t ack_queue_pop() {
    uint8_t retval = 0;
    atomic {
      if (ackQ.writePtr != ackQ.readPtr){
        retval =  ackQ.buf[ackQ.readPtr];
        if (++(ackQ.readPtr) > ACK_QUEUE_SIZE) ackQ.readPtr = 0;
      }
    }
    return retval;
  }


  /* 
   * Buffer Manipulation
   */

  inline void rx_buffer_init(){
    rxBuf.writePtr = rxBuf.readPtr = 0;
  }
  inline bool rx_buffer_is_full() {
    uint8_t tmp = rxBuf.writePtr;
    if (++tmp > RX_DATA_BUFFER_SIZE) tmp = 0;
    return (tmp == rxBuf.readPtr);
  }
  inline bool rx_buffer_is_empty(){
    return (rxBuf.readPtr == rxBuf.writePtr);
  }
  inline void rx_buffer_push(uint8_t data){
    rxBuf.buf[rxBuf.writePtr] = data;
    if (++(rxBuf.writePtr) > RX_DATA_BUFFER_SIZE) rxBuf.writePtr = 0;
  }
  inline uint8_t rx_buffer_top(){
    uint8_t tmp = rxBuf.buf[rxBuf.readPtr];
    return tmp;
  }
  inline uint8_t rx_buffer_pop(){
    uint8_t tmp = rxBuf.buf[rxBuf.readPtr];
    if (++(rxBuf.readPtr) > RX_DATA_BUFFER_SIZE) rxBuf.readPtr = 0;
    return tmp;
  }
  
  inline uint16_t rx_current_crc(){
    uint16_t crc;
    uint8_t tmp = rxBuf.writePtr;
    tmp = (tmp == 0 ? RX_DATA_BUFFER_SIZE : tmp - 1);
    crc = rxBuf.buf[tmp] & 0x00ff;
    crc = (crc << 8) & 0xFF00;
    tmp = (tmp == 0 ? RX_DATA_BUFFER_SIZE : tmp - 1);
    crc |= (rxBuf.buf[tmp] & 0x00FF);
    return crc;
  }

  task void startDoneTask() {
    call SerialControl.start();
    signal SplitControl.startDone(SUCCESS);
  }


  task void stopDoneTask() {
    call SerialFlush.flush();
  }

  event void SerialFlush.flushDone(){
    call SerialControl.stop();
    signal SplitControl.stopDone(SUCCESS);
  }

  task void defaultSerialFlushTask(){
    signal SerialFlush.flushDone();
  }
  default command void SerialFlush.flush(){
    post defaultSerialFlushTask();
  }

  command error_t SplitControl.start() {
    post startDoneTask();
    return SUCCESS;
  }

  void testOff() {
    bool turnOff = FALSE;
    atomic {
      if (txState == TXSTATE_INACTIVE &&
	  rxState == RXSTATE_INACTIVE) {
	turnOff = TRUE;
      }
    }
    if (turnOff) {
      post stopDoneTask();
      atomic offPending = FALSE;
    }
    else {
      atomic offPending = TRUE;
    }
  }

⌨️ 快捷键说明

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