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