diff --git a/src/common/crc.c b/src/common/crc.c index 73503633b..70625ce89 100644 --- a/src/common/crc.c +++ b/src/common/crc.c @@ -161,7 +161,6 @@ crcInit(void) int dividend; unsigned char bit; - /* * Compute the remainder of each possible dividend. */ diff --git a/src/vscp/common/vscp-bootdevice-pic1.cpp b/src/vscp/common/vscp-bootdevice-pic1.cpp index 909347b88..ecfdcc63f 100644 --- a/src/vscp/common/vscp-bootdevice-pic1.cpp +++ b/src/vscp/common/vscp-bootdevice-pic1.cpp @@ -40,9 +40,9 @@ // #include #include -#include #include -#include +#include +#include /////////////////////////////////////////////////////////////////////////////// // Constructor @@ -228,16 +228,13 @@ CBootDevice_PIC1::deviceInfo(void) // int -CBootDevice_PIC1::deviceInit(cguid &ourguid, uint16_t devicecode, bool bAbortOnFirmwareCodeFail) +CBootDevice_PIC1::deviceInit(cguid& ourguid, uint16_t devicecode, bool bAbortOnFirmwareCodeFail) { int rv; // Save our local GUID m_ourguid = ourguid; - // Save Firmware device code - m_firmwaredeviceCode = devicecode; - /* First do a test to see if the device is already in boot mode if it is 0x14nn/0x15nn should be returned (nn == nodeid). @@ -359,7 +356,7 @@ CBootDevice_PIC1::deviceInit(cguid &ourguid, uint16_t devicecode, bool bAbortOnF // Set device in boot mode cguid guid; m_stdRegs.getGUID(guid); - msg.data[0] = (uint8_t) m_nodeid; // Nickname to read register from + msg.data[0] = (uint8_t)m_nodeid; // Nickname to read register from msg.data[1] = VSCP_BOOTLOADER_PIC1; // VSCP PIC1 bootloader algorithm msg.data[2] = guid.getAt(0); msg.data[3] = guid.getAt(3); @@ -566,7 +563,7 @@ int CBootDevice_PIC1::writeDeviceControlRegs(uint32_t addr, uint8_t flags, uint8_t cmd, uint8_t cmdData0, uint8_t cmdData1) { int rv; - // vscpEventEx event; + //vscpEventEx event; canalMsg msg; // Save the internal addresss @@ -640,7 +637,7 @@ CBootDevice_PIC1::checkResponseLevel1(uint32_t response_id) // Response received from all - return success spdlog::debug("checkResponseLevel1: RECEIVE OK"); if (nullptr != m_statusCallback) { - // m_statusCallback(-1, "checkResponseLevel1: Response received OK."); + //m_statusCallback(-1, "checkResponseLevel1: Response received OK."); } return VSCP_ERROR_SUCCESS; } @@ -688,7 +685,7 @@ CBootDevice_PIC1::checkResponseLevel2(uint32_t id) // Response received - return success spdlog::debug("checkResponseLevel2: RECEIVE OK"); if (nullptr != m_statusCallback) { - // m_statusCallback(-1, "checkResponseLevel2: Response received OK."); + //m_statusCallback(-1, "checkResponseLevel2: Response received OK."); } return VSCP_ERROR_SUCCESS; } @@ -831,7 +828,7 @@ CBootDevice_PIC1::writeFirmwareBlock(uint32_t start, uint32_t end) } // Init the block - if (VSCP_ERROR_SUCCESS != (rv = fillMemoryBuffer(pbuf, size, start))) { + if (VSCP_ERROR_SUCCESS != (rv = fillMemoryBuffer(pbuf, size, start, end))) { spdlog::error("writeFirmwareBlock: Failed to fill code block with data."); if (nullptr != m_statusCallback) { m_statusCallback(-1, @@ -855,7 +852,7 @@ CBootDevice_PIC1::writeFirmwareBlock(uint32_t start, uint32_t end) } // Start at beginning - paddr += minAddr - start; + paddr += minAddr-start; for (uint32_t blk = 0; blk < nPackets; blk++) { spdlog::debug("Loading flash on remote device... block={0} {1:X}", blk, blk * 8); @@ -865,11 +862,11 @@ CBootDevice_PIC1::writeFirmwareBlock(uint32_t start, uint32_t end) } paddr += 8; if (nullptr != m_statusCallback) { - m_statusCallback((100 * blk) / nPackets, "" /*vscp_str_format("blk %d.", blk).c_str()*/); + m_statusCallback((100 * blk) / nPackets, ""/*vscp_str_format("blk %d.", blk).c_str()*/); } } // for - } // code + } // code delete[] pbuf; return VSCP_ERROR_SUCCESS; @@ -882,18 +879,18 @@ CBootDevice_PIC1::writeFirmwareBlock(uint32_t start, uint32_t end) int CBootDevice_PIC1::deviceLoad(std::function statusCallback, bool bAbortOnFirmwareCodeFail) { - // bool bRun = true; + //bool bRun = true; int rv; - m_checksum = 0; - // uint32_t progress = 0; + m_checksum = 0; + //uint32_t progress = 0; uint32_t addr = 0; std::string strStatus; - // uint8_t pbuf[BUFFER_SIZE_CODE]; - // uint32_t nPackets; - // uint32_t minAddr; - // uint32_t maxAddr; + //uint8_t pbuf[BUFFER_SIZE_CODE]; + //uint32_t nPackets; + // uint32_t minAddr; + // uint32_t maxAddr; if (nullptr != m_statusCallback) { m_statusCallback(0, "Starting firmware download"); diff --git a/src/vscp/common/vscp-bootdevice-vscp.cpp b/src/vscp/common/vscp-bootdevice-vscp.cpp index f4b7adb88..4f5896219 100644 --- a/src/vscp/common/vscp-bootdevice-vscp.cpp +++ b/src/vscp/common/vscp-bootdevice-vscp.cpp @@ -35,7 +35,7 @@ #include -#define CRC16 +#define CRC_CCITT #include #include @@ -47,6 +47,11 @@ #include #include +/////////////////////////////////////////////////////////////////////////////// +// CTORS +// + +// Level I CBootDevice_VSCP::CBootDevice_VSCP(CVscpClient *pclient, uint8_t nodeid, std::function statusCallback, @@ -57,6 +62,7 @@ CBootDevice_VSCP::CBootDevice_VSCP(CVscpClient *pclient, init(); } +// Level I over interface CBootDevice_VSCP::CBootDevice_VSCP(CVscpClient *pclient, uint8_t nodeid, cguid &guidif, @@ -68,6 +74,7 @@ CBootDevice_VSCP::CBootDevice_VSCP(CVscpClient *pclient, init(); } +// Level II CBootDevice_VSCP::CBootDevice_VSCP(CVscpClient *pclient, cguid &guid, std::function statusCallback, @@ -216,12 +223,6 @@ CBootDevice_VSCP::deviceInit(cguid &ourguid, uint16_t devicecode, bool bAbortOnF int rv; vscpEventEx ex; - // Save our local GUID - m_ourguid = ourguid; - - // Save Firmware device code - m_firmwaredeviceCode = devicecode; - // Read standard registers if (VSCP_ERROR_SUCCESS != m_stdRegs.init(*m_pclient, m_guid, m_guidif, nullptr, REGISTER_DEFAULT_TIMEOUT)) { spdlog::error("VSCP bootloader: Failed to read standard registers"); @@ -245,16 +246,17 @@ CBootDevice_VSCP::deviceInit(cguid &ourguid, uint16_t devicecode, bool bAbortOnF Must be the same as the firmware we try to load is intended for */ if (m_firmwaredeviceCode != m_stdRegs.getFirmwareDeviceCode()) { - spdlog::warn("Firmware device code is not equal! Firmware: {0} Device: {1}", + spdlog::warn("Firmware device code is not equal! Firmware: {0} Device: {1} (disable requirement in configuration)", m_firmwaredeviceCode, m_stdRegs.getFirmwareDeviceCode()); if (nullptr != m_statusCallback) { - m_statusCallback(-1, - vscp_str_format( - "Firmware device code is not equal! Firmware: {0} Device: {1}", - m_firmwaredeviceCode, - m_stdRegs.getFirmwareDeviceCode()) - .c_str()); + m_statusCallback( + -1, + vscp_str_format( + "Firmware device code is not equal! Firmware: {0} Device: {1} (disable requirement in configuration)", + m_firmwaredeviceCode, + m_stdRegs.getFirmwareDeviceCode()) + .c_str()); } if (bAbortOnFirmwareCodeFail) { return VSCP_ERROR_PARAMETER; @@ -298,7 +300,7 @@ CBootDevice_VSCP::deviceInit(cguid &ourguid, uint16_t devicecode, bool bAbortOnF return rv; } - // OK now in bootmode - return + // OK now in bootmode - return if valid block data m_blockSize = construct_unsigned32(ex.data[0], ex.data[1], ex.data[2], ex.data[3]); m_numBlocks = construct_unsigned32(ex.data[4], ex.data[5], ex.data[6], ex.data[7]); spdlog::debug("VSCP bootloader: Confirmed, device is in boot mood."); @@ -340,12 +342,13 @@ CBootDevice_VSCP::writeBlockStart(uint32_t block, uint8_t type) cguid node_guid; m_stdRegs.getGUID(node_guid); - ex.sizeData = 8; + ex.sizeData = 6; ex.data[0] = (block >> 24) & 0xff; ex.data[1] = (block >> 16) & 0xff; ex.data[2] = (block >> 8) & 0xff; ex.data[3] = block & 0xff; ex.data[4] = type; + ex.data[5] = 0; if (VSCP_ERROR_SUCCESS != (rv = m_pclient->send(ex))) { spdlog::error("VSCP bootloader: Failed to send start block transfer event {0}", rv); @@ -355,16 +358,20 @@ CBootDevice_VSCP::writeBlockStart(uint32_t block, uint8_t type) return rv; } + + // Wait for response on start block transfer event if (VSCP_ERROR_SUCCESS != (rv = checkResponse(ex, node_guid, VSCP_TYPE_PROTOCOL_START_BLOCK_ACK, VSCP_TYPE_PROTOCOL_START_BLOCK_NACK))) { spdlog::error("VSCP bootloader: Negative response from block start request {0}", rv); if (nullptr != m_statusCallback) { - m_statusCallback(-1, "VSCP bootloader: Negative response from block start request"); + m_statusCallback(-1, + vscp_str_format("VSCP bootloader: Negative response from block start request %d", rv).c_str()); } return rv; } + return VSCP_ERROR_SUCCESS; } @@ -386,7 +393,7 @@ CBootDevice_VSCP::programBlock(uint32_t block) cguid node_guid; m_stdRegs.getGUID(node_guid); - ex.sizeData = 8; + ex.sizeData = 4; ex.data[0] = (block >> 24) & 0xff; ex.data[1] = (block >> 16) & 0xff; ex.data[2] = (block >> 8) & 0xff; @@ -400,14 +407,14 @@ CBootDevice_VSCP::programBlock(uint32_t block) return rv; } - // Wait for response on start block transfer event + // Wait for response on program block data if (VSCP_ERROR_SUCCESS != (rv = checkResponse(ex, node_guid, VSCP_TYPE_PROTOCOL_PROGRAM_BLOCK_DATA_ACK, VSCP_TYPE_PROTOCOL_PROGRAM_BLOCK_DATA_NACK))) { - spdlog::error("VSCP bootloader: Negative response from block start request {0}", rv); + spdlog::error("VSCP bootloader: Negative response from ProgramBlock. {0}", rv); if (nullptr != m_statusCallback) { - m_statusCallback(-1, "VSCP bootloader: Negative response from block start request"); + m_statusCallback(-1, vscp_str_format("VSCP bootloader: Negative response from ProgramBlock. %d", rv).c_str()); } return rv; } @@ -452,10 +459,10 @@ CBootDevice_VSCP::writeChunk(const uint8_t *paddr, uint16_t size) // Wait for response on start block transfer event if (VSCP_ERROR_SUCCESS != - (rv = checkResponse(ex, node_guid, VSCP_TYPE_PROTOCOL_START_BLOCK_ACK, VSCP_TYPE_PROTOCOL_START_BLOCK_NACK))) { - spdlog::error("VSCP bootloader: Negative response from block start request {0}", rv); + (rv = checkResponse(ex, node_guid, VSCP_TYPE_PROTOCOL_BLOCK_CHUNK_ACK, VSCP_TYPE_PROTOCOL_BLOCK_CHUNK_NACK))) { + spdlog::error("VSCP bootloader: Negative response from block chunk send {0}", rv); if (nullptr != m_statusCallback) { - m_statusCallback(-1, "VSCP bootloader: Negative response from block start request"); + m_statusCallback(-1, vscp_str_format("VSCP bootloader: Negative response from block chunk send", rv).c_str()); } return rv; } @@ -470,10 +477,13 @@ CBootDevice_VSCP::writeChunk(const uint8_t *paddr, uint16_t size) int CBootDevice_VSCP::writeBlock(const uint8_t *paddr) { - int rv; - // vscpEventEx ex; + int rv = VSCP_ERROR_SUCCESS; cguid guid; - uint32_t nChunks; + uint32_t nChunks = 1; + vscpEventEx ex; + + cguid node_guid; + m_stdRegs.getGUID(node_guid); if (m_blockSize > m_chunkSize) { nChunks = m_blockSize / m_chunkSize; @@ -482,34 +492,61 @@ CBootDevice_VSCP::writeBlock(const uint8_t *paddr) nChunks++; } } - else { - // There is just one chunk - // We have taken care of chunk > block in init - nChunks = 1; - } for (uint32_t chunk = 0; chunk < nChunks; chunk++) { - spdlog::debug("Loading memory chunk on remote device. chunk={0} {1:X} ", chunk, chunk * m_chunkSize); + spdlog::debug("VSCP bootloader: memory chunk on remote device. chunk={0} {1:X} ", chunk, chunk * m_chunkSize); if (nullptr != m_statusCallback) { - m_statusCallback((100 * chunk) / nChunks, - vscp_str_format("Loading memory chunk on remote device. chunk = %d.", chunk).c_str()); + m_statusCallback( + -1 /*(100 * chunk) / nChunks*/, + // vscp_str_format("VSCP bootloader: Loading memory chunk on remote device. chunk = %d.", chunk).c_str() + ""); } - if (VSCP_ERROR_SUCCESS != writeChunk(paddr + (m_chunkSize * nChunks), m_chunkSize)) { - spdlog::error("Failed to write chunk to remote device. rv={}", rv); + if (VSCP_ERROR_SUCCESS != (rv = writeChunk(paddr + (chunk * m_chunkSize), m_chunkSize))) { + spdlog::error("VSCP bootloader: Failed to write chunk to remote device. rv={}", rv); if (nullptr != m_statusCallback) { - m_statusCallback((100 * chunk) / nChunks, - vscp_str_format("Failed to write chunk to remote device rv=%d.", rv).c_str()); + m_statusCallback( + (100 * chunk) / nChunks, + vscp_str_format("VSCP bootloader: Failed to write chunk %lu/%lu to remote device rv=%d.", chunk, nChunks, rv) + .c_str()); + spdlog::error("VSCP bootloader: Failed to write chunk {0}/{1} to remote device rv={2}.", chunk, nChunks, rv); } break; } - paddr += m_chunkSize; + //paddr += m_chunkSize; } // for - return VSCP_ERROR_SUCCESS; + // Wait for data block ACK/NACK response + if (VSCP_ERROR_SUCCESS != + (rv = checkResponse(ex, node_guid, VSCP_TYPE_PROTOCOL_BLOCK_DATA_ACK, VSCP_TYPE_PROTOCOL_BLOCK_DATA_NACK))) { + spdlog::error("VSCP bootloader: NACK received for data block {0}", rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "VSCP bootloader: NACK received for data block"); + } + } + + // Check that the crc is equal + uint16_t crc_block = crcFast(paddr, m_blockSize); + uint16_t crc_packet = construct_unsigned16(ex.data[0], ex.data[1]); + uint32_t block_packet = construct_unsigned32(ex.data[2], ex.data[3], ex.data[4], ex.data[5]); + + if (crc_packet != crc_block) { + spdlog::error("VSCP bootloader: CRC error for block. CRC Packet={0:0X} CRC_Block={1:0X}", crc_packet, crc_block); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: CRC error for block CRC Packet=%04X CRC_Block=%04X", crc_packet, crc_block) + .c_str()); + } + return VSCP_ERROR_INVALID_FRAME; // TODO: Change to CRC error + } + + // We have a valid block + + return rv; } /////////////////////////////////////////////////////////////////////////////// @@ -519,11 +556,7 @@ CBootDevice_VSCP::writeBlock(const uint8_t *paddr) int CBootDevice_VSCP::deviceLoad(std::function statusCallback, bool bAbortOnFirmwareCodeFail) { - int rv; - // vscpEventEx ex; - - // uint32_t progress = 0; - // uint32_t addr; + int rv = VSCP_ERROR_SUCCESS; std::string strStatus; m_checksum = 0; @@ -536,115 +569,226 @@ CBootDevice_VSCP::deviceLoad(std::function statusCallba m_checksum = 0; // Iterate over memory types - for (int pos = 0; pos < NUMBER_OF_MEMORY_TYPES; pos++) { + for (int memtype = 0; memtype < NUMBER_OF_MEMORY_TYPES; memtype++) { - spdlog::error("writeFirmwareBlock: Handling memory range {0}", memory_range[pos].type); + spdlog::debug("VSCP bootloader: Memory type {0}", m_memory_range[memtype].type); if (nullptr != m_statusCallback) { - m_statusCallback(-1, - vscp_str_format("writeFirmwareBlock: Handling memory range %d", memory_range[pos].type).c_str()); + m_statusCallback(-1, vscp_str_format("VSCP bootloader: Memory type %d", m_memory_range[memtype].type).c_str()); } uint32_t minAddr; uint32_t maxAddr; - // Fetch min and max address for selected memory range + // Fetch min and max address for selected memory type if (VSCP_ERROR_SUCCESS != - (rv = getMinMaxForRange(memory_range[pos].beginning, memory_range[pos].end, &minAddr, &maxAddr))) { - spdlog::error("writeFirmwareBlock: Failed to get min max range for block {0:X}-{1:X} rv=%d", - minAddr, - maxAddr, - rv); + (rv = getMinMaxForRange(m_memory_range[memtype].start, m_memory_range[memtype].end, &minAddr, &maxAddr))) { + spdlog::error("VSCP bootloader: Failed to get min max range for memory type {0} rv={1}", memtype, rv); if (nullptr != m_statusCallback) { m_statusCallback( -1, - vscp_str_format("writeFirmwareBlock: Failed to get min max range for block. rv=%d", rv).c_str()); + vscp_str_format("VSCP bootloader: Failed to get min max range for memory type %d. rv=%d", memtype, rv) + .c_str()); } - return rv; + continue; } - // If there is a memory range to work with - if (maxAddr > minAddr) { + // Check if there is any data to write + if (maxAddr <= minAddr) { + spdlog::error("VSCP bootloader: No data to write for memory type {0} block {1:X}-{2:X}.", + memtype, + m_memory_range[memtype].start, + m_memory_range[memtype].end); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, + vscp_str_format("VSCP bootloader: No data to write for memory type %d block %X-%X.", + memtype, + m_memory_range[memtype].start, + m_memory_range[memtype].end) + .c_str()); + } + continue; + } + + /* + The block where the first bytes of the image is located. + */ + uint32_t startBlock = minAddr / m_blockSize; + spdlog::debug("VSCP bootloader: Startblock {0}.", startBlock); - /*! - The number of blocks to transfer count from the first byte to the - last byte. The lowest address may need to be adjusted to a block - boundary. There is no ned to do this for the upper address - */ - minAddr -= (minAddr % m_blockSize); // Adjust to block boundary + /* + The number of blocks to transfer count from the first byte to the + last byte. The lowest address may need to be adjusted to a block + boundary. There is no need to do this for the upper address + */ + uint32_t nBlocks = (maxAddr - minAddr) / m_blockSize; - uint32_t nBlocks = (maxAddr - minAddr) / m_blockSize; - // A not completely full packet also count - if (0 != ((maxAddr - minAddr) % m_blockSize)) { - nBlocks++; + // A not completely full packet also count + if (0 != ((maxAddr - minAddr) % m_blockSize)) { + nBlocks++; + } + + spdlog::debug("VSCP bootloader: Number of blocks {0}.", nBlocks); + + /* + Allocate buffer memory for the block + Some notes to remember (and handle): + - Blocksize can be less than data size (ChunkSize) for a frame (8/512) + */ + uint8_t *pbuf = new uint8_t[m_blockSize * nBlocks]; + if (nullptr == pbuf) { + spdlog::error("VSCP bootloader: Failed to allocate memory for block {0:X}-{1:X}.", minAddr, maxAddr); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: Failed to allocate memory for block {0:X}-{1:X}.", minAddr, maxAddr) + .c_str()); } + return VSCP_ERROR_MEMORY; + } - uint32_t startBlock = (minAddr - memory_range[pos].beginning) / m_blockSize; + // Init the memory image. Fill unused positions with 0xff + // After fill we have a block with data that is + // offset memory_range[pos].beginning + if (VSCP_ERROR_SUCCESS != (rv = fillMemoryBuffer(pbuf, + m_blockSize * nBlocks, + m_memory_range[memtype].start, + m_memory_range[memtype].end, + startBlock * m_blockSize))) { + spdlog::error("VSCP bootloader: Failed to fill memory buffer with data."); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: Failed to fill memory buffer with with data rv=%d", rv).c_str()); + } + delete[] pbuf; + return rv; + } - /* - Some notes to remember (and handle): - - Blocksize can be less than data size (ChunkSize) for a frame (8/512) - - A block size that is less than - */ - uint8_t *pbuf = new uint8_t[memory_range[pos].end - memory_range[pos].beginning + 1]; + spdlog::debug("VSCP bootloader: Filled memory buffer with with data."); + m_statusCallback(-1, vscp_str_format("VSCP bootloader: Filled memory buffer with with data.").c_str()); - // Init the memory image. Fill unused positions with 0xff - // After fill we have a block with data that is that is - // offset memory_range[pos].beginning - if (VSCP_ERROR_SUCCESS != (rv = fillMemoryBuffer(pbuf, m_blockSize, memory_range[pos].beginning))) { - spdlog::error("writeFirmwareBlock: Failed to fill code block with data."); - if (nullptr != m_statusCallback) { - m_statusCallback( - -1, - vscp_str_format("writeFirmwareBlock: Failed to fill code block with data rv=%d", rv).c_str()); - } - delete[] pbuf; - return rv; + // Write blocks to remote device + + uint32_t block = 0; + while (block < nBlocks) { + + spdlog::debug("VSCP bootloader: Start block {0} of {1}.", block, nBlocks); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: Start block %lu of %lu", (unsigned long) block, (unsigned long) nBlocks) + .c_str()); } - // Write blocks to remote device + // ---------------------------------------------------------------------- - uint32_t block = 0; - while (block < nBlocks) { + int trycnt = 3; // We give block transfer + program three tries for each block + while (trycnt > 0) { /*! * * * start block * * * - Startblock is the first block in an area. The block number - is given and also memory type. Blocknumbers can skip + Startblock is the first block in an area. The block number6 + is given and also memory type. It is possible to skip blocks that should not be written. */ - if (VSCP_ERROR_SUCCESS != (rv = writeBlockStart(block, memory_range[pos].type))) { + if (VSCP_ERROR_SUCCESS != (rv = writeBlockStart(block, m_memory_range[memtype].type))) { + spdlog::error("VSCP bootloader: Failed to write block {0}, memory-type={1}, rv={3}.", block, memtype, rv); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, + vscp_str_format("VSCP bootloader: Failed to write block %lu, memory-type=%d, rv=%d", + (unsigned long) block, + memtype, + rv) + .c_str()); + } + trycnt--; + if (trycnt > 0) { + spdlog::debug("VSCP bootloader: Retry block start {0}.", block); + continue; + } + // Last try failed delete[] pbuf; return rv; } + spdlog::debug("VSCP bootloader: Block start succeeded {0}.", block); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: Block start succeeded %lu ", (unsigned long) block).c_str()); + } + + // for (int i = 0; i < m_blockSize; i++) { + // printf("%02X ", pbuf[block * m_blockSize + i]); + // if (i % 8 == 7) { + // printf("\n"); + // } + // } + // Write the block if (VSCP_ERROR_SUCCESS != (rv = writeBlock(pbuf + (block * m_blockSize)))) { spdlog::error("VSCP bootloader: Failed to write block {0}", rv); if (nullptr != m_statusCallback) { - m_statusCallback(-1, "VSCP bootloader: Failed to write block"); + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: Failed to write block %lu rv=%d", (unsigned long) block, rv).c_str()); } + trycnt--; + if (trycnt > 0) { + spdlog::debug("VSCP bootloader: Retry write block {0}.", block); + continue; + } + // Last try failed delete[] pbuf; return rv; } + spdlog::debug("VSCP bootloader: Write block succeeded {0}.", block); + // Program the block if (VSCP_ERROR_SUCCESS != (rv = programBlock(block))) { + spdlog::error("VSCP bootloader: Program block failed. block={0} rv={1}", block, rv); + if (nullptr != m_statusCallback) { + m_statusCallback( + -1, + vscp_str_format("VSCP bootloader: Program block failed. block=%lu rv=%d", (unsigned long) block, rv) + .c_str()); + } + trycnt--; + if (trycnt > 0) { + spdlog::debug("VSCP bootloader: Retry block start {0}.", block); + continue; + } + // Last try failed delete[] pbuf; return rv; } - // Next block - block++; + spdlog::debug("VSCP bootloader: Program block succeeded {0}.", block); + // Update transfer status + if (nullptr != m_statusCallback) { + m_statusCallback( + (100 * block) / nBlocks, + vscp_str_format("VSCP bootloader: Program block succeeded %lu ", (unsigned long) block).c_str()); + } + // Done + trycnt = 0; - } // Writing blocks + } // while block - delete[] pbuf; + // ---------------------------------------------------------------------- + + // Next block + block++; + + } // Writing blocks + + delete[] pbuf; - } // There is bytes to write } // for memory types - return VSCP_ERROR_TIMEOUT; + return rv; } /////////////////////////////////////////////////////////////////////////////// @@ -655,7 +799,6 @@ int CBootDevice_VSCP::deviceReboot(void) { // int rv; - return VSCP_ERROR_SUCCESS; } @@ -691,32 +834,66 @@ CBootDevice_VSCP::checkResponse(vscpEventEx &ex, rv = m_pclient->receive(ex); - spdlog::debug("VSCP Bootloader: Received event: class={0} type={1} size={2}", + cguid evguid(ex.GUID); + + spdlog::debug("VSCP Bootloader: Received event: class={0} type={1} size={2} ev.guid={3} guid={4}", ex.vscp_class, ex.vscp_type, - ex.sizeData); + ex.sizeData, + evguid.toString(), + guid.toString()); - // Is this a read/write reply from the node? - if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (response_event_ack == ex.vscp_type) && guid.isSameGUID(ex.GUID)) { - // ACK response - spdlog::debug("VSCP Bootloader: ACK received."); - if (nullptr != m_statusCallback) { - m_statusCallback(-1, "VSCP Bootloader:ACK received"); + if (m_pclient->isFullLevel2()) { + + // Is this an ack reply from the node? + if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (response_event_ack == ex.vscp_type) && + guid.isSameGUID(ex.GUID)) { + // ACK response + spdlog::debug("VSCP bootloader: Check response: Level II ACK received."); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "VSCP bootloader: Check response: Level II ACK received"); + } + rv = VSCP_ERROR_SUCCESS; + break; + } + + // Is this a nack reply from the node? + if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (response_event_nack == ex.vscp_type) && + guid.isSameGUID(ex.GUID)) { + // NACK response + spdlog::error("VSCP bootloader: Check response: Level II NACK received."); + rv = VSCP_ERROR_NACK; + break; } - rv = VSCP_ERROR_SUCCESS; - break; } + else { + + // Level I - Only LSB byte (nickname id) is of interest + + // ACK received? + if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (response_event_ack == ex.vscp_type) && + guid[15] == ex.GUID[15]) { + // ACK response + spdlog::debug("VSCP bootloader: Check response: Level I ACK received. nickname={0} ev.nickname={1}", + guid[15], + ex.GUID[15]); + rv = VSCP_ERROR_SUCCESS; + break; + } - // Is this a read/write reply from the node? - if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (response_event_nack == ex.vscp_type) && - guid.isSameGUID(ex.GUID)) { - // NACK response - spdlog::debug("VSCP Bootloader: NACK received."); - if (nullptr != m_statusCallback) { - m_statusCallback(-1, "VSCP Bootloader: NACK received."); + // NACK received? + if ((VSCP_CLASS1_PROTOCOL == ex.vscp_class) && (response_event_nack == ex.vscp_type) && + guid[15] == ex.GUID[15]) { + // ACK response + spdlog::error("VSCP bootloader: Check response: Level I NACK received. nickname={0} ev.nickname={1}", + guid[15], + ex.GUID[15]); + if (nullptr != m_statusCallback) { + m_statusCallback(-1, "VSCP bootloader: Check response: Level I NACK received"); + } + rv = VSCP_ERROR_SUCCESS; + break; } - rv = VSCP_ERROR_NACK; - break; } } } // while diff --git a/src/vscp/common/vscp-bootdevice-vscp.h b/src/vscp/common/vscp-bootdevice-vscp.h index b8a354593..9b5aad907 100644 --- a/src/vscp/common/vscp-bootdevice-vscp.h +++ b/src/vscp/common/vscp-bootdevice-vscp.h @@ -31,20 +31,27 @@ #include "vscp.h" - -// This macro construct a signed integer from two unsigned chars in a safe way +/* This macro construct a signed integer from two unsigned chars in a safe way */ +#if !defined(construct_signed16) #define construct_signed16(msb, lsb) ((int16_t) ((((uint16_t) msb) << 8) + (uint16_t) lsb)) +#endif -// This macro construct a unsigned integer from two unsigned chars in a safe way +/* This macro construct a unsigned integer from two unsigned chars in a safe way */ +#if !defined(construct_unsigned16) #define construct_unsigned16(msb, lsb) ((uint16_t) ((((uint16_t) msb) << 8) + (uint16_t) lsb)) +#endif -// This macro construct a signed long from four unsigned chars in a safe way +/* This macro construct a signed long from four unsigned chars in a safe way */ +#if !defined(construct_signed32) #define construct_signed32(b0, b1, b2, b3) \ ((int32_t) ((((uint32_t) b0) << 24) + (((uint32_t) b1) << 16) + (((uint32_t) b2) << 8) + (uint32_t) b3)) +#endif -// This macro construct a unsigned long from four unsigned chars in a safe way +/* This macro construct a unsigned long from four unsigned chars in a safe way */ +#if !defined(construct_unsigned32) #define construct_unsigned32(b0, b1, b2, b3) \ - ((uint32_t) ((((uint32_t) b0) << 24) + (((uint32_t) b1) << 16) + (((uint32_t) b1) << 8) + (uint32_t) b3)) + ((uint32_t) ((((uint32_t) b0) << 24) + (((uint32_t) b1) << 16) + (((uint32_t) b2) << 8) + (uint32_t) b3)) +#endif class CBootDevice_VSCP : public CBootDevice { public: @@ -55,7 +62,7 @@ class CBootDevice_VSCP : public CBootDevice { @param nodeid Nickname/nodeid for node that should be loaded with new code. @param statusCallback Status callback function or NULL - @param timeout Timeout for response + @param timeout Timeout for response */ CBootDevice_VSCP(CVscpClient *pclient, uint8_t nodeid, @@ -99,16 +106,18 @@ class CBootDevice_VSCP : public CBootDevice { virtual ~CBootDevice_VSCP(void); // Memory Types - enum mem_type { - MEM_TYPE_FLASH = 0x00, // 0x00000000 - 0x3FFFFFFF 1G - MEM_TYPE_RAM = 0x03, // 0x40000000 - 0xBFFFFFFF 2G - MEM_TYPE_USERID = 0x04, // 0xC1000000 - 0xC1FFFFFF 16M - MEM_TYPE_CONFIG = 0x02, // 0xC2000000 - 0xC2FFFFFF 16M - MEM_TYPE_EEPROM = 0x01, // 0xC3000000 - 0xC3FFFFFF 16M - MEM_TYPE_USER1 = 0x05, // 0xD0000000 - 0xDFFFFFFF 256M - MEM_TYPE_USER2 = 0x06, // 0xE0000000 - 0xEFFFFFFF 256M - MEM_TYPE_USER3 = 0x07, // 0xF0000000 - 0xFFFFFFFF 256M - }; + typedef enum mem_type { + MEM_TYPE_FLASH = 0x00, // 0x00000000 - 0x3FFFFFFF 1G + MEM_TYPE_RAM = 0x03, // 0x40000000 - 0xBFFFFFFF 2G + MEM_TYPE_USERID = 0x04, // 0xC1000000 - 0xC1FFFFFF 16M + MEM_TYPE_CONFIG = 0x02, // 0xC2000000 - 0xC2FFFFFF 16M + MEM_TYPE_EEPROM = 0x01, // 0xC3000000 - 0xC3FFFFFF 16M + MEM_TYPE_BOOTLOADER = 0x06, // 0xC4000000 - 0xC4FFFFFF 16M + MEM_TYPE_FUSES = 0x05, // 0xC5000000 - 0xC5FFFFFF 16M + MEM_TYPE_USER1 = 0xFD, // 0xD0000000 - 0xDFFFFFFF 256M + MEM_TYPE_USER2 = 0xFE, // 0xE0000000 - 0xEFFFFFFF 256M + MEM_TYPE_USER3 = 0xFF, // 0xF0000000 - 0xFFFFFFFF 256M + } mem_type_t; // Flash memory static const uint32_t MEM_CODE_START = 0x00000000; @@ -130,6 +139,14 @@ class CBootDevice_VSCP : public CBootDevice { static const uint32_t MEM_EEPROM_START = 0xC3000000; static const uint32_t MEM_EEPROM_END = 0xC3FFFFFF; + // BOOTLOADER memory + static const uint32_t MEM_BOOTLOADER_START = 0xC4000000; + static const uint32_t MEM_BOOTLOADER_END = 0xC4FFFFFF; + + // FUSES memory + static const uint32_t MEM_FUSES_START = 0xC5000000; + static const uint32_t MEM_FUSES_END = 0xC5FFFFFF; + // User defined memory 0 static const uint32_t MEM_USER0_START = 0xD0000000; static const uint32_t MEM_USER0_END = 0xDFFFFFFF; @@ -145,18 +162,27 @@ class CBootDevice_VSCP : public CBootDevice { // Default timeout for response static const uint8_t BOOT_COMMAND_RESPONSE_TIMEOUT = 5; - static const uint8_t NUMBER_OF_MEMORY_TYPES = 8; + // Number of memory types + static const uint8_t NUMBER_OF_MEMORY_TYPES = 10; + /* clang-format off */ struct memory_range { uint8_t type; - uint32_t beginning; + uint32_t start; uint32_t end; - } memory_range[NUMBER_OF_MEMORY_TYPES] = { - { 0x00, MEM_CODE_START, MEM_CODE_START }, { 0x01, MEM_EEPROM_START, MEM_EEPROM_END }, - { 0x02, MEM_CONFIG_START, MEM_CONFIG_END }, { 0x03, MEM_RAM_START, MEM_RAM_END }, - { 0x04, MEM_USERID_START, MEM_USERID_END }, { 0xfd, MEM_USER0_START, MEM_USER0_END }, - { 0xfe, MEM_USER1_START, MEM_USER1_END }, { 0xff, MEM_USER2_START, MEM_USER2_END } + } m_memory_range[NUMBER_OF_MEMORY_TYPES] = { + { 0x00, MEM_CODE_START, MEM_CODE_END }, + { 0x01, MEM_EEPROM_START, MEM_EEPROM_END }, + { 0x02, MEM_CONFIG_START, MEM_CONFIG_END }, + { 0x03, MEM_RAM_START, MEM_RAM_END }, + { 0x04, MEM_USERID_START, MEM_USERID_END }, + { 0x05, MEM_BOOTLOADER_START, MEM_BOOTLOADER_END }, + { 0x06, MEM_FUSES_START, MEM_FUSES_END }, + { 0xfd, MEM_USER0_START, MEM_USER0_END }, + { 0xfe, MEM_USER1_START, MEM_USER1_END }, + { 0xff, MEM_USER2_START, MEM_USER2_END } }; + /* clang-format on */ // Initialize data void init(void); @@ -200,8 +226,6 @@ class CBootDevice_VSCP : public CBootDevice { */ int deviceReboot(void); - - /*! Write block start to remote device @param block Block number to write @@ -217,14 +241,14 @@ class CBootDevice_VSCP : public CBootDevice { */ int programBlock(uint32_t block); - /*! - Write a sector - @param paddr Pointer to first byte of 8-byte block to write - to remote device - @param size Number of data bytes to send. Must be less than the - max event data (8/512) - @return VSCP_ERROR_SUCCESS on success. - */ + /*! + Write a sector + @param paddr Pointer to first byte of 8-byte block to write + to remote device + @param size Number of data bytes to send. Must be less than the + max event data (8/512) + @return VSCP_ERROR_SUCCESS on success. + */ int writeChunk(const uint8_t *paddr, uint16_t size); /*! diff --git a/src/vscp/common/vscp-bootdevice.cpp b/src/vscp/common/vscp-bootdevice.cpp index 5510d31f3..487b3808d 100644 --- a/src/vscp/common/vscp-bootdevice.cpp +++ b/src/vscp/common/vscp-bootdevice.cpp @@ -63,15 +63,15 @@ // Ctor // -CBootMemBlock::CBootMemBlock(uint32_t address, uint8_t blksize, const uint8_t *pblkdata) +CBootMemSegment::CBootMemSegment(uint32_t address, uint8_t size, const uint8_t *pdata) { m_startAddress = address; - m_blksize = blksize; - m_pmemblk = nullptr; - if (nullptr != pblkdata) { - m_pmemblk = new uint8_t[blksize]; - if (nullptr != m_pmemblk) { - memcpy(m_pmemblk, pblkdata, blksize); + m_segSize = size; + m_pmemSegment = nullptr; + if (nullptr != pdata) { + m_pmemSegment = new uint8_t[size]; + if (nullptr != m_pmemSegment) { + memcpy(m_pmemSegment, pdata, size); } } } @@ -80,11 +80,11 @@ CBootMemBlock::CBootMemBlock(uint32_t address, uint8_t blksize, const uint8_t *p // Dtor // -CBootMemBlock::~CBootMemBlock(void) +CBootMemSegment::~CBootMemSegment(void) { - if (nullptr != m_pmemblk) { - delete[] m_pmemblk; - m_pmemblk = nullptr; + if (nullptr != m_pmemSegment) { + delete[] m_pmemSegment; + m_pmemSegment = nullptr; } } @@ -146,9 +146,9 @@ CBootDevice::CBootDevice(CVscpClient *pclient, CBootDevice::~CBootDevice(void) { - while (m_memblkList.size()) { - CBootMemBlock *pblk = m_memblkList.front(); - m_memblkList.pop_front(); + while (m_memSegList.size()) { + CBootMemSegment *pblk = m_memSegList.front(); + m_memSegList.pop_front(); delete pblk; pblk = nullptr; } @@ -162,8 +162,6 @@ int CBootDevice::loadIntelHexFile(const std::string &path) { char szline[2048]; - // char buf[16]; - // char *endptr; std::ifstream hexfile; uint16_t lowaddr = 0; // Low part of address uint16_t highaddr = 0; // High part if address @@ -215,7 +213,7 @@ CBootDevice::loadIntelHexFile(const std::string &path) // Construct fulladdress uint32_t fulladdr = (((uint32_t) highaddr) << 16) + lowaddr + segmentaddr; - spdlog::trace("cnt: {0} rectype:{1} lowaddr: {2} highaddr: {3} fulladdr: {4} segment: {5}", + spdlog::trace("cnt: {0} rectype:{1} lowaddr: {2:X} highaddr: {3:X} fulladdr: {4:X} segment: {5}", cnt, rectype, lowaddr, @@ -231,13 +229,13 @@ CBootDevice::loadIntelHexFile(const std::string &path) for (int i = 0; i < cnt; i++) { mem[i] = linebuf[4 + i]; } - CBootMemBlock *pblk = new CBootMemBlock(fulladdr, cnt, mem); + CBootMemSegment *pblk = new CBootMemSegment(fulladdr, cnt, mem); if (nullptr == pblk) { - spdlog::error("Load intel hex: Unabled to allocate block"); + spdlog::error("Load intel hex: Unable to allocate block"); hexfile.close(); return VSCP_ERROR_MEMORY; } - m_memblkList.push_back(pblk); + m_memSegList.push_back(pblk); } break; case CBootDevice::INTELHEX_LINETYPE_EOF: @@ -305,7 +303,7 @@ CBootDevice::getMinMaxForRange(uint32_t start, uint32_t end, uint32_t *pmin, uin *pmin = 0xffffffff; *pmax = 0; - for (auto const &pblk : m_memblkList) { + for (auto const &pblk : m_memSegList) { if ((pblk->getStartAddress() >= start) && (pblk->getStartAddress() <= end)) { // Set min to lowest address found if (pblk->getStartAddress() < *pmin) { @@ -333,7 +331,12 @@ CBootDevice::getMinMaxForRange(uint32_t start, uint32_t end, uint32_t *pmin, uin // int -CBootDevice::fillMemoryBuffer(uint8_t *pmem, uint32_t size, uint32_t start, uint8_t fill) +CBootDevice::fillMemoryBuffer(uint8_t *pmem, + uint32_t size, + uint32_t start, + uint32_t end, + uint32_t offset, + uint8_t fillbyte) { // Check pointers if (nullptr == pmem) { @@ -346,13 +349,15 @@ CBootDevice::fillMemoryBuffer(uint8_t *pmem, uint32_t size, uint32_t start, uint } // Fill block with void value (0xff for flash) - memset(pmem, fill, size); - - for (auto const &pblk : m_memblkList) { - if ((pblk->getStartAddress() >= start) && (pblk->getStartAddress() < (start + size))) { - for (uint8_t pos = 0; pos < pblk->getSize(); pos++) { - pmem[(pblk->getStartAddress() - start) + pos] = *(pblk->getBlock() + pos); - } + memset(pmem, fillbyte, size); + + /*! + Fill the memory buffer with data for this address range (given by start and size) + */ + for (auto const &pblk : m_memSegList) { + // Only add if the segment fits in the range + if ((pblk->getStartAddress() >= start) && ((pblk->getStartAddress() + pblk->getSize()) < end)) { + memcpy(pmem + (pblk->getStartAddress() - start - offset), pblk->getSegment(), pblk->getSize()); } } diff --git a/src/vscp/common/vscp-bootdevice.h b/src/vscp/common/vscp-bootdevice.h index 4e35e3741..10fc05652 100644 --- a/src/vscp/common/vscp-bootdevice.h +++ b/src/vscp/common/vscp-bootdevice.h @@ -56,7 +56,7 @@ different memory regions. When a block of data from that region is sent to the remote device it is up to that device to place the data at the correct location. This model can be used - for code, ram, eeprom, fuses, config data etc. The pic1 bootloader + for code, ram, EEPROM, fuses, config data etc. The pic1 bootloader use the Microchip abstract memory model. The VSCP bootloader let the receiving end take the decision on where a block should be written @@ -75,41 +75,78 @@ #include -class CBootMemBlock { +class CBootMemSegment { public: /*! - A memory blocks have a 32-bit start address and is - extending from this address with blksize bytes. The - block size is usually the same size as intel hex records + A memory segments have a 32-bit start address and is + extending from this address with segmentsize bytes. The + segment size is usually the same size as intel hex records but that is not a requirement @param address 32-bit start address for memory block - @param blksize 8-bit block size - @param pblkdata If not nullpointer this is a pointer to - a block with blksize bytes. + @param size 8-bit chunk size + @param pdata If not nullpointer this is a pointer to + a block with size bytes. */ - CBootMemBlock(uint32_t address, uint8_t blksize, const uint8_t *pblkdata = nullptr); + CBootMemSegment(uint32_t address, uint8_t size, const uint8_t *pdata = nullptr); /// @brief Dtor - virtual ~CBootMemBlock(void); + virtual ~CBootMemSegment(void); + /*! + Get the abstract start address for the segment + + @return Start address for segment + */ uint32_t getStartAddress(void) { return m_startAddress; }; + + /*! + Set the abstract start address for the segment + + @param addr Start address for segment + */ void setStartAddress(uint32_t addr) { m_startAddress = addr; }; - uint8_t getSize(void) { return m_blksize; }; - void setSize(uint8_t blksize) { m_blksize = blksize; }; + /*! + Get the size of the segment + + @return Size of segment + */ + uint8_t getSize(void) { return m_segSize; }; + + /*! + Set the size of the segment + + @param size Size of segment + */ + void setSize(uint8_t size) { m_segSize = size; }; + + /*! + Get a pointer to the segment data + + @return Pointer to segment data + */ + uint8_t *getSegment(void) { return m_pmemSegment; }; + + /*! + Get the memory type for this segment - uint8_t *getBlock(void) { return m_pmemblk; }; + @return Memory type as numeric defined in the VSCP specification + */ + uint8_t getType(void) { return m_type; }; private: /// The start addres for the memory block uint32_t m_startAddress; - /// Size of block - uint8_t m_blksize; + /// Size of segment + uint8_t m_segSize; /// Pointer to memory block (max 256 bytes) - uint8_t *m_pmemblk; + uint8_t *m_pmemSegment; + + /// Memory type + uint8_t m_type; }; class CBootDevice { @@ -195,7 +232,7 @@ class CBootDevice { /*! Get minimum and maximum address in a given memory range. This is intended for use when memory areas is used to define different - types of memory. Such as flash, eeprom, config, ram etc. + types of memory. Such as flash, EEPROM, config, ram etc. @param start Start address for memory range (inclusive - start is part of address space) @param end Stop address for memory range (inclusive - end is part of address space) @@ -210,16 +247,24 @@ class CBootDevice { virtual int getMinMaxForRange(uint32_t start, uint32_t end, uint32_t *pmin, uint32_t *pmax); /*! - Fill memory buffer with firmware data - The memory buffer is an area that hold an image of the memory on a remote - device. Typically for one type of memory. - @param pmem Pointer to the beginning of an allocated memory buffer - @param size Total size of block - @param start Logical start address - @param fill Value to initialize block with- 0xff is default - @return VSCP_ERROR_SUCCESS or errorcode otherwise. - */ - int fillMemoryBuffer(uint8_t *pmem, uint32_t size, uint32_t start, uint8_t fill = 0xff); + Fill memory buffer with firmware data + The memory buffer is an area that hold an image of the memory on a remote + device. Typically for one type of memory. + @param pmem Pointer to the beginning of an allocated memory buffer + @param size Total size of memory buffer + @param start Logical start address (inclusive) + @param end Logical end address (inclusive) + @param offset Memory offset for first used block. Always on a block + boundary. Defaults to zero. + @param fillbyte Value to initialize block with - 0xff is default + @return VSCP_ERROR_SUCCESS or errorcode otherwise. + */ + int fillMemoryBuffer(uint8_t *pmem, + uint32_t size, + uint32_t start, + uint32_t end, + uint32_t blockstart = 0, + uint8_t fillbyte = 0xff); /*! Get info for hex file in html format @@ -243,7 +288,8 @@ class CBootDevice { and status message (const char *) @return VSCP_ERROR_SUCCESS on success. */ - virtual int deviceLoad(std::function statusCallback = nullptr, bool bAbortOnFirmwareCodeFail = false) = 0; + virtual int deviceLoad(std::function statusCallback = nullptr, + bool bAbortOnFirmwareCodeFail = false) = 0; /*! Restart the device @@ -274,8 +320,6 @@ class CBootDevice { The device code tell the type of hardware of the remote device Must/should be the same as for the firmware we try to load. - This code is set in devicInit and is compared with the code in the device - Some (old) devices will have this code set to 0 in this cae no check should be performed. */ @@ -307,5 +351,5 @@ class CBootDevice { CStandardRegisters m_stdRegs; /// List with boot data - std::list m_memblkList; + std::list m_memSegList; }; diff --git a/src/vscp/common/vscp-class.h b/src/vscp/common/vscp-class.h index c40801ff4..1e485abaf 100644 --- a/src/vscp/common/vscp-class.h +++ b/src/vscp/common/vscp-class.h @@ -47,7 +47,7 @@ !!!!!!!!!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!!!!!!!!!! This file is auto-generated see https://github.com/grodansparadis/vscp-classes - Generated: 2024-12-09 21:43:36.673255 + Generated: 2024-12-12 17:07:55.637062 */ #ifndef VSCP_CLASS_H diff --git a/src/vscp/common/vscp-hashclass.h b/src/vscp/common/vscp-hashclass.h index eed28b99b..3bda76a05 100644 --- a/src/vscp/common/vscp-hashclass.h +++ b/src/vscp/common/vscp-hashclass.h @@ -2,7 +2,7 @@ !!!!!!!!!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!!!!!!!!!! This file is auto-generated see https://github.com/grodansparadis/vscp-classes - Generated: 2024-12-09 21:43:37.667848 + Generated: 2024-12-12 17:07:56.944066 */ m_hashClass[ 0 ] = _("CLASS1_PROTOCOL"); diff --git a/src/vscp/common/vscp-hashtype.h b/src/vscp/common/vscp-hashtype.h index edb2a8fb1..b20464108 100644 --- a/src/vscp/common/vscp-hashtype.h +++ b/src/vscp/common/vscp-hashtype.h @@ -2,7 +2,7 @@ !!!!!!!!!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!!!!!!!!!! This file is auto-generated see https://github.com/grodansparadis/vscp-classes - Generated: 2024-12-09 21:43:38.327870 + Generated: 2024-12-12 17:07:57.403175 */ diff --git a/src/vscp/common/vscp-type.h b/src/vscp/common/vscp-type.h index a21d62f37..719194a30 100644 --- a/src/vscp/common/vscp-type.h +++ b/src/vscp/common/vscp-type.h @@ -48,7 +48,7 @@ !!!!!!!!!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!!!!!!!!!! This file is auto-generated see https://github.com/grodansparadis/vscp-classes - Generated: 2024-12-09 21:43:37.152426 + Generated: 2024-12-12 17:07:56.200428 */ #ifndef VSCP_TYPE_H