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

📄 serialp.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 2 页
字号:
    
  command error_t SplitControl.stop() {
    atomic {
      if (rxState == RXSTATE_NOSYNC) {
	rxState = RXSTATE_INACTIVE;
      }
    }
    atomic {
      if (txState == TXSTATE_IDLE) {
	txState = TXSTATE_INACTIVE;
      }
    }
    testOff();
    return SUCCESS;
  }

  /*
   *  Receive Path
   */ 
  
  
  async event void SerialFrameComm.delimiterReceived(){
    rx_state_machine(TRUE,0);
  }
  async event void SerialFrameComm.dataReceived(uint8_t data){
    rx_state_machine(FALSE,data);
  }

  bool valid_rx_proto(uint8_t proto){
    switch (proto){
    case SERIAL_PROTO_PACKET_ACK: 
      return TRUE;
    case SERIAL_PROTO_ACK:
    case SERIAL_PROTO_PACKET_NOACK:
    default: 
      return FALSE;
    }
  }

  void rx_state_machine(bool isDelimeter, uint8_t data){

    switch (rxState) {
      
    case RXSTATE_NOSYNC: 
      if (isDelimeter) {
        rxInit();
        rxState = RXSTATE_PROTO;
      }
      break;
      
    case RXSTATE_PROTO:
      if (!isDelimeter){
        rxCRC = crcByte(rxCRC,data);
        rxState = RXSTATE_TOKEN;
        rxProto = data;
        if (!valid_rx_proto(rxProto))
          goto nosync;
        // only supports serial proto packet ack
        if (rxProto != SERIAL_PROTO_PACKET_ACK){
          goto nosync;
        }
        if (signal ReceiveBytePacket.startPacket() != SUCCESS){
          goto nosync;
        }
      }      
      break;
      
    case RXSTATE_TOKEN:
      if (isDelimeter) {
        goto nosync;
      }
      else {
        rxSeqno = data;
        rxCRC = crcByte(rxCRC,rxSeqno);
        rxState = RXSTATE_INFO;
      }
      break;
      
    case RXSTATE_INFO:
      if (rxByteCnt < SERIAL_MTU){ 
        if (isDelimeter) { /* handle end of frame */
          if (rxByteCnt >= 2) {
            if (rx_current_crc() == rxCRC) {
              signal ReceiveBytePacket.endPacket(SUCCESS);
              ack_queue_push(rxSeqno);
              goto nosync;
            }
            else {
              goto nosync;
            }
          }
          else {
            goto nosync;
          }
	}
        else { /* handle new bytes to save */
          if (rxByteCnt >= 2){ 
            signal ReceiveBytePacket.byteReceived(rx_buffer_top());
            rxCRC = crcByte(rxCRC,rx_buffer_pop());
          }
	  rx_buffer_push(data);
          rxByteCnt++;
        }
      }
      
      /* no valid message.. */
      else {
        goto nosync;
       }
      break;
      
    default:      
      goto nosync;
    }
    goto done;

  nosync:
    /* reset all counters, etc */
    rxInit();
    call SerialFrameComm.resetReceive();
    signal ReceiveBytePacket.endPacket(FAIL);
    if (offPending) {
      rxState = RXSTATE_INACTIVE;
      testOff();
    }
    /* if this was a flag, start in proto state.. */
    else if (isDelimeter) {
      rxState = RXSTATE_PROTO;
    }
    
  done:
  }

  
  /*
   *  Send Path
   */ 


  void MaybeScheduleTx() {
    atomic {
      if (txPending == 0) {
        if (post RunTx() == SUCCESS) {
          txPending = 1;
        }
      }
    }
  }


  async command error_t SendBytePacket.completeSend(){
    bool ret = FAIL;
    atomic {
        txBuf[TX_DATA_INDEX].state = BUFFER_COMPLETE;
        ret = SUCCESS;
    }
    return ret;
  }

  async command error_t SendBytePacket.startSend(uint8_t b){
    bool not_busy = FALSE;
    atomic {
      if (txBuf[TX_DATA_INDEX].state == BUFFER_AVAILABLE){
        txBuf[TX_DATA_INDEX].state = BUFFER_FILLING;
        txBuf[TX_DATA_INDEX].buf = b;
        not_busy = TRUE;
      }
    }
    if (not_busy) {
      MaybeScheduleTx();
      return SUCCESS;
    }
    return EBUSY;

  }
  
  task void RunTx() {
    uint8_t idle;
    uint8_t done;
    uint8_t fail;
    
    /*
      the following trigger MaybeScheduleTx, which starts at most one RunTx:
      1) adding an ack to the ack queue (ack_queue_push())
      2) starting to send a packet (SendBytePacket.startSend())
      3) failure to send start delimiter in RunTx
      4) putDone: 
    */
    
    error_t result = SUCCESS;
    bool send_completed = FALSE;
    bool start_it = FALSE;
    
    atomic { 
      txPending = 0;
      idle = (txState == TXSTATE_IDLE);
      done = (txState == TXSTATE_FINISH);
      fail = (txState == TXSTATE_ERROR);
      if (done || fail){ 
        txState = TXSTATE_IDLE;
        txBuf[txIndex].state = BUFFER_AVAILABLE;
      }
    }
    
    /* if done, call the send done */
    if (done || fail) {
      txSeqno++;
      if (txProto == SERIAL_PROTO_ACK){
        ack_queue_pop();
      }
      else {
        result = done ? SUCCESS : FAIL;
        send_completed = TRUE;
      }
      idle = TRUE;
    }
    
    /* if idle, set up next packet to TX */ 
    if (idle) {
      bool goInactive;
      atomic goInactive = offPending;
      if (goInactive) {
        atomic txState = TXSTATE_INACTIVE;
      }
      else {
        /* acks are top priority */
        uint8_t myAckState;
        uint8_t myDataState;
        atomic {
          myAckState = txBuf[TX_ACK_INDEX].state;
          myDataState = txBuf[TX_DATA_INDEX].state;
        }
        if (!ack_queue_is_empty() && myAckState == BUFFER_AVAILABLE) {
          atomic {
            txBuf[TX_ACK_INDEX].state = BUFFER_COMPLETE;
            txBuf[TX_ACK_INDEX].buf = ack_queue_top();
          }
          txProto = SERIAL_PROTO_ACK;
          txIndex = TX_ACK_INDEX;
          start_it = TRUE;
        }
        else if (myDataState == BUFFER_FILLING || myDataState == BUFFER_COMPLETE){
          txProto = SERIAL_PROTO_PACKET_NOACK;
          txIndex = TX_DATA_INDEX;
          start_it = TRUE;
        }
        else {
          /* nothing to send now.. */
        }
      }
    }
    else {
      /* we're in the middle of transmitting */
    }
    
    if (send_completed){
      signal SendBytePacket.sendCompleted(result);
    }
    
    if (txState == TXSTATE_INACTIVE) {
      testOff();
      return;
    }
    
    if (start_it){
      /* OK, start transmitting ! */
      atomic { 
        txCRC = 0;
        txByteCnt = 0;
        txState = TXSTATE_PROTO; 
      }
      if (call SerialFrameComm.putDelimiter() != SUCCESS) {
        atomic txState = TXSTATE_ERROR; 
        MaybeScheduleTx();
      }
    }
    
  }
  
  async event void SerialFrameComm.putDone() {
    {
      error_t txResult = SUCCESS;
      
      switch (txState) {
        
      case TXSTATE_PROTO:

         txResult = call SerialFrameComm.putData(txProto);
#ifdef NO_TX_SEQNO
        txState = TXSTATE_INFO;
#else
        txState = TXSTATE_SEQNO;
#endif
        txCRC = crcByte(txCRC,txProto);
        break;
        
      case TXSTATE_SEQNO:
        txResult = call SerialFrameComm.putData(txSeqno);
        txState = TXSTATE_INFO;
        txCRC = crcByte(txCRC,txSeqno);
        break;
        
      case TXSTATE_INFO:
        atomic {
          txResult = call SerialFrameComm.putData(txBuf[txIndex].buf);
          txCRC = crcByte(txCRC,txBuf[txIndex].buf);
          ++txByteCnt;
          
          if (txIndex == TX_DATA_INDEX){
            uint8_t nextByte;
            nextByte = signal SendBytePacket.nextByte();
            if (txBuf[txIndex].state == BUFFER_COMPLETE || txByteCnt >= SERIAL_MTU){
              txState = TXSTATE_FCS1;
            }
            else { /* never called on ack b/c ack is BUFFER_COMPLETE initially */
              txBuf[txIndex].buf = nextByte;
            }
          }
          else { // TX_ACK_INDEX
            txState = TXSTATE_FCS1;
          }
        }
        break;
        
      case TXSTATE_FCS1:
        txResult = call SerialFrameComm.putData(txCRC & 0xff);
        txState = TXSTATE_FCS2;
        break;
        
      case TXSTATE_FCS2:
        txResult = call SerialFrameComm.putData((txCRC >> 8) & 0xff);
        txState = TXSTATE_ENDFLAG;
        break;
        
      case TXSTATE_ENDFLAG:
        txResult = call SerialFrameComm.putDelimiter();
        txState = TXSTATE_ENDWAIT;
        break;
        
      case TXSTATE_ENDWAIT:
        txState = TXSTATE_FINISH;
      case TXSTATE_FINISH:
        MaybeScheduleTx();
        break;
      case TXSTATE_ERROR:
      default:
        txResult = FAIL; 
        break;
      }
      
      if (txResult != SUCCESS) {
        txState = TXSTATE_ERROR;
        MaybeScheduleTx();
      }
    }
  }

  
 default event void SplitControl.startDone(error_t err) {}
 default event void SplitControl.stopDone(error_t err) {}
}

⌨️ 快捷键说明

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