A small C library for reading Intel HEX, Motorola SREC, and possibly more in the future.
All these formats are for storing programs as text using hexidecimal bytes. You can read all about them on Wikipedia:
FILE *file = fopen("example.hex", "r");
char buf[IHR_MAX_SIZE];
int reclen;
struct ihr_record rec;
size_t size;
char *line;
do {
line = fgetln(file, &size); /* This is valid until next call. */
/* The buffer is filled if the record has type 0 (data): */
rec.data.data = buf;
/* Read the line as an I8HEX record: */
if ((reclen = ihr_read(IHRT_I8, size, line, &rec)) < 0) {
/* ~reclen is the column; -rec.type is the error code: */
do_error(&rec, ~reclen);
} else {
use_record(&rec);
}
} while (rec.type != IHRR_I_END_OF_FILE);
fclose(file);
To use this library, you can probably just copy the header file into some header directory and the source file into your source directory. It should compile with ANSI C.
There is only one function in the API, although it is somewhat complex:
int ihr_read(
int file_type,
size_t len,
const char *text,
struct ihr_record *rec);
This function reads text-encoded data from text
, which is assumed to be of
length len
. No string terminator is necessary.
Before you call the function, you must set rec->data.data
to a buffer at
least IHR_MAX_SIZE
bytes in width (the maximum data entry length.) rec
points to a structure with this format:
struct ihr_record {
char type;
IHR_U8 size;
IHR_U32 addr;
union {
IHR_U8 *data;
union {
IHR_U16 base_addr;
IHR_U32 ext_instr_ptr;
struct {
IHR_U16 code_seg;
IHR_U16 instr_ptr;
} start;
} ihex;
} data;
};
The types called things like IHR_U8
are just unsigned integers of a certain
width (8 bits in this case.) You can read about the format of a record in the
Wikipedia link from the introduction, but here is a summary of the fields:
type
is the record type. The possible values are as follows:IHRR_DATA
is Data.IHRR_END_OF_FILE
is End of FileIHRR_EXT_SEG_ADDR
is Extended Segment Address.IHRR_START_SEG_ADDR
is Start Segment Address.IHRR_EXT_LIN_ADDR
is Extended Linear Address.IHRR_START_LIN_ADDR
is Start Linear Address.
size
is the byte count.addr
is the address.data
is a bunch of bytes, the number of which is indicated bysize
. The members of its union:data
is just raw bytes. This field is associated with the Data record type. The library does no allocation, which is why you must set this to an empty buffer beforehand.ihex
contains options specific to Intel HEX:base_addr
is associated with either one of the Extended Segment Address or Extended Linear Address types. The meaning of the address is different, but the data can be stored the same way.ext_instr_ptr
corresponds with the Start Linear Address type.start
corresponds with the Start Segment Address type. Itscode_seg
field is the start of the code segment, while itsinstr_ptr
field is the initial instruction pointer position.
The file_type
field describes the subset of the format to use. The subset
restricts which field types are valid.
IHRT_I8
is I8HEXIHRT_I16
is I32HEXIHRT_I32
is I32HEXIHRT_S19
is SREC S19IHRT_S28
is SREC S28IHRT_S37
is SREC S37
The return value of the function is positive on success or negative on error. If
it is positive, it indicates how much of the text was read as part of the
record. If it is negative, ~line
(not -
, but ~
) indicates the erroneous
part of the text. On error, the type
of the record is set to a negated error
value. No other data can be read from the record. Here are possible errors with
their descriptions:
IHRE_EXPECTED_EOL
: Record does not end with\n
or\r\n
.IHRE_INVALID_CHECKSUM
: The checksum of the record did not match its computed checksum.IHRE_INVALID_SIZE
: The byte count of the record was not correct.IHRE_INVALID_TYPE
: The type of the record was not valid.IHRE_MISSING_COLON
: The:
which must begin every record was not present.IHRE_NOT_HEX
: A pair of bytes could not be parsed as a hexidecimal number.IHRE_SUB_MIN_LENGTH
: The givenlen
is belowIHR_MIN_LENGTH
, the minimum text-encoded record length.