OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_c/] [ihex2bin/] [kk_ihex_write.c] - Blame information for rev 25

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 alirezamon
/*
2
 * kk_ihex_write.c: A simple library for writing the Intel HEX (IHEX) format.
3
 *
4
 * See the header `kk_ihex.h` for instructions.
5
 *
6
 * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/
7
 * Provided with absolutely no warranty, use at your own risk only.
8
 * Use and distribute freely, mark modified copies as such.
9
 */
10
 
11
#include "kk_ihex_write.h"
12
 
13
#define IHEX_START ':'
14
 
15
#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U)
16
#define ADDRESS_HIGH_BYTES(addr) ((addr) >> 16)
17
 
18
#define HEX_DIGIT(n) ((char)((n) + (((n) < 10) ? '0' : ('A' - 10))))
19
 
20
#ifndef IHEX_EXTERNAL_WRITE_BUFFER
21
static char ihex_write_buffer[IHEX_WRITE_BUFFER_LENGTH];
22
#endif
23
 
24
#if IHEX_MAX_OUTPUT_LINE_LENGTH > IHEX_LINE_MAX_LENGTH
25
#error "IHEX_MAX_OUTPUT_LINE_LENGTH > IHEX_LINE_MAX_LENGTH"
26
#endif
27
 
28
void
29
ihex_init (struct ihex_state * const ihex) {
30
    ihex->address = 0;
31
#ifndef IHEX_DISABLE_SEGMENTS
32
    ihex->segment = 0;
33
#endif
34
    ihex->flags = 0;
35
    ihex->line_length = IHEX_DEFAULT_OUTPUT_LINE_LENGTH;
36
    ihex->length = 0;
37
}
38
 
39
static char *
40
ihex_buffer_byte (char * restrict w, const uint8_t byte) {
41
    uint8_t n = (byte & 0xF0U) >> 4; // high nybble
42
    *w++ = HEX_DIGIT(n);
43
    n = byte & 0x0FU; // low nybble
44
    *w++ = HEX_DIGIT(n);
45
    return w;
46
}
47
 
48
static char *
49
ihex_buffer_word (char * restrict w, const uint_fast16_t word,
50
                  uint8_t * const restrict checksum) {
51
    uint8_t byte = (word >> 8) & 0xFFU; // high byte
52
    w = ihex_buffer_byte(w, (uint8_t)byte);
53
    *checksum += byte;
54
    byte = word & 0xFFU; // low byte
55
    *checksum += byte;
56
    return ihex_buffer_byte(w, (uint8_t)byte);
57
}
58
 
59
static char *
60
ihex_buffer_newline (char * restrict w) {
61
    const char * restrict r = IHEX_NEWLINE_STRING;
62
    do {
63
        *w++ = *r++;
64
    } while (*r);
65
    return w;
66
}
67
 
68
static void
69
ihex_write_end_of_file (struct ihex_state * const ihex) {
70
    char * restrict w = ihex_write_buffer;
71
    *w++ = IHEX_START; // :
72
#if 1
73
    *w++ = '0'; *w++ = '0'; // length
74
    *w++ = '0'; *w++ = '0'; *w++ = '0'; *w++ = '0'; // address
75
    *w++ = '0'; *w++ = '1'; // record type
76
    *w++ = 'F'; *w++ = 'F'; // checksum
77
#else
78
    w = ihex_buffer_byte(w, 0); // length
79
    w = ihex_buffer_byte(w, 0); // address msb
80
    w = ihex_buffer_byte(w, 0); // address lsb
81
    w = ihex_buffer_byte(w, IHEX_END_OF_FILE_RECORD); // record type
82
    w = ihex_buffer_byte(w, (uint8_t)~IHEX_END_OF_FILE_RECORD + 1U); // checksum
83
#endif
84
    w = ihex_buffer_newline(w);
85
    ihex_flush_buffer(ihex, ihex_write_buffer, w);
86
}
87
 
88
static void
89
ihex_write_extended_address (struct ihex_state * const ihex,
90
                             const ihex_segment_t address,
91
                             const uint8_t type) {
92
    char * restrict w = ihex_write_buffer;
93
    uint8_t sum = type + 2U;
94
 
95
    *w++ = IHEX_START;              // :
96
    w = ihex_buffer_byte(w, 2U);    // length
97
    w = ihex_buffer_byte(w, 0);     // 16-bit address msb
98
    w = ihex_buffer_byte(w, 0);     // 16-bit address lsb
99
    w = ihex_buffer_byte(w, type);  // record type
100
    w = ihex_buffer_word(w, address, &sum); // high bytes of address
101
    w = ihex_buffer_byte(w, (uint8_t)~sum + 1U); // checksum
102
    w = ihex_buffer_newline(w);
103
    ihex_flush_buffer(ihex, ihex_write_buffer, w);
104
}
105
 
