mirror of
https://github.com/VARCem/ihex.git
synced 2026-09-23 15:34:23 +00:00
Size optmstn
This commit is contained in:
156
kk_ihex_write.c
156
kk_ihex_write.c
@@ -10,10 +10,11 @@
|
||||
|
||||
#include "kk_ihex_write.h"
|
||||
|
||||
static const char IHEX_START = ':';
|
||||
#define IHEX_START ':'
|
||||
|
||||
static const char IHEX_NEWLINE[] = IHEX_NEWLINE_STRING;
|
||||
|
||||
#define ADDRESS_HIGH_MASK 0xFFFF0000U
|
||||
#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U)
|
||||
#define ADDRESS_HIGH_BYTES(addr) ((addr) >> 16)
|
||||
|
||||
#define HEX_DIGIT(n) ((n) + ( ((n) < 10) ? '0' : ('A' - 10)))
|
||||
@@ -30,9 +31,9 @@ ihex_init (struct ihex_state * const ihex) {
|
||||
#ifndef IHEX_DISABLE_SEGMENTS
|
||||
ihex->segment = 0;
|
||||
#endif
|
||||
ihex->length = 0;
|
||||
ihex->flags = 0;
|
||||
ihex->line_length = IHEX_DEFAULT_OUTPUT_LINE_LENGTH;
|
||||
ihex->length = 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -63,18 +64,63 @@ ihex_buffer_newline (char *w) {
|
||||
return w;
|
||||
}
|
||||
|
||||
// Write the contents of the data buffer to w, increment address, and reset
|
||||
// data length. Return pointer to one past the last character written to w
|
||||
// (w is not NUL-terminated).
|
||||
static void
|
||||
ihex_write_end_of_file (struct ihex_state * const ihex) {
|
||||
char *w = line_buffer;
|
||||
*w++ = IHEX_START; // :
|
||||
#if 0
|
||||
for (unsigned int i = 7; i; --i) {
|
||||
*w++ = '0';
|
||||
}
|
||||
*w++ = '1';
|
||||
*w++ = 'F';
|
||||
*w++ = 'F';
|
||||
#else
|
||||
w = ihex_buffer_byte(w, 0); // length
|
||||
w = ihex_buffer_byte(w, 0); // address msb
|
||||
w = ihex_buffer_byte(w, 0); // address lsb
|
||||
w = ihex_buffer_byte(w, IHEX_END_OF_FILE_RECORD); // record type
|
||||
w = ihex_buffer_byte(w, ~IHEX_END_OF_FILE_RECORD + 1); // checksum
|
||||
#endif
|
||||
w = ihex_buffer_newline(w);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
}
|
||||
|
||||
static char *
|
||||
ihex_buffer_data (char *w, struct ihex_state * const ihex) {
|
||||
static void
|
||||
ihex_write_extended_address (struct ihex_state * const ihex,
|
||||
const ihex_segment_t address,
|
||||
const enum ihex_record_type type) {
|
||||
char *w = line_buffer;
|
||||
unsigned int sum = type + 2;
|
||||
|
||||
*w++ = IHEX_START; // :
|
||||
w = ihex_buffer_byte(w, 2); // length
|
||||
w = ihex_buffer_byte(w, 0); // 16-bit address msb
|
||||
w = ihex_buffer_byte(w, 0); // 16-bit address lsb
|
||||
w = ihex_buffer_byte(w, type); // record type
|
||||
w = ihex_buffer_word(w, address, &sum); // high bytes of address
|
||||
w = ihex_buffer_byte(w, ~sum + 1); // checksum
|
||||
w = ihex_buffer_newline(w);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
}
|
||||
|
||||
// Write out `ihex->data`
|
||||
//
|
||||
static void
|
||||
ihex_write_data (struct ihex_state * const ihex) {
|
||||
unsigned int len = ihex->length;
|
||||
unsigned int sum = len;
|
||||
uint8_t *r = ihex->data;
|
||||
char *w = line_buffer;
|
||||
|
||||
if (!len) {
|
||||
return w;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ihex->flags & IHEX_FLAG_ADDRESS_OVERFLOW) {
|
||||
ihex_write_extended_address(ihex, ADDRESS_HIGH_BYTES(ihex->address),
|
||||
IHEX_EXTENDED_LINEAR_ADDRESS_RECORD);
|
||||
ihex->flags &= ~IHEX_FLAG_ADDRESS_OVERFLOW;
|
||||
}
|
||||
|
||||
// :
|
||||
@@ -89,7 +135,7 @@ ihex_buffer_data (char *w, struct ihex_state * const ihex) {
|
||||
unsigned int addr = ihex->address & 0xFFFFU;
|
||||
ihex->address += len;
|
||||
if ((0xFFFFU - addr) < len) {
|
||||
// signal overflow (need to write extended address record)
|
||||
// signal address overflow (need to write extended address)
|
||||
ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW;
|
||||
}
|
||||
w = ihex_buffer_word(w, addr, &sum);
|
||||
@@ -107,59 +153,17 @@ ihex_buffer_data (char *w, struct ihex_state * const ihex) {
|
||||
} while (--len);
|
||||
|
||||
// checksum
|
||||
sum = 0x100U - (sum & 0xFFU);
|
||||
w = ihex_buffer_byte(w, sum);
|
||||
w = ihex_buffer_byte(w, ~sum + 1U);
|
||||
|
||||
return ihex_buffer_newline(w);
|
||||
}
|
||||
|
||||
static char *
|
||||
ihex_buffer_extended_address (char *w, const ihex_segment_t address,
|
||||
const enum ihex_record_type type) {
|
||||
unsigned int sum = type + 2;
|
||||
|
||||
*w++ = IHEX_START; // :
|
||||
w = ihex_buffer_byte(w, 2); // length
|
||||
w = ihex_buffer_byte(w, 0); // address msb
|
||||
w = ihex_buffer_byte(w, 0); // address lsb
|
||||
w = ihex_buffer_byte(w, type); // record type
|
||||
w = ihex_buffer_word(w, address, &sum); // high bytes of 32-bit address
|
||||
w = ihex_buffer_byte(w, 0x100U - sum); // checksum
|
||||
return ihex_buffer_newline(w);
|
||||
}
|
||||
|
||||
// Write an end of file record to w, return a pointer to one past the
|
||||
// last character written to w (which is not NUL-terminated).
|
||||
|
||||
static char *
|
||||
ihex_buffer_end_of_file (char *w) {
|
||||
*w++ = IHEX_START; // :
|
||||
w = ihex_buffer_byte(w, 0); // length
|
||||
w = ihex_buffer_byte(w, 0); // address msb
|
||||
w = ihex_buffer_byte(w, 0); // address lsb
|
||||
w = ihex_buffer_byte(w, IHEX_END_OF_FILE_RECORD); // record type
|
||||
w = ihex_buffer_byte(w, 0x100U - IHEX_END_OF_FILE_RECORD); // checksum
|
||||
return ihex_buffer_newline(w);
|
||||
}
|
||||
|
||||
static void
|
||||
ihex_check_address_overflow (struct ihex_state *ihex) {
|
||||
if (ihex->flags & IHEX_FLAG_ADDRESS_OVERFLOW) {
|
||||
char *w = ihex_buffer_extended_address(line_buffer,
|
||||
ADDRESS_HIGH_BYTES(ihex->address),
|
||||
IHEX_EXTENDED_LINEAR_ADDRESS_RECORD);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
ihex->flags &= ~IHEX_FLAG_ADDRESS_OVERFLOW;
|
||||
}
|
||||
w = ihex_buffer_newline(w);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
}
|
||||
|
||||
void
|
||||
ihex_write_at_address (struct ihex_state *ihex, ihex_address_t address) {
|
||||
if (ihex->length) {
|
||||
ihex_check_address_overflow(ihex);
|
||||
// flush any existing data
|
||||
char *w = ihex_buffer_data(line_buffer, ihex);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
ihex_write_data(ihex);
|
||||
}
|
||||
if ((ihex->address & ADDRESS_HIGH_MASK) != (address & ADDRESS_HIGH_MASK)) {
|
||||
ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW;
|
||||
@@ -186,42 +190,32 @@ ihex_write_at_segment (struct ihex_state *ihex, ihex_segment_t segment, ihex_add
|
||||
ihex_write_at_address(ihex, address);
|
||||
if (ihex->segment != segment) {
|
||||
// clear segment
|
||||
char *w = ihex_buffer_extended_address(line_buffer,
|
||||
(ihex->segment = segment),
|
||||
IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
ihex_write_extended_address(ihex, (ihex->segment = segment),
|
||||
IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ihex_write_byte (struct ihex_state *ihex, uint8_t byte) {
|
||||
ihex->data[(ihex->length)++] = byte;
|
||||
if (ihex->length >= ihex->line_length) {
|
||||
ihex_check_address_overflow(ihex);
|
||||
char *w = ihex_buffer_data(line_buffer, ihex);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
ihex_write_byte (struct ihex_state *ihex, unsigned int byte) {
|
||||
if (ihex->line_length <= ihex->length) {
|
||||
ihex_write_data(ihex);
|
||||
}
|
||||
ihex->data[(ihex->length)++] = byte;
|
||||
}
|
||||
|
||||
void
|
||||
ihex_end_write (struct ihex_state *ihex) {
|
||||
char *w;
|
||||
if (ihex->length) {
|
||||
ihex_check_address_overflow(ihex);
|
||||
w = ihex_buffer_data(line_buffer, ihex);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
}
|
||||
w = ihex_buffer_end_of_file(line_buffer);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
ihex_write_data(ihex); // flush any remaining data
|
||||
ihex_write_end_of_file(ihex);
|
||||
}
|
||||
|
||||
void
|
||||
ihex_write_bytes (struct ihex_state *ihex, uint8_t *data, unsigned int count) {
|
||||
uint8_t *r = data;
|
||||
while (count) {
|
||||
unsigned int i = ihex->line_length - ihex->length;
|
||||
if (i) {
|
||||
if (ihex->line_length > ihex->length) {
|
||||
unsigned int i = ihex->line_length - ihex->length;
|
||||
uint8_t *w = &(ihex->data[ihex->length]);
|
||||
i = (i > count) ? count : i;
|
||||
count -= i;
|
||||
@@ -229,13 +223,9 @@ ihex_write_bytes (struct ihex_state *ihex, uint8_t *data, unsigned int count) {
|
||||
do {
|
||||
*w++ = *r++;
|
||||
} while (--i);
|
||||
} else {
|
||||
ihex_write_data(ihex);
|
||||
}
|
||||
if (ihex->length >= ihex->line_length) {
|
||||
char *w;
|
||||
ihex_check_address_overflow(ihex);
|
||||
w = ihex_buffer_data(line_buffer, ihex);
|
||||
ihex_flush_buffer(ihex, line_buffer, w);
|
||||
}
|
||||
} while (count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ void ihex_init(struct ihex_state * const ihex);
|
||||
void ihex_write_at_address(struct ihex_state *ihex, ihex_address_t address);
|
||||
|
||||
// Write a single byte
|
||||
void ihex_write_byte(struct ihex_state *ihex, uint8_t b);
|
||||
void ihex_write_byte(struct ihex_state *ihex, unsigned int b);
|
||||
|
||||
// Write `count` bytes from `data`
|
||||
void ihex_write_bytes(struct ihex_state *ihex, uint8_t *data, unsigned int count);
|
||||
|
||||
Reference in New Issue
Block a user