This repository has been archived by the owner on Mar 11, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathihex.c
170 lines (138 loc) · 6.07 KB
/
ihex.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
* ihex.c
* Utility functions to create, read, write, and print Intel HEX8 binary records.
*
* Written by Vanya A. Sergeev <[email protected]>
* Version 1.0.5 - February 2011
*
*/
#include "ihex.h"
/* Initializes a new IHexRecord structure that the paramater ihexRecord points to with the passed
* record type, 16-bit integer address, 8-bit data array, and size of 8-bit data array. */
int New_IHexRecord(int type, uint16_t address, const uint8_t *data, int dataLen, IHexRecord *ihexRecord) {
/* Data length size check, assertion of ihexRecord pointer */
if (dataLen < 0 || dataLen > IHEX_MAX_DATA_LEN/2 || ihexRecord == NULL)
return IHEX_ERROR_INVALID_ARGUMENTS;
ihexRecord->type = type;
ihexRecord->address = address;
memcpy(ihexRecord->data, data, (unsigned int)dataLen);
ihexRecord->dataLen = dataLen;
ihexRecord->checksum = Checksum_IHexRecord(ihexRecord);
return IHEX_OK;
}
/* Utility function to read an Intel HEX8 record from a file */
int Read_IHexRecord(IHexRecord *ihexRecord, FILE *in) {
char recordBuff[IHEX_RECORD_BUFF_SIZE];
/* A temporary buffer to hold ASCII hex encoded data, set to the maximum length we would ever need */
char hexBuff[IHEX_ADDRESS_LEN+1];
int dataCount, i;
/* Check our record pointer and file pointer */
if (ihexRecord == NULL || in == NULL)
return IHEX_ERROR_INVALID_ARGUMENTS;
if (fgets(recordBuff, IHEX_RECORD_BUFF_SIZE, in) == NULL) {
/* In case we hit EOF, don't report a file error */
if (feof(in) != 0)
return IHEX_ERROR_EOF;
else
return IHEX_ERROR_FILE;
}
/* Null-terminate the string at the first sign of a \r or \n */
for (i = 0; i < (int)strlen(recordBuff); i++) {
if (recordBuff[i] == '\r' || recordBuff[i] == '\n') {
recordBuff[i] = 0;
break;
}
}
/* Check if we hit a newline */
if (strlen(recordBuff) == 0)
return IHEX_ERROR_NEWLINE;
/* Size check for start code, count, addess, and type fields */
if (strlen(recordBuff) < (unsigned int)(1+IHEX_COUNT_LEN+IHEX_ADDRESS_LEN+IHEX_TYPE_LEN))
return IHEX_ERROR_INVALID_RECORD;
/* Check the for colon start code */
if (recordBuff[IHEX_START_CODE_OFFSET] != IHEX_START_CODE)
return IHEX_ERROR_INVALID_RECORD;
/* Copy the ASCII hex encoding of the count field into hexBuff, convert it to a usable integer */
strncpy(hexBuff, recordBuff+IHEX_COUNT_OFFSET, IHEX_COUNT_LEN);
hexBuff[IHEX_COUNT_LEN] = 0;
dataCount = (int)strtoul(hexBuff, (char **)NULL, 16);
/* Copy the ASCII hex encoding of the address field into hexBuff, convert it to a usable integer */
strncpy(hexBuff, recordBuff+IHEX_ADDRESS_OFFSET, IHEX_ADDRESS_LEN);
hexBuff[IHEX_ADDRESS_LEN] = 0;
ihexRecord->address = (uint16_t)strtoul(hexBuff, (char **)NULL, 16);
/* Copy the ASCII hex encoding of the address field into hexBuff, convert it to a usable integer */
strncpy(hexBuff, recordBuff+IHEX_TYPE_OFFSET, IHEX_TYPE_LEN);
hexBuff[IHEX_TYPE_LEN] = 0;
ihexRecord->type = (int)strtoul(hexBuff, (char **)NULL, 16);
/* Size check for start code, count, address, type, data and checksum fields */
if (strlen(recordBuff) < (unsigned int)(1+IHEX_COUNT_LEN+IHEX_ADDRESS_LEN+IHEX_TYPE_LEN+dataCount*2+IHEX_CHECKSUM_LEN))
return IHEX_ERROR_INVALID_RECORD;
/* Loop through each ASCII hex byte of the data field, pull it out into hexBuff,
* convert it and store the result in the data buffer of the Intel HEX8 record */
for (i = 0; i < dataCount; i++) {
/* Times two i because every byte is represented by two ASCII hex characters */
strncpy(hexBuff, recordBuff+IHEX_DATA_OFFSET+2*i, IHEX_ASCII_HEX_BYTE_LEN);
hexBuff[IHEX_ASCII_HEX_BYTE_LEN] = 0;
ihexRecord->data[i] = (uint8_t)strtoul(hexBuff, (char **)NULL, 16);
}
ihexRecord->dataLen = dataCount;
/* Copy the ASCII hex encoding of the checksum field into hexBuff, convert it to a usable integer */
strncpy(hexBuff, recordBuff+IHEX_DATA_OFFSET+dataCount*2, IHEX_CHECKSUM_LEN);
hexBuff[IHEX_CHECKSUM_LEN] = 0;
ihexRecord->checksum = (uint8_t)strtoul(hexBuff, (char **)NULL, 16);
if (ihexRecord->checksum != Checksum_IHexRecord(ihexRecord))
return IHEX_ERROR_INVALID_RECORD;
return IHEX_OK;
}
/* Utility function to write an Intel HEX8 record to a file */
int Write_IHexRecord(const IHexRecord *ihexRecord, FILE *out) {
int i;
/* Check our record pointer and file pointer */
if (ihexRecord == NULL || out == NULL)
return IHEX_ERROR_INVALID_ARGUMENTS;
/* Check that the data length is in range */
if (ihexRecord->dataLen > IHEX_MAX_DATA_LEN/2)
return IHEX_ERROR_INVALID_RECORD;
/* Write the start code, data count, address, and type fields */
if (fprintf(out, "%c%2.2X%2.4X%2.2X", IHEX_START_CODE, ihexRecord->dataLen, ihexRecord->address, ihexRecord->type) < 0)
return IHEX_ERROR_FILE;
/* Write the data bytes */
for (i = 0; i < ihexRecord->dataLen; i++) {
if (fprintf(out, "%2.2X", ihexRecord->data[i]) < 0)
return IHEX_ERROR_FILE;
}
/* Calculate and write the checksum field */
if (fprintf(out, "%2.2X\r\n", Checksum_IHexRecord(ihexRecord)) < 0)
return IHEX_ERROR_FILE;
return IHEX_OK;
}
/* Utility function to print the information stored in an Intel HEX8 record */
void Print_IHexRecord(const IHexRecord *ihexRecord) {
int i;
printf("Intel HEX8 Record Type: \t%d\n", ihexRecord->type);
printf("Intel HEX8 Record Address: \t0x%2.4X\n", ihexRecord->address);
printf("Intel HEX8 Record Data: \t{");
for (i = 0; i < ihexRecord->dataLen; i++) {
if (i+1 < ihexRecord->dataLen)
printf("0x%02X, ", ihexRecord->data[i]);
else
printf("0x%02X", ihexRecord->data[i]);
}
printf("}\n");
printf("Intel HEX8 Record Checksum: \t0x%2.2X\n", ihexRecord->checksum);
}
/* Utility function to calculate the checksum of an Intel HEX8 record */
uint8_t Checksum_IHexRecord(const IHexRecord *ihexRecord) {
uint8_t checksum;
int i;
/* Add the data count, type, address, and data bytes together */
checksum = (uint8_t)ihexRecord->dataLen;
checksum += (uint8_t)ihexRecord->type;
checksum += (uint8_t)ihexRecord->address;
checksum += (uint8_t)((ihexRecord->address & 0xFF00)>>8);
for (i = 0; i < ihexRecord->dataLen; i++)
checksum += (uint8_t)ihexRecord->data[i];
/* Two's complement on checksum */
checksum = ~checksum + 1;
return checksum;
}