-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/****************************************************************************** | ||
* * | ||
* Copyright (C) 2024 MachineWare GmbH * | ||
* All Rights Reserved * | ||
* * | ||
* This is work is licensed under the terms described in the LICENSE file * | ||
* found in the root directory of this source tree. * | ||
* * | ||
******************************************************************************/ | ||
|
||
#ifndef MWR_UTILS_IHEX_H | ||
#define MWR_UTILS_IHEX_H | ||
|
||
#include "mwr/core/types.h" | ||
#include "mwr/core/report.h" | ||
|
||
#include "mwr/stl/strings.h" | ||
#include "mwr/stl/containers.h" | ||
|
||
namespace mwr { | ||
|
||
class ihex | ||
{ | ||
public: | ||
struct record { | ||
u64 addr; | ||
vector<u8> data; | ||
}; | ||
|
||
u64 start_addr() const { return m_start_addr; } | ||
const vector<record>& records() const { return m_records; } | ||
|
||
ihex(const string& filename); | ||
~ihex() = default; | ||
|
||
ihex(const ihex&) = delete; | ||
|
||
private: | ||
u64 m_start_addr; | ||
vector<record> m_records; | ||
}; | ||
|
||
} // namespace mwr | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/****************************************************************************** | ||
* * | ||
* Copyright (C) 2024 MachineWare GmbH * | ||
* All Rights Reserved * | ||
* * | ||
* This is work is licensed under the terms described in the LICENSE file * | ||
* Found in the root directory of this source tree. * | ||
* * | ||
******************************************************************************/ | ||
|
||
#include "mwr/utils/ihex.h" | ||
|
||
namespace mwr { | ||
|
||
enum record_type : u8 { | ||
IHEX_DATA = 0x00, | ||
IHEX_EOF = 0x01, | ||
IHEX_EX_SEG = 0x02, | ||
IHEX_START_SEG = 0x03, | ||
IHEX_EX_LIN_ADDR = 0x04, | ||
IHEX_START_LIN_ADDR = 0x05, | ||
INVALID_LINE_FORMAT, | ||
INVALID_LINE_LEN, | ||
INVALID_TYPE, | ||
INVALID_DESCRIPTOR, | ||
INVALID_CHECKSUM, | ||
}; | ||
|
||
struct ihex_record { | ||
record_type type; | ||
u64 addr; | ||
vector<u8> data; | ||
}; | ||
|
||
static inline u8 ihex_byte(const string& line, size_t off) { | ||
MWR_ERROR_ON(off + 1 >= line.size(), "reading beyond srec line"); | ||
return from_hex_ascii(line[off]) << 4 | from_hex_ascii(line[off + 1]); | ||
} | ||
|
||
template <typename T> | ||
static inline u64 vec_to(const std::vector<u8>& vec) { | ||
constexpr size_t num_bytes = sizeof(T); | ||
MWR_ERROR_ON(num_bytes > vec.size(), "reading beyond given vector"); | ||
T result = 0; | ||
for (size_t i = 0; i < num_bytes; ++i) | ||
result = (result << 8) | vec[i]; | ||
return result; | ||
} | ||
|
||
static inline ihex_record process_line(const string& line) { | ||
const size_t delim = 1; | ||
const size_t data_start = 9; | ||
const size_t check_bytes = 1; | ||
const size_t min_line_len = data_start + check_bytes * 2; | ||
|
||
if (line.size() < min_line_len || line[0] != ':') | ||
return { INVALID_LINE_FORMAT, 0, { 0 } }; | ||
|
||
const u32 nr_bytes = ihex_byte(line, 1); | ||
const u16 addr = ihex_byte(line, 3) << 8 | ihex_byte(line, 5); | ||
const record_type r_type = static_cast<record_type>(ihex_byte(line, 7)); | ||
const size_t line_len = min_line_len + nr_bytes * 2; | ||
|
||
if (line.size() < line_len) | ||
return { INVALID_LINE_LEN, 0, { 0 } }; | ||
|
||
u8 check_sum = 0; | ||
for (size_t pos = delim; pos < line_len; pos += 2) | ||
check_sum += ihex_byte(line, pos); | ||
if (check_sum != 0x00) | ||
return { INVALID_CHECKSUM, 0, {} }; | ||
|
||
switch (r_type) { | ||
case IHEX_DATA: | ||
break; | ||
case IHEX_EOF: | ||
if (nr_bytes != 0x00 || addr != 0x0000) | ||
return { INVALID_DESCRIPTOR, 0, {} }; | ||
return { IHEX_EOF, 0, {} }; | ||
case IHEX_EX_SEG: | ||
case IHEX_EX_LIN_ADDR: | ||
if (nr_bytes != 0x02 || addr != 0x0000) | ||
return { INVALID_DESCRIPTOR, 0, {} }; | ||
break; | ||
case IHEX_START_SEG: | ||
case IHEX_START_LIN_ADDR: | ||
if (nr_bytes != 0x04 || addr != 0x0000) | ||
return { INVALID_DESCRIPTOR, 0, {} }; | ||
break; | ||
default: | ||
return { INVALID_TYPE, 0, {} }; | ||
} | ||
|
||
vector<u8> data; | ||
data.reserve(nr_bytes); | ||
for (size_t pos = data_start; pos < data_start + nr_bytes * 2; pos += 2) | ||
data.push_back(ihex_byte(line, pos)); | ||
return { r_type, addr, std::move(data) }; | ||
} | ||
|
||
ihex::ihex(const string& filename): m_start_addr(), m_records() { | ||
ifstream file(filename); | ||
MWR_ERROR_ON(!file, "Cannot open ihex file '%s'", filename.c_str()); | ||
|
||
u64 seg_offset = 0; | ||
u64 linear_offset = 0; | ||
string line; | ||
while (getline(file, line)) { | ||
line = trim(line); | ||
ihex_record ihex_rec = process_line(line); | ||
|
||
switch (ihex_rec.type) { | ||
case IHEX_DATA: { | ||
record rec = {}; | ||
rec.addr = ihex_rec.addr + seg_offset + linear_offset; | ||
rec.data = std::move(ihex_rec.data); | ||
m_records.push_back(std::move(rec)); | ||
break; | ||
}; | ||
case IHEX_EOF: | ||
return; | ||
case IHEX_EX_SEG: | ||
seg_offset = vec_to<u16>(ihex_rec.data) << 4; | ||
break; | ||
case IHEX_START_SEG: | ||
case IHEX_START_LIN_ADDR: | ||
m_start_addr = vec_to<u32>(ihex_rec.data); | ||
break; | ||
case IHEX_EX_LIN_ADDR: | ||
linear_offset = vec_to<u16>(ihex_rec.data) << 16; | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
MWR_REPORT_ON(m_records.size() == 0, | ||
"File '%s' does not seem to be in Intel hex format", | ||
filename.c_str()); | ||
} | ||
|
||
} // namespace mwr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
:04000005000000CD2A //start address = 0x000000CD | ||
:10010000214601360121470136007EFE09D2190140 | ||
:100110002146017E17C20001FF5F16002148011928 | ||
:020000040800F2//extended linear address by 0x800 << 16 | ||
:10012000194E79234623965778239EDA3F01B2CAA7 | ||
:0200000200001FA//extended linear address by 0x1 << 4 | ||
:100130003F0156702B5E712B722B732146013421C7 | ||
:100130003F0156702B5E712B722B732146013421C6 //broken checksum -> should not appear as line in test | ||
:00000001FF//eof |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/****************************************************************************** | ||
* * | ||
* Copyright (C) 2024 MachineWare GmbH * | ||
* All Rights Reserved * | ||
* * | ||
* This is work is licensed under the terms described in the LICENSE file * | ||
* found in the root directory of this source tree. * | ||
* * | ||
******************************************************************************/ | ||
|
||
#include "testing.h" | ||
|
||
#include "mwr.h" | ||
|
||
using namespace mwr; | ||
|
||
const vector<u8> V1 = { 0x21, 0x46, 0x01, 0x36, 0x01, 0x21, 0x47, 0x01, | ||
0x36, 0x00, 0x7E, 0xFE, 0x09, 0xD2, 0x19, 0x01 }; | ||
|
||
const vector<u8> V2 = { 0x21, 0x46, 0x01, 0x7E, 0x17, 0xC2, 0x00, 0x01, | ||
0xFF, 0x5F, 0x16, 0x00, 0x21, 0x48, 0x01, 0x19 }; | ||
|
||
const vector<u8> V3 = { 0x19, 0x4E, 0x79, 0x23, 0x46, 0x23, 0x96, 0x57, | ||
0x78, 0x23, 0x9E, 0xDA, 0x3F, 0x01, 0xB2, 0xCA }; | ||
|
||
const vector<u8> V4 = { 0x3F, 0x01, 0x56, 0x70, 0x2B, 0x5E, 0x71, 0x2B, | ||
0x72, 0x2B, 0x73, 0x21, 0x46, 0x01, 0x34, 0x21 }; | ||
|
||
TEST(ihex, load) { | ||
ihex reader(get_resource_path("sample.ihex")); | ||
|
||
EXPECT_EQ(reader.start_addr(), 0xcd); | ||
ASSERT_EQ(reader.records().size(), 4); | ||
|
||
EXPECT_EQ(reader.records()[0].addr, 0x0100); | ||
EXPECT_EQ(reader.records()[1].addr, 0x0110); | ||
EXPECT_EQ(reader.records()[2].addr, 0x0120 | 0x800 << 16); | ||
EXPECT_EQ(reader.records()[3].addr, 0x0130 | 0x800 << 16 | 0x1 << 4); | ||
|
||
EXPECT_EQ(reader.records()[0].data, V1); | ||
EXPECT_EQ(reader.records()[1].data, V2); | ||
EXPECT_EQ(reader.records()[2].data, V3); | ||
EXPECT_EQ(reader.records()[3].data, V4); | ||
} |