Skip to content

Commit

Permalink
Merge pull request #55 from Jannibal/master
Browse files Browse the repository at this point in the history
Added functionality to write Motorola S-record formatted files to device
  • Loading branch information
vdudouyt committed Jan 27, 2017
2 parents 7eac1cf + 81cdfef commit 35b4e9f
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,4 +4,5 @@
*.ihx
*.hex
*.exe
*.gch
tags
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -44,7 +44,7 @@ override CFLAGS := $(BASE_CFLAGS) $(LIBUSB_CFLAGS) $(CFLAGS)


BIN =stm8flash
OBJECTS =stlink.o stlinkv2.o main.o byte_utils.o ihex.o stm8.o
OBJECTS =stlink.o stlinkv2.o main.o byte_utils.o ihex.o srec.o stm8.o


.PHONY: all clean install
Expand Down
37 changes: 28 additions & 9 deletions main.c
Expand Up @@ -13,6 +13,7 @@
#include "stlinkv2.h"
#include "stm8.h"
#include "ihex.h"
#include "srec.h"

#ifdef __APPLE__
extern char *optarg;
Expand All @@ -36,8 +37,8 @@ programmer_t pgms[] = {
stlink_swim_read_range,
stlink_swim_write_range,
},
{
"stlinkv2",
{
"stlinkv2",
0x0483,
0x3748,
stlink2_open,
Expand Down Expand Up @@ -142,7 +143,8 @@ const stm8_device_t *get_part(const char *name)
}

int main(int argc, char **argv) {
int start, bytes_count = 0;
unsigned int start;
int bytes_count = 0;
char filename[256];
memset(filename, 0, sizeof(filename));
// Parsing command line
Expand Down Expand Up @@ -256,7 +258,7 @@ int main(int argc, char **argv) {
}

if(memtype != UNKNOWN) {
// Selecting start addr depending on
// Selecting start addr depending on
// specified part and memtype
switch(memtype) {
case RAM:
Expand Down Expand Up @@ -311,6 +313,8 @@ int main(int argc, char **argv) {
spawn_error("Couldn't initialize stlink");
if(!pgm->open(pgm))
spawn_error("Error communicating with MCU. Please check your SWIM connection.");


FILE *f;
if(action == READ) {
fprintf(stderr, "Reading %d bytes at 0x%x... ", bytes_count, start);
Expand All @@ -330,6 +334,16 @@ int main(int argc, char **argv) {
fprintf(stderr, "Reading from Intel hex file ");
ihex_write(f, buf, start, start+bytes_count);
}
else if(is_ext(filename, ".s19") || is_ext(filename, ".s8") || is_ext(filename, ".srec"))
{
printf("Reading from Motorola S-record files are not implemented (yet)\n");
printf("Exiting...\n");
exit(-1);

//TODO Remove the above message and exit, and implement reading from S-record.
fprintf(stderr, "Reading from Motorola S-record file ");
srec_write(f, buf, start, start+bytes_count);
}
else
{
fwrite(buf, 1, bytes_count, f);
Expand Down Expand Up @@ -362,9 +376,9 @@ int main(int argc, char **argv) {
fseek(f, 0L, SEEK_END);
bytes_to_verify = ftell(f);
if(bytes_count_specified) {
bytes_to_verify = bytes_count;
bytes_to_verify = bytes_count;
} else if(bytes_count < bytes_to_verify) {
bytes_to_verify = bytes_count;
bytes_to_verify = bytes_count;
}
fseek(f, 0, SEEK_SET);
fread(buf2, 1, bytes_to_verify, f);
Expand All @@ -378,6 +392,8 @@ int main(int argc, char **argv) {
fprintf(stderr, "FAILED\n");
exit(-1);
}


} else if (action == WRITE) {
if(!(f = fopen(filename, "r")))
spawn_error("Failed to open file");
Expand All @@ -391,14 +407,17 @@ int main(int argc, char **argv) {
if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) {
fprintf(stderr, "Writing Intel hex file ");
bytes_to_write = ihex_read(f, buf, start, start + bytes_count);
} else if (is_ext(filename, ".s19") || is_ext(filename, ".s8") || is_ext(filename, ".srec")) {
fprintf(stderr, "Writing Motorola S-record file ");
bytes_to_write = srec_read(f, buf, start, start + bytes_count);
} else {
fprintf(stderr, "Writing binary file ");
fseek(f, 0L, SEEK_END);
bytes_to_write = ftell(f);
if(bytes_count_specified) {
bytes_to_write = bytes_count;
bytes_to_write = bytes_count;
} else if(bytes_count < bytes_to_write) {
bytes_to_write = bytes_count;
bytes_to_write = bytes_count;
}
fseek(f, 0, SEEK_SET);
fread(buf, 1, bytes_to_write, f);
Expand Down Expand Up @@ -426,7 +445,7 @@ int main(int argc, char **argv) {
for (int i=0; i<bytes_to_write;i++) {
buf[i]=0;
if ((i>0)&&((i&1)==0)) buf[i]=0xff;
}
}
}

/* flashing MCU */
Expand Down
1 change: 0 additions & 1 deletion pgm.h
Expand Up @@ -52,4 +52,3 @@ typedef int (*pgm_read_range_cb)(programmer_t *, unsigned char *, unsigned int,
typedef int (*pgm_write_range_cb)(programmer_t *, unsigned char *, unsigned int, unsigned int);

#endif

122 changes: 122 additions & 0 deletions srec.c
@@ -0,0 +1,122 @@
/* stlink/v2 stm8 memory programming utility
(c) Valentin Dudouyt, 2012 - 2014 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "srec.h"
#include "error.h"
#include "byte_utils.h"

char line[256];

static unsigned char checksum(unsigned char *buf, unsigned int length, int chunk_len, int chunk_addr, int chunk_type) {
int sum = chunk_len + (LO(chunk_addr)) + (HI(chunk_addr)) + chunk_type;
unsigned int i;
for(i = 0; i < length; i++) {
sum += buf[i];
}

int complement = (~sum + 1);
return complement & 0xff;
}


static bool is_data_type(unsigned int chunk_type)
{
return (chunk_type == 0x01 || chunk_type == 0x02 || chunk_type == 0x03);
}



int srec_read(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int end) {
fseek(pFile, 0, SEEK_SET);
unsigned int chunk_len, chunk_addr, chunk_type, i, byte, line_no = 0, greatest_addr = 0;
unsigned int number_of_records = 0;

bool data_record = false;
bool found_S5_rec = false;
unsigned int expected_data_records = 0;
unsigned int data_len = 0;

while(fgets(line, sizeof(line), pFile)) {
data_record = true; //Assume that the read data is a data record. Set to false if not.
line_no++;

// Reading chunk header
if(sscanf(line, "S%01x%02x%04x", &chunk_type, &chunk_len, &chunk_addr) != 3) {
free(buf);
ERROR2("Error while parsing SREC at line %d\n", line_no);
}

if(chunk_type == 0x00 || chunk_type == 0x04) //Header type record or reserved. Skip!
{
continue;
}
else if(chunk_type == 0x05)
{ //This will contain the total expected number of data records. Save for error checking later
found_S5_rec = true;
if (chunk_len != 3) { // Length field must contain a 3 to be a valid S5 record.
ERROR2("Error while parsing S5 Record at line %d\n", line_no);
}
expected_data_records = chunk_addr; //The expected total number of data records is saved in S503<addr> field.
}
else if(is_data_type(chunk_type))
{
data_len = chunk_len - chunk_type - 2; // See https://en.wikipedia.org/wiki/SREC_(file_format)#Record_types
}
else
{
continue;
}

// Reading chunk data
for(i = 6 + 2*chunk_type; i < 2*data_len + 8; i +=2) {
if(sscanf(&(line[i]), "%02x", &byte) != 1) {
free(buf);
ERROR2("Error while parsing SREC at line %d byte %d\n", line_no, i);
}

if(!is_data_type(chunk_type)) {
// The only data records have to be processed
data_record = false;
continue;
}

if((i - 8) / 2 >= chunk_len) {
// Respect chunk_len and do not capture checksum as data
break;
}
if(chunk_addr < start) {
free(buf);
ERROR2("Address %04x is out of range at line %d\n", chunk_addr, line_no);
}
if(chunk_addr + chunk_len > end) {
free(buf);
ERROR2("Address %04x + %d is out of range at line %d\n", chunk_addr, chunk_len, line_no);
}
if(chunk_addr + chunk_len > greatest_addr) {
greatest_addr = chunk_addr + chunk_len;
}
buf[chunk_addr - start + (i - 8) / 2] = byte;
}
if(data_record) { //We found a data record. Remember this.
number_of_records++;
}
}

//Check to see if the number of data records expected is the same as we actually read.
if(found_S5_rec && number_of_records != expected_data_records) {
ERROR2("Error while comparing S5 record (number of data records: %d) with the number actually read: %d\n", expected_data_records, number_of_records);
}

return(greatest_addr - start);

}


void srec_write(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int end) {
ERROR("srec_write is not implemented!");
/* Ducplicate most of the code from ihex.c ihex_write. */
}
8 changes: 8 additions & 0 deletions srec.h
@@ -0,0 +1,8 @@
#ifndef __SREC_H
#define __SREC_H

int srec_read(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int end);

void srec_write(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int end);

#endif

0 comments on commit 35b4e9f

Please sign in to comment.