Size optmstn

This commit is contained in:
Kimmo Kulovesi
2013-12-28 15:46:46 +02:00
parent d2ee1f089d
commit 4ec3a686b8
2 changed files with 74 additions and 84 deletions

View File

@@ -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);
}
}

View File

@@ -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);