structure finished. Copy to memory should work (not tested yet) as well as verification, flash routines yet need to be written
This commit is contained in:
@@ -31,16 +31,37 @@
|
|||||||
#include <s19reader.h>
|
#include <s19reader.h>
|
||||||
|
|
||||||
typedef enum { FALSE, TRUE } bool;
|
typedef enum { FALSE, TRUE } bool;
|
||||||
typedef enum { OK, FAIL } err_t;
|
typedef enum
|
||||||
|
{
|
||||||
|
OK, /* no error */
|
||||||
|
FAIL, /* general error aka "I don't know what went wrong" */
|
||||||
|
FILE_OPEN, /* file open failed */
|
||||||
|
FILE_READ, /* file read failed */
|
||||||
|
SREC_CORRUPT, /* file doesn't seem to contain valid S-records */
|
||||||
|
MEMCPY_FAILED, /* could not copy buffer to destination */
|
||||||
|
CODE_OVERLAPS, /* copying would overwrite ourself */
|
||||||
|
VERIFY_FAILED /* destination does not read as we've written to */
|
||||||
|
} err_t;
|
||||||
|
|
||||||
#define NULL (void *) 0L
|
#define NULL (void *) 0L
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Yes, I know. The following doesn't really look like code should look like...
|
||||||
|
*
|
||||||
|
* I did try to map structures over the S-records with (packed) which didn't work reliably due to gcc _not_ packing them appropiate
|
||||||
|
* and finally ended up with this. Not nice, put paid (and working).
|
||||||
|
*
|
||||||
|
*/
|
||||||
#define SREC_TYPE(a) (a)[0] /* type of record */
|
#define SREC_TYPE(a) (a)[0] /* type of record */
|
||||||
#define SREC_COUNT(a) (a)[1] /* length of valid bytes to follow */
|
#define SREC_COUNT(a) (a)[1] /* length of valid bytes to follow */
|
||||||
#define SREC_ADDR16(a) (256 * (a)[2] + (a)[3]) /* 2 byte address field */
|
#define SREC_ADDR16(a) (256 * (a)[2] + (a)[3]) /* 2 byte address field */
|
||||||
#define SREC_ADDR32(a) (0x1000000 * a[2] + 0x10000 * a[3] + 0x100 * (a)[4] + (a)[5]) /* 4 byte address field */
|
#define SREC_ADDR32(a) (0x1000000 * a[2] + 0x10000 *\
|
||||||
#define SREC_DATA16(a) ((uint8_t *)&((a)[4]))
|
a[3] + 0x100 * (a)[4] + (a)[5]) /* 4 byte address field */
|
||||||
#define SREC_DATA32(a) ((uint8_t *)&((a)[6]))
|
#define SREC_DATA16(a) ((uint8_t *)&((a)[4])) /* address of first byte of data in a record */
|
||||||
#define SREC_CHECKSUM(a) (a)[SREC_COUNT(a) + 2 - 1]
|
#define SREC_DATA32(a) ((uint8_t *)&((a)[6])) /* adress of first byte of a record with 32 bit address field */
|
||||||
|
#define SREC_DATA16_SIZE(a) (SREC_COUNT((a)) - 3) /* length of the data[] array without the checksum field */
|
||||||
|
#define SREC_DATA32_SIZE(a) (SREC_COUNT((a)) - 5) /* length of the data[] array without the checksum field */
|
||||||
|
#define SREC_CHECKSUM(a) (a)[SREC_COUNT(a) + 2 - 1] /* record's checksum (two's complement of the sum of all bytes) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert a single hex character into byte
|
* convert a single hex character into byte
|
||||||
@@ -153,11 +174,28 @@ void line_to_vector(uint8_t *line, uint8_t *vector)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef err_t (*memcpy_callback_t)(uint8_t *dst, uint8_t *src, uint32_t length);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read and parse a Motorola S-record file. Currently only records that the gcc toolchain emits are
|
* read and parse a Motorola S-record file and copy contents to dst. The theory of operation is to read and parse the S-record file
|
||||||
* supported.
|
* and to use the supplied callback routine to copy the buffer to the destination when the supplied buffer gets full.
|
||||||
|
* The memcpy callback can be anything (as long as it conforms parameter-wise) - a basically empty function to just let
|
||||||
|
* read_srecords validate the file, a standard memcpy() to copy file contents to destination RAM or a more sophisticated
|
||||||
|
* routine that does write/erase flash
|
||||||
|
*
|
||||||
|
* FIXME: Currently only records that the gcc toolchain emits are supported.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* IN
|
||||||
|
* filename - the filename that contains the S-records
|
||||||
|
* callback - the memcpy() routine discussed above
|
||||||
|
* OUT
|
||||||
|
* start_address - the execution address of the code as read from the file. Can be used to jump into and execute it
|
||||||
|
* actual_length - the overall length of the binary code read from the file
|
||||||
|
* returns
|
||||||
|
* OK or an err_t error code if anything failed
|
||||||
*/
|
*/
|
||||||
err_t read_srecords(char *filename, uint32_t *start_address, uint32_t *actual_length, uint8_t *buffer, uint32_t buffer_length)
|
err_t read_srecords(char *filename, uint8_t **start_address, uint32_t *actual_length, memcpy_callback_t callback)
|
||||||
{
|
{
|
||||||
FRESULT fres;
|
FRESULT fres;
|
||||||
FIL file;
|
FIL file;
|
||||||
@@ -183,7 +221,6 @@ err_t read_srecords(char *filename, uint32_t *start_address, uint32_t *actual_le
|
|||||||
|
|
||||||
if (line[0] == 'S')
|
if (line[0] == 'S')
|
||||||
{
|
{
|
||||||
//print_record(vector);
|
|
||||||
if (SREC_CHECKSUM(vector) != checksum(vector))
|
if (SREC_CHECKSUM(vector) != checksum(vector))
|
||||||
{
|
{
|
||||||
xprintf("invalid checksum in line %d\r\n", lineno);
|
xprintf("invalid checksum in line %d\r\n", lineno);
|
||||||
@@ -200,6 +237,7 @@ err_t read_srecords(char *filename, uint32_t *start_address, uint32_t *actual_le
|
|||||||
xprintf("S7 or S3 record found before S0: S-records corrupt?\r\n");
|
xprintf("S7 or S3 record found before S0: S-records corrupt?\r\n");
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* four byte address field data record */
|
case 3: /* four byte address field data record */
|
||||||
@@ -208,6 +246,7 @@ err_t read_srecords(char *filename, uint32_t *start_address, uint32_t *actual_le
|
|||||||
xprintf("S3 record found before S0 or after S7: S-records corrupt?\r\n");
|
xprintf("S3 record found before S0 or after S7: S-records corrupt?\r\n");
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
}
|
}
|
||||||
|
ret = callback((uint8_t *) SREC_ADDR32(vector), SREC_DATA32(vector), SREC_COUNT(vector) - 4);
|
||||||
data_records++;
|
data_records++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -244,15 +283,61 @@ err_t read_srecords(char *filename, uint32_t *start_address, uint32_t *actual_le
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this callback just does nothing besides returning OK. Meant to do a dry run over the file to check its integrity
|
||||||
|
*/
|
||||||
|
err_t simulate()
|
||||||
|
{
|
||||||
|
err_t ret = OK;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t memcpy(uint8_t *dst, uint8_t *src, uint32_t length)
|
||||||
|
{
|
||||||
|
uint8_t *end = src + length;
|
||||||
|
|
||||||
|
do {
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
while (src < end);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t flash(uint8_t *dst, uint8_t *src, uint32_t length)
|
||||||
|
{
|
||||||
|
err_t ret = OK;
|
||||||
|
|
||||||
|
/* do the actual flash */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this callback verifies the data against the S-record file contens after a write to destination
|
||||||
|
*/
|
||||||
|
err_t verify(uint8_t *dst, uint8_t *src, uint32_t length)
|
||||||
|
{
|
||||||
|
uint8_t *end = src + length;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*src++ != *dst++)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
while (src < end);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
void flasher_load(char *flasher_filename)
|
void flasher_load(char *flasher_filename)
|
||||||
{
|
{
|
||||||
DRESULT res;
|
DRESULT res;
|
||||||
FRESULT fres;
|
FRESULT fres;
|
||||||
FATFS fs;
|
FATFS fs;
|
||||||
err_t err;
|
err_t err;
|
||||||
uint32_t start_address;
|
uint8_t *start_address;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint8_t buffer[2048];
|
|
||||||
|
|
||||||
xprintf("S-record reader\r\n");
|
xprintf("S-record reader\r\n");
|
||||||
|
|
||||||
@@ -263,10 +348,17 @@ void flasher_load(char *flasher_filename)
|
|||||||
fres = f_mount(0, &fs);
|
fres = f_mount(0, &fs);
|
||||||
if (fres == FR_OK)
|
if (fres == FR_OK)
|
||||||
{
|
{
|
||||||
err = read_srecords(flasher_filename, &start_address, &length, buffer, sizeof(buffer));
|
/* parse and check for inconsistencies */
|
||||||
|
err = read_srecords(flasher_filename, &start_address, &length, simulate);
|
||||||
if (err == OK)
|
if (err == OK)
|
||||||
{
|
{
|
||||||
|
/* next pass: copy to destination */
|
||||||
|
err = read_srecords(flasher_filename, &start_address, &length, memcpy);
|
||||||
|
if (err == OK)
|
||||||
|
{
|
||||||
|
/* next pass: verify */
|
||||||
|
err = read_srecords(flasher_filename, &start_address, &length, verify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user