diff --git a/tools/src/librlink/RlinkConnect.cpp b/tools/src/librlink/RlinkConnect.cpp index a0932c65..afa170ad 100644 --- a/tools/src/librlink/RlinkConnect.cpp +++ b/tools/src/librlink/RlinkConnect.cpp @@ -1,9 +1,10 @@ -// $Id: RlinkConnect.cpp 1185 2019-07-12 17:29:12Z mueller $ +// $Id: RlinkConnect.cpp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright 2011-2019 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 2.8.6 add Nak handling // 2019-03-10 1121 2.8.5 DecodeResponse(): rblk expect check over BlockDone // 2018-12-22 1091 2.8.4 Open(): (-Wpessimizing-move fix); add BadPort() // 2018-12-19 1090 2.8.3 use RosPrintf(bool) @@ -152,6 +153,7 @@ RlinkConnect::RlinkConnect() fStats.Define(kStatNErrCmd, "NErrCmd", "decode: command mismatch"); fStats.Define(kStatNErrLen, "NErrLen", "decode: length mismatch"); fStats.Define(kStatNErrCrc, "NErrCrc", "decode: crc mismatch"); + fStats.Define(kStatNErrNak, "NErrNak", "decode: nak seen"); } //------------------------------------------+----------------------------------- @@ -874,7 +876,7 @@ int RlinkConnect::DecodeResponse(RlinkCommandList& clist, size_t ibeg, size_t iend) { size_t ncmd = 0; - + for (size_t i=ibeg; i<=iend; i++) { RlinkCommand& cmd = clist[i]; uint8_t ccode = cmd.Command(); @@ -888,7 +890,24 @@ int RlinkConnect::DecodeResponse(RlinkCommandList& clist, size_t ibeg, continue; } - // FIXME_code: handle NAK properly !! + if (fRcvPkt.CheckNak()) { // NAK seen + cmd.SetFlagBit(RlinkCommand::kFlagErrNak); + fStats.Inc(kStatNErrNak); + RlogMsg lmsg(*fspLog, 'E'); + lmsg << "DecodeResponse: NAK seen, code "; + switch (fRcvPkt.NakCode()) { + case RlinkPacketBufRcv::kNcCcrc: lmsg << "Ccrc"; break; + case RlinkPacketBufRcv::kNcDcrc: lmsg << "Dcrc"; break; + case RlinkPacketBufRcv::kNcFrame: lmsg << "Frame"; break; + case RlinkPacketBufRcv::kNcUnused: lmsg << "Unused"; break; + case RlinkPacketBufRcv::kNcCmd: lmsg << "Cmd"; break; + case RlinkPacketBufRcv::kNcCnt: lmsg << "Cnt"; break; + case RlinkPacketBufRcv::kNcRtOvlf: lmsg << "RtOvlf"; break; + case RlinkPacketBufRcv::kNcRtWblk: lmsg << "RtWblk"; break; + case RlinkPacketBufRcv::kNcInval: lmsg << "Inval"; break; + } + return -1; + } if (!fRcvPkt.CheckSize(cmd.RcvSize())) { // not enough data for cmd cmd.SetFlagBit(RlinkCommand::kFlagErrDec); @@ -899,7 +918,7 @@ int RlinkConnect::DecodeResponse(RlinkCommandList& clist, size_t ibeg, } fRcvPkt.GetWithCrc(rdata8); - if (rdata8 != cmd.Request()) { // command mismatch + if (rdata8 != cmd.Request()) { // command mismatch cmd.SetFlagBit(RlinkCommand::kFlagErrDec); fStats.Inc(kStatNErrCmd); RlogMsg lmsg(*fspLog, 'E'); diff --git a/tools/src/librlink/RlinkConnect.hpp b/tools/src/librlink/RlinkConnect.hpp index cb10d659..48940fe4 100644 --- a/tools/src/librlink/RlinkConnect.hpp +++ b/tools/src/librlink/RlinkConnect.hpp @@ -1,9 +1,10 @@ -// $Id: RlinkConnect.hpp 1186 2019-07-12 17:49:59Z mueller $ +// $Id: RlinkConnect.hpp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright 2011-2019 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 2.8.5 add Nak handling // 2019-06-07 1160 2.8.4 *Stats() not longer const // 2018-12-23 1091 2.8.3 add BadPort() // 2018-12-17 1085 2.8.2 use std::recursive_mutex instead of boost @@ -217,6 +218,7 @@ namespace Retro { kStatNErrCmd, //!< decode: command mismatch kStatNErrLen, //!< decode: length mismatch kStatNErrCrc, //!< decode: crc mismatch + kStatNErrNak, //!< decode: nak seen kDimStat }; diff --git a/tools/src/librlink/RlinkPacketBuf.cpp b/tools/src/librlink/RlinkPacketBuf.cpp index 9b601995..dafb6e6c 100644 --- a/tools/src/librlink/RlinkPacketBuf.cpp +++ b/tools/src/librlink/RlinkPacketBuf.cpp @@ -1,9 +1,10 @@ -// $Id: RlinkPacketBuf.cpp 1186 2019-07-12 17:49:59Z mueller $ +// $Id: RlinkPacketBuf.cpp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright 2011-2017 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 2.0.4 add kNc* definitions // 2017-04-07 868 2.0.1 Dump(): add detail arg // 2014-11-23 606 2.0 re-organize for rlink v4 // 2013-04-21 509 1.0.4 add SndAttn() method @@ -60,6 +61,15 @@ const uint8_t RlinkPacketBuf::kEcXoff; const uint8_t RlinkPacketBuf::kEcFill; const uint8_t RlinkPacketBuf::kEcEsc; const uint8_t RlinkPacketBuf::kEcClobber; +const uint8_t RlinkPacketBuf::kNcCcrc; +const uint8_t RlinkPacketBuf::kNcDcrc; +const uint8_t RlinkPacketBuf::kNcFrame; +const uint8_t RlinkPacketBuf::kNcUnused; +const uint8_t RlinkPacketBuf::kNcCmd; +const uint8_t RlinkPacketBuf::kNcCnt; +const uint8_t RlinkPacketBuf::kNcRtOvlf; +const uint8_t RlinkPacketBuf::kNcRtWblk; +const uint8_t RlinkPacketBuf::kNcInval; //------------------------------------------+----------------------------------- //! Default constructor diff --git a/tools/src/librlink/RlinkPacketBuf.hpp b/tools/src/librlink/RlinkPacketBuf.hpp index e81ac378..c4c6a0b9 100644 --- a/tools/src/librlink/RlinkPacketBuf.hpp +++ b/tools/src/librlink/RlinkPacketBuf.hpp @@ -1,9 +1,10 @@ -// $Id: RlinkPacketBuf.hpp 1186 2019-07-12 17:49:59Z mueller $ +// $Id: RlinkPacketBuf.hpp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright 2011-2019 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 2.0.4 add kNc* definitions // 2019-06-07 1160 2.0.3 Stats() not longer const // 2018-12-16 1084 2.0.2 use =delete for noncopyable instead of boost // 2017-04-07 868 2.0.1 Dump(): add detail arg @@ -74,7 +75,16 @@ namespace Retro { static const uint8_t kEcXoff = 0x05; //!< VHDL def ec_xoff 101 static const uint8_t kEcFill = 0x06; //!< VHDL def ec_fill 110 static const uint8_t kEcEsc = 0x07; //!< VHDL def ec_esc 111 - static const uint8_t kEcClobber = 0xff; //!< invalid Ecode + static const uint8_t kEcClobber = 0xff; //!< invalid Ecode + static const uint8_t kNcCcrc = 0x00; //!< VHDL def nak_ccrc 000 + static const uint8_t kNcDcrc = 0x01; //!< VHDL def nak_dcrc 001 + static const uint8_t kNcFrame = 0x02; //!< VHDL def nak_frame 010 + static const uint8_t kNcUnused = 0x03; //!< VHDL def nak_unused 011 + static const uint8_t kNcCmd = 0x04; //!< VHDL def nak_cmd 100 + static const uint8_t kNcCnt = 0x05; //!< VHDL def nak_cnt 101 + static const uint8_t kNcRtOvlf = 0x06; //!< VHDL def nak_rtovfl 110 + static const uint8_t kNcRtWblk = 0x07; //!< VHDL def nak_rtwblk 111 + static const uint8_t kNcInval = 0x08; //!< invalid NAK protected: void SetFlagBit(uint32_t mask); diff --git a/tools/src/librlink/RlinkPacketBufRcv.cpp b/tools/src/librlink/RlinkPacketBufRcv.cpp index ed7e24a4..5f9cf4e4 100644 --- a/tools/src/librlink/RlinkPacketBufRcv.cpp +++ b/tools/src/librlink/RlinkPacketBufRcv.cpp @@ -1,9 +1,10 @@ -// $Id: RlinkPacketBufRcv.cpp 1186 2019-07-12 17:49:59Z mueller $ +// $Id: RlinkPacketBufRcv.cpp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright 2014-2019 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 1.2.3 add Nak handling // 2019-06-14 1163 1.2.2 ReadData(): coverity fixup (logically dead code) // 2018-12-23 1091 1.2.1 ReadData(): remove port open check, done at caller // 2018-12-08 1079 1.2 use ref not ptr for RlinkPort @@ -20,6 +21,8 @@ #include +#include + #include "RlinkPacketBufRcv.hpp" #include "librtools/RosFill.hpp" @@ -47,17 +50,27 @@ RlinkPacketBufRcv::RlinkPacketBufRcv() fNDone(0), fEscSeen(false), fNakIndex(-1), + fNakCode(0), fDropData() { // Statistic setup - fStats.Define(kStatNRxPktByt, "NRxPktByt", "Rx packet bytes rcvd"); - fStats.Define(kStatNRxDrop, "NRxDrop", "Rx bytes dropped"); - fStats.Define(kStatNRxSop, "NRxSop", "Rx SOP commas seen"); - fStats.Define(kStatNRxEop, "NRxEop", "Rx EOP commas seen"); - fStats.Define(kStatNRxNak, "NRxNak", "Rx NAK commas seen"); - fStats.Define(kStatNRxAttn, "NRxAttn", "Rx ATTN commas seen"); - fStats.Define(kStatNRxEsc, "NRxEsc", "Rx data escapes"); - fStats.Define(kStatNRxClobber,"NRxClobber","Rx clobbered escapes"); + fStats.Define(kStatNRxPktByt, "NRxPktByt", "Rx packet bytes rcvd"); + fStats.Define(kStatNRxDrop, "NRxDrop", "Rx bytes dropped"); + fStats.Define(kStatNRxSop, "NRxSop", "Rx SOP commas seen"); + fStats.Define(kStatNRxEop, "NRxEop", "Rx EOP commas seen"); + fStats.Define(kStatNRxNak, "NRxNak", "Rx NAK commas seen"); + fStats.Define(kStatNRxAttn, "NRxAttn", "Rx ATTN commas seen"); + fStats.Define(kStatNRxEsc, "NRxEsc", "Rx data escapes"); + fStats.Define(kStatNRxClobber, "NRxClobber", "Rx clobbered escapes"); + fStats.Define(kStatNRxNakCcrc, "NRxNakCcrc", "Rx NAK Ccrc seen"); + fStats.Define(kStatNRxNakDcrc, "NRxNakDcrc", "Rx NAK Dcrc seen"); + fStats.Define(kStatNRxNakFrame, "NRxNakFrame", "Rx NAK Frame seen"); + fStats.Define(kStatNRxNakUnused, "NRxNakUnused", "Rx NAK Unused seen"); + fStats.Define(kStatNRxNakCmd, "NRxNakCmd", "Rx NAK Cmd seen"); + fStats.Define(kStatNRxNakCnt, "NRxNakCnt", "Rx NAK Cnt seen"); + fStats.Define(kStatNRxNakRtOvlf, "NRxNakRtOvlf", "Rx NAK RtOvlf seen"); + fStats.Define(kStatNRxNakRtWblk, "NRxNakRtWblk", "Rx NAK RtWblk seen"); + fStats.Define(kStatNRxNakInval, "NRxNakInval", "Rx NAK invalid seen"); } //------------------------------------------+----------------------------------- @@ -134,6 +147,7 @@ void RlinkPacketBufRcv::AcceptPacket() fRcvState = kRcvIdle; fNDone = 0; fNakIndex = -1; + fNakCode = 0; fDropData.clear(); return; } @@ -158,7 +172,7 @@ RlinkPacketBufRcv::pkt_state RlinkPacketBufRcv::PacketState() if (fRcvState==kRcvDone) return TestFlag(kFlagSopSeen) ? kPktResp : kPktAttn; return kPktError; } - + //------------------------------------------+----------------------------------- //! FIXME_docs @@ -187,6 +201,7 @@ void RlinkPacketBufRcv::Dump(std::ostream& os, int ind, const char* text, os << bl << " fNDone: " << RosPrintf(fNDone,"d",4) << endl; os << bl << " fEscSeen: " << RosPrintf(fEscSeen) << endl; os << bl << " fNakIndex: " << RosPrintf(fNakIndex,"d",4) << endl; + os << bl << " fNakCode: " << RosPrintf(fNakCode,"d",4) << endl; os << bl << " fDropData.size:" << RosPrintf(fDropData.size(),"d",4); size_t ncol = max(1, (80-ind-4-6)/(2+1)); @@ -276,8 +291,30 @@ void RlinkPacketBufRcv::ProcessDataFill() fRcvState = kRcvError; return; } // else 1st NAK + SetFlagBit(kFlagNakSeen); // -> set flag and index; continue fNakIndex = fPktBuf.size(); + if (fRawBufDone+1 < fRawBufSize) { + uint8_t nc = fRawBuf[fRawBufDone]; + uint8_t ncpre = nc & 0xc0; + uint8_t ncneg = ((~nc)>>3) & 0x07; + uint8_t ncpos = nc & 0x07; + fNakCode = (ncpre == 0x80 && ncneg == ncpos) ? ncpos : kNcInval; + } else { + fNakCode = kNcInval; + } + switch (fNakCode) { + case kNcCcrc: fStats.Inc(kStatNRxNakCcrc); break; // NAK Ccrc seen + case kNcDcrc: fStats.Inc(kStatNRxNakDcrc); break; // NAK Dcrc seen + case kNcFrame: fStats.Inc(kStatNRxNakFrame); break; // NAK Frame seen + case kNcUnused: fStats.Inc(kStatNRxNakUnused); break; // NAK Unused seen + case kNcCmd: fStats.Inc(kStatNRxNakCmd); break; // NAK Cmd seen + case kNcCnt: fStats.Inc(kStatNRxNakCnt); break; // NAK Cnt seen + case kNcRtOvlf: fStats.Inc(kStatNRxNakRtOvlf); break; // NAK RtOvlf seen + case kNcRtWblk: fStats.Inc(kStatNRxNakRtWblk); break; // NAK RtWblk seen + case kNcInval: fStats.Inc(kStatNRxNakInval); break; // NAK invalid seen + } + break; // data escapes seen: add escaped char and continue diff --git a/tools/src/librlink/RlinkPacketBufRcv.hpp b/tools/src/librlink/RlinkPacketBufRcv.hpp index 0bdd1985..1be1c8cc 100644 --- a/tools/src/librlink/RlinkPacketBufRcv.hpp +++ b/tools/src/librlink/RlinkPacketBufRcv.hpp @@ -1,9 +1,10 @@ -// $Id: RlinkPacketBufRcv.hpp 1186 2019-07-12 17:49:59Z mueller $ +// $Id: RlinkPacketBufRcv.hpp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later -// Copyright 2014-2018 by Walter F.J. Mueller +// Copyright 2014-2019 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 1.2.1 add Nak handling // 2018-12-08 1079 1.2 use ref not ptr for RlinkPort // 2017-04-07 868 1.1.1 Dump(): add detail arg // 2017-02-19 853 1.1 use Rtime @@ -41,10 +42,11 @@ namespace Retro { kPktPend=0, //!< pending, still being filled kPktResp, //!< response packet (SOP+EOP) kPktAttn, //!< attn notify packet (ATTN+EOP) - kPktError //!< errorous packet + kPktError //!< erroneous packet }; pkt_state PacketState(); + bool CheckNak() const; bool CheckSize(size_t nbyte) const; void GetWithCrc(uint8_t& data); void GetWithCrc(uint16_t& data); @@ -52,6 +54,7 @@ namespace Retro { bool CheckCrc(); int NakIndex() const; + uint8_t NakCode() const; void Dump(std::ostream& os, int ind=0, const char* text=0, int detail=0) const; @@ -65,7 +68,16 @@ namespace Retro { kStatNRxNak, //!< Rx NAK commas seen kStatNRxAttn, //!< Rx ATTN commas seen kStatNRxEsc, //!< Rx data escapes - kStatNRxClobber //!< Rx clobbered escapes + kStatNRxClobber, //!< Rx clobbered escapes + kStatNRxNakCcrc, //!< Rx NAK Ccrc seen + kStatNRxNakDcrc, //!< Rx NAK Dcrc seen + kStatNRxNakFrame, //!< Rx NAK Frame seen + kStatNRxNakUnused, //!< Rx NAK Unused seen + kStatNRxNakCmd, //!< Rx NAK Cmd seen + kStatNRxNakCnt, //!< Rx NAK Cnt seen + kStatNRxNakRtOvlf, //!< Rx NAK RtOvlf seen + kStatNRxNakRtWblk, //!< Rx NAK RtWblk seen + kStatNRxNakInval //!< Rx NAK invalid seen }; protected: @@ -88,6 +100,7 @@ namespace Retro { size_t fNDone; //!< number of pkt bytes processed bool fEscSeen; //!< last char was Escape int fNakIndex; //!< index of active nak (-1 if no) + uint8_t fNakCode; //!< code of active nak std::vector fDropData; //!< dropped data buffer }; diff --git a/tools/src/librlink/RlinkPacketBufRcv.ipp b/tools/src/librlink/RlinkPacketBufRcv.ipp index 8e5feb50..cc09ffee 100644 --- a/tools/src/librlink/RlinkPacketBufRcv.ipp +++ b/tools/src/librlink/RlinkPacketBufRcv.ipp @@ -1,9 +1,10 @@ -// $Id: RlinkPacketBufRcv.ipp 1186 2019-07-12 17:49:59Z mueller $ +// $Id: RlinkPacketBufRcv.ipp 1198 2019-07-27 19:08:31Z mueller $ // SPDX-License-Identifier: GPL-3.0-or-later -// Copyright 2014- by Walter F.J. Mueller +// Copyright 2014-2019 by Walter F.J. Mueller // // Revision History: // Date Rev Version Comment +// 2019-07-27 1198 1.0.1 add Nak handling // 2014-11-23 606 1.0 Initial version // 2014-11-02 600 0.1 First draft (re-organize PacketBuf for rlink v4) // --------------------------------------------------------------------------- @@ -18,6 +19,14 @@ namespace Retro { //------------------------------------------+----------------------------------- //! FIXME_docs +inline bool RlinkPacketBufRcv::CheckNak() const +{ + return fNakIndex >= 0 && int(fNDone) == fNakIndex; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + inline bool RlinkPacketBufRcv::CheckSize(size_t nbyte) const { return fPktBuf.size()-fNDone >= nbyte; @@ -63,4 +72,12 @@ inline int RlinkPacketBufRcv::NakIndex() const return fNakIndex; } +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline uint8_t RlinkPacketBufRcv::NakCode() const +{ + return fNakCode; +} + } // end namespace Retro