106
// Write out `ihex->data`
107
//
108
static void
109
ihex_write_data (struct ihex_state * const ihex) {
110
    uint_fast8_t len = ihex->length;
111
    uint8_t sum = len;
112
    char * restrict w = ihex_write_buffer;
113
 
114
    if (!len) {
115
        return;
116
    }
117
 
118
    if (ihex->flags & IHEX_FLAG_ADDRESS_OVERFLOW) {
119
        ihex_write_extended_address(ihex, ADDRESS_HIGH_BYTES(ihex->address),
120
                                    IHEX_EXTENDED_LINEAR_ADDRESS_RECORD);
121
        ihex->flags &= ~IHEX_FLAG_ADDRESS_OVERFLOW;
122
    }
123
 
124
    // :
125
    *w++ = IHEX_START;
126
 
127
    // length
128
    w = ihex_buffer_byte(w, len);
129
    ihex->length = 0;
130
 
131
    // 16-bit address
132
    {
133
        uint_fast16_t addr = ihex->address & 0xFFFFU;
134
        ihex->address += len;
135
        if ((0xFFFFU - addr) < len) {
136
            // signal address overflow (need to write extended address)
137
            ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW;
138
        }
139
        w = ihex_buffer_word(w, addr, &sum);
140
    }
141
 
142
    // record type
143
    w = ihex_buffer_byte(w, IHEX_DATA_RECORD);
144
    //sum += IHEX_DATA_RECORD; // IHEX_DATA_RECORD is zero, so NOP
145
 
146
    // data
147
    {
148
        uint8_t * restrict r = ihex->data;
149
        do {
150
            uint8_t byte = *r++;
151
            sum += byte;
152
            w = ihex_buffer_byte(w, byte);
153
        } while (--len);
154
    }
155
 
156
    // checksum
157
    w = ihex_buffer_byte(w, ~sum + 1U);
158
 
159
    w = ihex_buffer_newline(w);
160
    ihex_flush_buffer(ihex, ihex_write_buffer, w);
161
}
162
 
163
void
164
ihex_write_at_address (struct ihex_state * const ihex, ihex_address_t address) {
165
    if (ihex->length) {
166
        // flush any existing data
167
        ihex_write_data(ihex);
168
    }
169
    if ((ihex->address & ADDRESS_HIGH_MASK) != (address & ADDRESS_HIGH_MASK)) {
170
        ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW;
171
    } else {
172
        ihex->flags &= ~IHEX_FLAG_ADDRESS_OVERFLOW;
173
    }
174
    ihex->address = address;
175
    ihex_set_output_line_length(ihex, ihex->line_length);
176
}
177
 
178
void
179
ihex_set_output_line_length (struct ihex_state * const ihex,
180
                             uint8_t line_length) {
181
#if IHEX_MAX_OUTPUT_LINE_LENGTH < 255
182
    if (line_length > IHEX_MAX_OUTPUT_LINE_LENGTH) {
183
        line_length = IHEX_MAX_OUTPUT_LINE_LENGTH;
184
    } else
185
#endif
186
    if (!line_length) {
187
        line_length = IHEX_DEFAULT_OUTPUT_LINE_LENGTH;
188
    }
189
    ihex->line_length = line_length;
190
}
191
 
192
#ifndef IHEX_DISABLE_SEGMENTS
193
void
194
ihex_write_at_segment (struct ihex_state * const ihex,
195
                       ihex_segment_t segment,
196
                       ihex_address_t address) {
197
    ihex_write_at_address(ihex, address);
198
    if (ihex->segment != segment) {
199
        // clear segment
200
        ihex_write_extended_address(ihex, (ihex->segment = segment),
201
                                    IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD);
202
    }
203
}
204
#endif
205
 
206
void
207
ihex_write_byte (struct ihex_state * const ihex, const int byte) {
208
    if (ihex->line_length <= ihex->length) {
209
        ihex_write_data(ihex);
210
    }
211
    ihex->data[(ihex->length)++] = (uint8_t) byte;
212
}
213
 
214
void
215
ihex_write_bytes (struct ihex_state * restrict const ihex,
216
                  const void * restrict buf,
217
                  ihex_count_t count) {
218
    const uint8_t *r = buf;
219
    while (count > 0) {
220
        if (ihex->line_length > ihex->length) {
221
            uint_fast8_t i = ihex->line_length - ihex->length;
222
            uint8_t *w = ihex->data + ihex->length;
223
            i = ((ihex_count_t) i > count) ? (uint_fast8_t) count : i;
224
            count -= i;
225
            ihex->length += i;
226
            do {
227
                *w++ = *r++;
228
            } while (--i);
229
        } else {
230
            ihex_write_data(ihex);
231
        }
232
    }
233
}
234
 
235
void
236
ihex_end_write (struct ihex_state * const ihex) {
237
    ihex_write_data(ihex); // flush any remaining data
238
    ihex_write_end_of_file(ihex);
239
}
240
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.