📄 serialp.nc
字号:
/* * 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 + -