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_read.c] - Blame information for rev 25

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 alirezamon
/*
2
 * kk_ihex_read.c: A simple library for reading 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_read.h"
12
 
13
#define IHEX_START ':'
14
 
15
#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U)
16
 
17
enum ihex_read_state {
18
    READ_WAIT_FOR_START = 0,
19
    READ_COUNT_HIGH = 1,
20
    READ_COUNT_LOW,
21
    READ_ADDRESS_MSB_HIGH,
22
    READ_ADDRESS_MSB_LOW,
23
    READ_ADDRESS_LSB_HIGH,
24
    READ_ADDRESS_LSB_LOW,
25
    READ_RECORD_TYPE_HIGH,
26
    READ_RECORD_TYPE_LOW,
27
    READ_DATA_HIGH,
28
    READ_DATA_LOW
29
};
30
 
31
#define IHEX_READ_RECORD_TYPE_MASK 0x07
32
#define IHEX_READ_STATE_MASK 0x78
33
#define IHEX_READ_STATE_OFFSET 3
34
 
35
void
36
ihex_begin_read (struct ihex_state * const ihex) {
37
    ihex->address = 0;
38
#ifndef IHEX_DISABLE_SEGMENTS
39
    ihex->segment = 0;
40
#endif
41
    ihex->flags = 0;
42
    ihex->line_length = 0;
43
    ihex->length = 0;
44
}
45
 
46
void
47
ihex_read_at_address (struct ihex_state * const ihex, ihex_address_t address) {
48
    ihex_begin_read(ihex);
49
    ihex->address = address;
50
}
51
 
52
#ifndef IHEX_DISABLE_SEGMENTS
53
void
54
ihex_read_at_segment (struct ihex_state * const ihex, ihex_segment_t segment) {
55
    ihex_begin_read(ihex);
56
    ihex->segment = segment;
57
}
58
#endif
59
 
60
void
61
ihex_end_read (struct ihex_state * const ihex) {
62
    uint_fast8_t type = ihex->flags & IHEX_READ_RECORD_TYPE_MASK;
63
    uint_fast8_t sum;
64
    if ((sum = ihex->length) == 0 && type == IHEX_DATA_RECORD) {
65
        return;
66
    }
67
    {
68
        // compute and validate checksum
69
        const uint8_t * const eptr = ihex->data + sum;
70
        const uint8_t *r = ihex->data;
71
        sum += type + (ihex->address & 0xFFU) + ((ihex->address >> 8) & 0xFFU);
72
        while (r != eptr) {
73
            sum += *r++;
74
        }
75
        sum = (~sum + 1U) ^ *eptr; // *eptr is the received checksum
76
    }
77
    if (ihex_data_read(ihex, type, (uint8_t) sum)) {
78
        if (type == IHEX_EXTENDED_LINEAR_ADDRESS_RECORD) {
79
            ihex->address &= 0xFFFFU;
80
            ihex->address |= (((ihex_address_t) ihex->data[0]) << 24) |
81
                             (((ihex_address_t) ihex->data[1]) << 16);
82
#ifndef IHEX_DISABLE_SEGMENTS
83
        } else if (type == IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD) {
84
            ihex->segment = (ihex_segment_t) ((ihex->data[0] << 8) | ihex->data[1]);
85
#endif
86
        }
87
    }
88
    ihex->length = 0;
89
    ihex->flags = 0;
90
}
91
 
92
void
93
ihex_read_byte (struct ihex_state * const ihex, const char byte) {
94
    uint_fast8_t b = (uint_fast8_t) byte;
95
    uint_fast8_t len = ihex->length;
96
    uint_fast8_t state = (ihex->flags & IHEX_READ_STATE_MASK);
97
    ihex->flags ^= state; // turn off the old state
98
    state >>= IHEX_READ_STATE_OFFSET;
99
 
100
    if (b >= '0' && b <= '9') {
101
        b -= '0';
102
    } else if (b >= 'A' && b <= 'F') {
103
        b -= 'A' - 10;
104
    } else if (b >= 'a' && b <= 'f') {
105
        b -= 'a' - 10;
106
    } else if (b == IHEX_START) {
107
        // sync to a new record at any state
108
        state = READ_COUNT_HIGH;
109
        goto end_read;
110
    } else {
111
        // ignore unknown characters (e.g., extra whitespace)
112
        goto save_read_state;
113
    }
114
 
115
    if (!(++state & 1)) {
116
        // high nybble, store temporarily at end of data:
117
        b <<= 4;
118
        ihex->data[len] = b;
119
    } else {
120
        // low nybble, combine with stored high nybble:
121
        b = (ihex->data[len] |= b);
122
        switch (state >> 1) {
123
        default:
124
            // remain in initial state while waiting for :
125
            return;
126
        case (READ_COUNT_LOW >> 1):
127
            // data length
128
            ihex->line_length = b;
129
#if IHEX_LINE_MAX_LENGTH < 255
130
            if (b > IHEX_LINE_MAX_LENGTH) {
131
                ihex_end_read(ihex);
132
                return;
133
            }
134
#endif
135
            break;
136
        case (READ_ADDRESS_MSB_LOW >> 1):
137
            // high byte of 16-bit address
138
            ihex->address &= ADDRESS_HIGH_MASK; // clear the 16-bit address
139
            ihex->address |= ((ihex_address_t) b) << 8U;
140
            break;
141
        case (READ_ADDRESS_LSB_LOW >> 1):
142
            // low byte of 16-bit address
143
            ihex->address |= (ihex_address_t) b;
144
            break;
145
        case (READ_RECORD_TYPE_LOW >> 1):
146
            // record type
147
            if (b & ~IHEX_READ_RECORD_TYPE_MASK) {
148
                // skip unknown record types silently
149
                return;
150
            }
151
            ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK) | b;
152
            break;
153
        case (READ_DATA_LOW >> 1):
154
            if (len < ihex->line_length) {
155
                // data byte
156
                ihex->length = len + 1;
157
                state = READ_DATA_HIGH;
158
                goto save_read_state;
159
            }
160
            // end of line (last "data" byte is checksum)
161
            state = READ_WAIT_FOR_START;
162
        end_read:
163
            ihex_end_read(ihex);
164
        }
165
    }
166
save_read_state:
167
    ihex->flags |= state << IHEX_READ_STATE_OFFSET;
168
}
169
 
170
void
171
ihex_read_bytes (struct ihex_state * restrict ihex,
172
                 const char * restrict data,
173
                 ihex_count_t count) {
174
    while (count > 0) {
175
        ihex_read_byte(ihex, *data++);
176
        --count;
177
    }
178
}
179
 

powered by: WebSVN 2.1.0

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