Skip to content

Commit cc5a237

Browse files
authored
Merge pull request #68
added reader for Motorola SREC format.
2 parents b722f96 + af6e831 commit cc5a237

2 files changed

Lines changed: 213 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* Motorola SREC Reader Header */
2+
3+
#ifndef VMCU_SREC_H
4+
#define VMCU_SREC_H
5+
6+
// C Headers
7+
#include <inttypes.h>
8+
9+
typedef struct vmcu_binary_buffer vmcu_binary_buffer_t;
10+
11+
extern vmcu_binary_buffer_t * vmcu_read_srec(const char *srec_file, uint32_t *size);
12+
13+
#endif

engine/src/reader/format/srec.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/* Intel Hex Reader Header */
2+
3+
// C Headers
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <stdbool.h>
8+
9+
// Project Headers (engine, readers)
10+
#include "engine/include/reader/format/srec.h"
11+
#include "engine/include/reader/binary_buffer.h"
12+
13+
// Project Headers (engine utilities)
14+
#include "engine/include/misc/filemanip.h"
15+
#include "engine/include/misc/stringmanip.h"
16+
17+
#define RECORD_MAX_LENGTH_BYTES (1+1+2+255)
18+
#define SREC_MAX_BYTE_COUNT 249
19+
20+
#define ERR_RECORD_NOT_SUPPORTED -2
21+
#define ERR_FATAL -1
22+
23+
/* Forward Declaration of static Members */
24+
25+
typedef enum srec_record_type {
26+
27+
S0_HEADER = 0,
28+
S1_DATA,
29+
S2_DATA,
30+
S3_DATA,
31+
S4_RESERVED,
32+
S5_COUNT,
33+
S6_COUNT,
34+
S7_START_ADDR,
35+
S8_START_ADDR,
36+
S9_START_ADDR
37+
38+
} srec_record_type_t;
39+
40+
typedef struct srec_properties {
41+
42+
srec_record_type_t record_type;
43+
uint32_t address;
44+
45+
uint8_t data_count;
46+
uint8_t data[SREC_MAX_BYTE_COUNT];
47+
48+
} srec_properties_t;
49+
50+
/* --- static --- */
51+
static uint32_t estimate_buffer_size(const char* srec_file);
52+
53+
static int8_t read_srec_line(const char* line, vmcu_binary_buffer_t* buffer, uint32_t* size);
54+
55+
static int8_t get_srec_properties(const char* line, srec_properties_t* prop);
56+
/* --- Extern --- */
57+
58+
vmcu_binary_buffer_t * vmcu_read_srec(const char *srec_file, uint32_t *size) {
59+
60+
FILE* file = fopen(srec_file, "r");
61+
62+
if(file == NULL)
63+
return NULL;
64+
65+
uint32_t n = estimate_buffer_size(srec_file);
66+
67+
vmcu_binary_buffer_t* buffer = malloc(sizeof(vmcu_binary_buffer_t)*n);
68+
69+
char* line = NULL;
70+
size_t len;
71+
72+
while(getline(&line, &len, file) != -1){
73+
74+
int8_t status = read_srec_line(line, buffer, size);
75+
76+
if(status == ERR_FATAL){
77+
78+
*size = 0;
79+
80+
free(line);
81+
fclose(file);
82+
83+
return NULL;
84+
}
85+
}
86+
87+
free(line);
88+
fclose(file);
89+
return buffer;
90+
}
91+
92+
static uint32_t estimate_buffer_size(const char* srec_file){
93+
94+
FILE* file = fopen(srec_file, "r");
95+
96+
long bytes = vmcu_fbytes(srec_file);
97+
98+
fclose(file);
99+
100+
return (bytes / 4);
101+
}
102+
103+
static int8_t read_srec_line(const char* line, vmcu_binary_buffer_t* buffer, uint32_t* size){
104+
105+
srec_properties_t prop;
106+
107+
int8_t status = get_srec_properties(line, &prop);
108+
109+
if(status < 0)
110+
return status;
111+
112+
for(uint32_t i = 0; i < (prop.data_count / 2); i++) {
113+
114+
uint16_t srec_bytes = (prop.data[i*2 + 0] << 8)| prop.data[i*2 + 1];
115+
116+
buffer[*size] = (vmcu_binary_buffer_t) {
117+
118+
.bytes = srec_bytes,
119+
.addr = (prop.address/2) + i
120+
};
121+
122+
*size += 1;
123+
}
124+
125+
return 0;
126+
}
127+
128+
static int8_t get_srec_properties(const char* line, srec_properties_t* prop){
129+
130+
uint32_t len = strlen(line);
131+
132+
if(len < 10)
133+
return ERR_FATAL;
134+
135+
if(line[0] != 'S')
136+
return ERR_FATAL;
137+
138+
prop->record_type = line[1] - '0';
139+
140+
char byte_count_str[3] = { line[2], line[3], '\0' };
141+
142+
uint8_t byte_count = vmcu_htoi(byte_count_str);
143+
144+
if(byte_count > SREC_MAX_BYTE_COUNT)
145+
return ERR_FATAL;
146+
147+
char addr_str[9] = {};
148+
memset(addr_str, 0, 9);
149+
150+
uint32_t index_data;
151+
uint8_t address_nbytes;
152+
153+
switch (prop->record_type) {
154+
case S0_HEADER:
155+
return ERR_RECORD_NOT_SUPPORTED;
156+
157+
case S1_DATA:
158+
memcpy(addr_str, line+4, 4);
159+
address_nbytes = 2;
160+
index_data = 8;
161+
break;
162+
case S2_DATA:
163+
memcpy(addr_str, line+4, 6);
164+
address_nbytes = 3;
165+
index_data = 10;
166+
break;
167+
case S3_DATA:
168+
memcpy(addr_str, line+4, 8);
169+
address_nbytes = 4;
170+
index_data = 12;
171+
break;
172+
173+
case S4_RESERVED:
174+
return ERR_FATAL;
175+
176+
case S5_COUNT:
177+
case S6_COUNT:
178+
case S7_START_ADDR:
179+
case S8_START_ADDR:
180+
case S9_START_ADDR:
181+
return ERR_RECORD_NOT_SUPPORTED;
182+
}
183+
184+
prop->data_count = byte_count - (address_nbytes + 1);
185+
186+
prop->address = vmcu_htoi(addr_str);
187+
188+
for(uint32_t i = 0; i < prop->data_count; i++){
189+
190+
char data_str[3] = {
191+
line[index_data],
192+
line[index_data + 1],
193+
'\0'
194+
};
195+
index_data += 2;
196+
prop->data[i] = vmcu_htoi(data_str);
197+
}
198+
199+
return 0;
200+
}

0 commit comments

Comments
 (0)