Allow using an external write buffer

This commit is contained in:
Kimmo Kulovesi
2014-02-25 16:23:09 +02:00
parent 2c2177de56
commit 3cd2850a6d
3 changed files with 40 additions and 12 deletions

View File

@@ -80,6 +80,12 @@
* maximum as greater than the line length you'll actually be writing,
* e.g., 32 or 16.
*
* If the write functionality is only occasionally used, you can provide
* your own buffer for the duration by defining `IHEX_EXTERNAL_WRITE_BUFFER`
* and providing a `char *ihex_write_buffer` which points to valid storage
* for at least `IHEX_WRITE_BUFFER_LENGTH` characters from before the first
* call to any IHEX write function to until after the last.
*
* If you are doing both reading and writing, you can define the maximum
* output length separately as `IHEX_MAX_OUTPUT_LINE_LENGTH` - this will
* decrease the write buffer size, but `struct ihex_state` will still
@@ -100,7 +106,7 @@
#ifndef KK_IHEX_H
#define KK_IHEX_H
#define KK_IHEX_VERSION "2014-02-24"
#define KK_IHEX_VERSION "2014-02-25"
#include <stdint.h>
#include <stdbool.h>
@@ -128,6 +134,7 @@ typedef struct ihex_state {
} kk_ihex_t;
#define IHEX_FLAG_ADDRESS_OVERFLOW 0x80 // 16-bit address overflow
// (Other flags are reserved for internal use!)
enum ihex_record_type {
IHEX_DATA_RECORD,
@@ -153,7 +160,7 @@ enum ihex_record_type {
// afterwards.
//
// To implement fully correct segmented addressing, compute the address
// of _each byte_ with its index as follows:
// of _each byte_ with its index in `data` as follows:
//
#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((((ihex)->address + (byte_index)) & 0xFFFFU) + (((ihex_address_t)((ihex)->segment)) << 4))

View File

@@ -12,14 +12,14 @@
#define IHEX_START ':'
static const char IHEX_NEWLINE[] = IHEX_NEWLINE_STRING;
#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)))
static char line_buffer[1+2+4+2+(IHEX_MAX_OUTPUT_LINE_LENGTH*2)+2+sizeof(IHEX_NEWLINE)];
#ifndef IHEX_EXTERNAL_WRITE_BUFFER
static char ihex_write_buffer[IHEX_WRITE_BUFFER_LENGTH];
#endif
#if IHEX_MAX_OUTPUT_LINE_LENGTH > IHEX_LINE_MAX_LENGTH
#error "IHEX_MAX_OUTPUT_LINE_LENGTH > IHEX_LINE_MAX_LENGTH"
@@ -58,7 +58,7 @@ ihex_buffer_word (char * restrict w, const unsigned int word,
static char *
ihex_buffer_newline (char * restrict w) {
const char * restrict r = IHEX_NEWLINE;
const char *r = IHEX_NEWLINE_STRING;
do {
*w++ = *r++;
} while (*r);
@@ -67,7 +67,7 @@ ihex_buffer_newline (char * restrict w) {
static void
ihex_write_end_of_file (struct ihex_state * const ihex) {
char *w = line_buffer;
char * restrict w = ihex_write_buffer;
*w++ = IHEX_START; // :
#if 0
for (unsigned int i = 7; i; --i) {
@@ -84,14 +84,14 @@ ihex_write_end_of_file (struct ihex_state * const ihex) {
w = ihex_buffer_byte(w, ~((unsigned int)IHEX_END_OF_FILE_RECORD) + 1U); // checksum
#endif
w = ihex_buffer_newline(w);
ihex_flush_buffer(ihex, line_buffer, w);
ihex_flush_buffer(ihex, ihex_write_buffer, w);
}
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;
char * restrict w = ihex_write_buffer;
unsigned int sum = type + 2;
*w++ = IHEX_START; // :
@@ -102,7 +102,7 @@ ihex_write_extended_address (struct ihex_state * const ihex,
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);
ihex_flush_buffer(ihex, ihex_write_buffer, w);
}
// Write out `ihex->data`
@@ -111,7 +111,7 @@ static void
ihex_write_data (struct ihex_state * const ihex) {
unsigned int len = ihex->length;
unsigned int sum = len;
char *w = line_buffer;
char * restrict w = ihex_write_buffer;
if (!len) {
return;
@@ -159,7 +159,7 @@ ihex_write_data (struct ihex_state * const ihex) {
w = ihex_buffer_byte(w, ~sum + 1U);
w = ihex_buffer_newline(w);
ihex_flush_buffer(ihex, line_buffer, w);
ihex_flush_buffer(ihex, ihex_write_buffer, w);
}
void

View File

@@ -48,6 +48,16 @@
* both the `struct ihex_state' and the internal write buffer smaller.
* For example, 32 or even 16 can be used instead of the default 255.
*
* If the write functionality is not used all the time and can thus
* share its write buffer memory with something else that is inactive
* during writing IHEX, you can define `IHEX_EXTERNAL_WRITE_BUFFER` and
* provide the buffer as `char *ihex_write_buffer`. The size of the
* buffer must be at least `IHEX_WRITE_BUFFER_LENGTH` bytes and it must
* be valid for the entire duration from the first call to a write function
* until after the last call to `ihex_end_write`. Note that there is
* no advantage to this unless something else, mutually exclusive with
* IHEX writing, can share the memory.
*
* If you are reading IHEX as well, then you'll end up limiting the
* maximum length of line that can be read. In that case you may wish to
* define `IHEX_MAX_OUTPUT_LINE_LENGTH` as smaller to decrease the
@@ -79,6 +89,17 @@ extern "C" {
#define IHEX_MAX_OUTPUT_LINE_LENGTH IHEX_LINE_MAX_LENGTH
#endif
// Length of the write buffer required
#define IHEX_WRITE_BUFFER_LENGTH (1+2+4+2+(IHEX_MAX_OUTPUT_LINE_LENGTH*2)+2+sizeof(IHEX_NEWLINE_STRING))
#ifdef IHEX_EXTERNAL_WRITE_BUFFER
// Define `IHEX_EXTERNAL_WRITE_BUFFER` to provide an external write buffer,
// as `char *ihex_write_buffer`, which must point to a valid storage for
// at least `IHEX_WRITE_BUFFER_LENGTH` characters whenever any of the
// write functionality is used (see above under "CONSERVING MEMORY").
extern char *ihex_write_buffer;
#endif
// Initialise the structure `ihex` for writing
void ihex_init(struct ihex_state * const ihex);