diff --git a/docs/enhanced_proto.md b/docs/enhanced_proto.md index ee98bc16..3ad225fa 100644 --- a/docs/enhanced_proto.md +++ b/docs/enhanced_proto.md @@ -1,6 +1,7 @@ ## Transfer speed -In order to compensate potential overhead of transfer encoding, the transfer speed is set to 9600 Baud with 8 bits, no parity, and 1 stop bit. +In order to compensate potential overhead of transfer encoding, the transfer speed is set to 9600 Baud or 115200 Baud +with 8 bits, no parity, and 1 stop bit. ## Protocol @@ -103,21 +104,21 @@ These are the predefined symbols as used above. * ERR_OVERRUN 0x01: buffer overrun error ### Feature bits (both directions) - * bit 7-1: tbd - * bit 2: full message sending (complete sequence instead of single bytes) - * bit 1: high speed transfer at 115200 Bd - When requested, the UART speed is changed to 115200 Bd immediately after sending the complete RESETTED reponse. + * bit 7-2: tbd + * // planned: bit 1: full message sending (complete sequence instead of single bytes) * bit 0: additional infos (version, PIC ID, etc.) ### Information IDs (both directions) The first level below is the `info_id` value and the second level describes the response data byte sequence. The first byte transferred in response is always the number of data bytes to be transferred (excluding the length itself). * 0x00: version - * `length`: =5 (2 before 20220220) + * `length`: =8 (2 before 20220220, 5 before 20220831) * `version`: version number * `features`: feature bits * `checksum_H` `checksum_L`: checksum (since 20220220) * `jumpers`: jumper settings + * `bootloader_version`: bootloader version (since 20220831) + * `bootloader_checksum_H` `bootloader_checksum_L`: bootloader checksum * 0x01: PIC ID * `length`: =9 * 9*`mui`: PIC MUI @@ -134,4 +135,7 @@ The first byte transferred in response is always the number of data bytes to be * `length`: =2 * `voltage_max`: maximum bus voltage in 10th volts * `voltage_min`: minimum bus voltage in 10th volts - + * 0x06: reset info (since 20220831) + * `length`: =2 + * `reset_cause`: reset cause (1=power-on, 2=brown-out, 3=watchdog, 4=clear, 5=reset, 6=stack, 7=memory) + * `restart_count`: restart count (within same power cycle) diff --git a/src/lib/ebus/device.cpp b/src/lib/ebus/device.cpp index 5d712042..993976a1 100755 --- a/src/lib/ebus/device.cpp +++ b/src/lib/ebus/device.cpp @@ -80,7 +80,8 @@ Device::Device(const char* name, bool checkDevice, unsigned int latency, bool re bool enhancedProto) : m_name(name), m_checkDevice(checkDevice), m_latency(HOST_LATENCY_MS+(enhancedProto?ENHANCED_LATENCY_MS:0)+latency), m_readOnly(readOnly), - m_initialSend(initialSend), m_enhancedProto(enhancedProto), m_fd(-1), m_listener(nullptr), m_arbitrationMaster(SYN), + m_initialSend(initialSend), m_enhancedProto(enhancedProto), m_fd(-1), m_resetRequested(false), + m_listener(nullptr), m_arbitrationMaster(SYN), m_arbitrationCheck(0), m_bufSize(((MAX_LEN+1+3)/4)*4), m_bufLen(0), m_bufPos(0), m_extraFatures(0), m_infoId(0xff), m_infoLen(0), m_infoPos(0) { m_buffer = reinterpret_cast(malloc(m_bufSize)); @@ -158,6 +159,7 @@ result_t Device::afterOpen() { if (m_listener != nullptr) { m_listener->notifyStatus(false, "resetting"); } + m_resetRequested = true; } else if (m_initialSend && !write(ESC)) { return RESULT_ERR_SEND; } @@ -227,6 +229,10 @@ string Device::getEnhancedInfos() { return "cannot request config"; } } + res = requestEnhancedInfo(6); + if (res != RESULT_OK) { + return "cannot request reset info"; + } res = requestEnhancedInfo(3); if (res != RESULT_OK) { return "cannot request temperature"; @@ -446,7 +452,7 @@ bool Device::available() { symbol_t ch = m_buffer[(pos+m_bufPos)%m_bufSize]; if (!(ch&ENH_BYTE_FLAG)) { #ifdef DEBUG_RAW_TRAFFIC - fprintf(stdout, "raw avail direct\n"); + fprintf(stdout, "raw avail direct @%d+%d %2.2x\n", m_bufPos, pos, ch); fflush(stdout); #endif return true; @@ -459,7 +465,7 @@ bool Device::available() { ch = m_buffer[(pos+m_bufPos+1)%m_bufSize]; if (!(ch&ENH_BYTE_FLAG) || (ch&ENH_BYTE_MASK) != ENH_BYTE2) { #ifdef DEBUG_RAW_TRAFFIC - fprintf(stdout, "raw avail enhanced following bad\n"); + fprintf(stdout, "raw avail enhanced following bad @%d+%d %2.2x %2.2x\n", m_bufPos, pos, m_buffer[(pos+m_bufPos)%m_bufSize], ch); fflush(stdout); #endif if (m_listener != nullptr) { @@ -472,13 +478,13 @@ bool Device::available() { continue; } #ifdef DEBUG_RAW_TRAFFIC - fprintf(stdout, "raw avail enhanced\n"); + fprintf(stdout, "raw avail enhanced @%d+%d %2.2x %2.2x\n", m_bufPos, pos, m_buffer[(pos+m_bufPos)%m_bufSize], ch); fflush(stdout); #endif return true; } #ifdef DEBUG_RAW_TRAFFIC - fprintf(stdout, "raw avail enhanced bad\n"); + fprintf(stdout, "raw avail enhanced bad @%d+%d %2.2x\n", m_bufPos, pos, ch); fflush(stdout); #endif if (m_listener != nullptr) { @@ -508,11 +514,19 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati tail = (m_bufPos+m_bufLen) % m_bufSize; size_t head = m_bufLen-tail; memmove(m_buffer+head, m_buffer, tail); +#ifdef DEBUG_RAW_TRAFFIC + fprintf(stdout, "raw move tail %d @0 to @%d\n", tail, head); + fflush(stdout); +#endif } else { tail = 0; } // move head to first position memmove(m_buffer, m_buffer + m_bufPos, m_bufLen - tail); +#ifdef DEBUG_RAW_TRAFFIC + fprintf(stdout, "raw move head %d @%d to 0\n", m_bufLen - tail, m_bufPos); + fflush(stdout); +#endif } } m_bufPos = 0; @@ -524,7 +538,7 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati #ifdef DEBUG_RAW_TRAFFIC fprintf(stdout, "raw %ld+%ld <", m_bufLen, size); for (int pos=0; pos < size; pos++) { - fprintf(stdout, " %2.2x", m_buffer[m_bufLen+pos]); + fprintf(stdout, " %2.2x", m_buffer[(m_bufLen+pos)%m_bufSize]); } fprintf(stdout, "\n"); fflush(stdout); @@ -612,6 +626,16 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati m_arbitrationMaster = SYN; m_arbitrationCheck = 0; } + m_enhInfoTemperature = ""; + m_enhInfoSupplyVoltage = ""; + m_enhInfoBusVoltage = ""; + m_infoId = 0xff; + if (m_resetRequested) { + m_resetRequested = false; + } else { + close(); // on self-reset of device close and reopen it to have a clean startup + cancelRunningArbitration(arbitrationState); + } m_extraFatures = data; if (m_listener != nullptr) { m_listener->notifyStatus(false, (m_extraFatures&0x01) ? "reset, supports info" : "reset"); @@ -631,12 +655,19 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati switch ((m_infoLen << 8) | m_infoId) { case 0x0200: case 0x0500: // with firmware version and jumper info - stream << "firmware " << static_cast(m_infoBuf[0]) << "." << std::hex - << static_cast(m_infoBuf[1]); - if (m_infoLen>4) { - stream << " [" << std::hex << static_cast(m_infoBuf[2]) - << static_cast(m_infoBuf[3]) << "]"; - stream << ", jumpers 0x" << std::hex << static_cast(m_infoBuf[4]); + case 0x0800: // with firmware version, jumper info, and bootloader version + stream << "firmware " << static_cast(m_infoBuf[0]) << "." // version minor + << std::hex << static_cast(m_infoBuf[1]); // features mask + if (m_infoLen>=5) { + stream << " [" << std::setfill('0') << std::setw(2) << std::hex << static_cast(m_infoBuf[2]) + << std::setw(2) << static_cast(m_infoBuf[3]) << "]"; + stream << ", jumpers 0x" << std::setw(2) << static_cast(m_infoBuf[4]); + stream << std::setfill(' '); // reset + } + if (m_infoLen>=8) { + stream << ", bootloader " << std::dec << static_cast(m_infoBuf[5]); + stream << " [" << std::setfill('0') << std::setw(2) << std::hex << static_cast(m_infoBuf[6]) + << std::setw(2) << static_cast(m_infoBuf[7]) << "]"; } break; case 0x0901: @@ -646,7 +677,7 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati for (uint8_t pos = 0; pos < m_infoPos; pos++) { stream << " " << std::setw(2) << static_cast(m_infoBuf[pos]); } - if (m_infoId == 2 && m_infoBuf[2]!=0x3f) { + if (m_infoId == 2 && (m_infoBuf[2]&0x3f)!=0x3f) { // non-default arbitration delay val = (m_infoBuf[2]&0x3f)*10; // steps of 10us stream << ", arbitration delay " << std::dec << static_cast(val) << " us"; @@ -668,6 +699,25 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati << static_cast(m_infoBuf[0] / 10.0) << " V"; m_enhInfoBusVoltage = stream.str(); break; + case 0x0206: + stream << "reset cause "; + if (m_infoBuf[0]) { + stream << static_cast(m_infoBuf[0]) << "="; + switch (m_infoBuf[0]) { + case 1: stream << "power-on"; break; + case 2: stream << "brown-out"; break; + case 3: stream << "watchdog"; break; + case 4: stream << "clear"; break; + case 5: stream << "reset"; break; + case 6: stream << "stack"; break; + case 7: stream << "memory"; break; + default: stream << "other"; break; + } + stream << ", restart count " << static_cast(m_infoBuf[1]); + } else { + stream << "unknown"; + } + break; default: stream << "unknown 0x" << std::hex << std::setfill('0') << std::setw(2) << static_cast(m_infoId) << ", len " << std::dec << std::setw(0) diff --git a/src/lib/ebus/device.h b/src/lib/ebus/device.h index e77312a3..1cf944aa 100755 --- a/src/lib/ebus/device.h +++ b/src/lib/ebus/device.h @@ -283,6 +283,8 @@ class Device { /** the opened file descriptor, or -1. */ int m_fd; + /** whether the reset of an enhanced device was already requested. */ + bool m_resetRequested; private: /** the @a DeviceListener, or nullptr. */