Add files via upload

initial upload
This commit is contained in:
Markus
2017-12-25 10:17:23 +01:00
committed by GitHub
parent 7b95647613
commit c6de494f33
100 changed files with 66174 additions and 0 deletions

383
flash/flash.c Normal file
View File

@@ -0,0 +1,383 @@
#include <stddef.h>
#include "bas_types.h"
#if defined(MACHINE_FIREBEE)
#include "firebee.h"
#elif defined(MACHINE_M5484LITE)
#include "m5484l.h"
#endif /* MACHINE_FIREBEE */
#define AMD_FLASH_BUS_SHIFT 1
#define AMD_FLASH_CELL volatile uint16_t
#define AMD_FLASH_CELL_BYTES 2
#define AMD_FLASH_CELL_MASK 0x1
#define AMD_FLASH_CMD_DATA(x) ((uint16_t) x)
struct amd_flash_sector_info
{
uint32_t size; /* sector size in bytes */
uint32_t offset; /* offset from base of device */
};
/*
* AM29LV640D flash layout (bottom boot as used in the Firebee )
*/
static struct amd_flash_sector_info sector[] =
{
{ 8 * 1024, 0x00000000 }, /* SA0 */
{ 8 * 1024, 0x00008000 }, /* SA1 */
{ 8 * 1024, 0x00010000 }, /* SA2 */
{ 8 * 1024, 0x00018000 }, /* SA3 */
{ 8 * 1024, 0x00020000 }, /* SA4 */
{ 8 * 1024, 0x00028000 }, /* SA5 */
{ 8 * 1024, 0x00030000 }, /* SA6 */
{ 8 * 1024, 0x00038000 }, /* SA7 */
{ 8 * 1024, 0x00040000 }, /* SA8 */
{ 64 * 1024, 0x00048000 }, /* SA9 */
{ 64 * 1024, 0x00050000 }, /* SA10 */
{ 64 * 1024, 0x00058000 }, /* SA11 */
{ 64 * 1024, 0x00060000 }, /* SA12 */
{ 64 * 1024, 0x00068000 }, /* SA13 */
{ 64 * 1024, 0x00070000 }, /* SA14 */
{ 64 * 1024, 0x00078000 }, /* SA15 */
{ 64 * 1024, 0x00080000 }, /* SA16 */
{ 64 * 1024, 0x00088000 }, /* SA17 */
{ 64 * 1024, 0x00090000 }, /* SA18 */
{ 64 * 1024, 0x00098000 }, /* SA19 */
{ 64 * 1024, 0x000a0000 }, /* SA20 */
{ 64 * 1024, 0x000a8000 }, /* SA21 */
{ 64 * 1024, 0x000b0000 }, /* SA22 */
{ 64 * 1024, 0x000b8000 }, /* SA23 */
{ 64 * 1024, 0x000c0000 }, /* SA24 */
{ 64 * 1024, 0x000c8000 }, /* SA25 */
{ 64 * 1024, 0x000d0000 }, /* SA26 */
{ 64 * 1024, 0x000d8000 }, /* SA27 */
{ 64 * 1024, 0x000e0000 }, /* SA28 */
{ 64 * 1024, 0x000e8000 }, /* SA29 */
{ 64 * 1024, 0x000f0000 }, /* SA30 */
{ 64 * 1024, 0x000f8000 }, /* SA31 */
{ 64 * 1024, 0x00100000 }, /* SA32 */
{ 64 * 1024, 0x00108000 }, /* SA32 */
{ 64 * 1024, 0x00110000 }, /* SA34 */
{ 64 * 1024, 0x00118000 }, /* SA35 */
{ 64 * 1024, 0x00120000 }, /* SA36 */
{ 64 * 1024, 0x00128000 }, /* SA37 */
{ 64 * 1024, 0x00130000 }, /* SA38 */
{ 64 * 1024, 0x00138000 }, /* SA39 */
{ 64 * 1024, 0x00140000 }, /* SA40 */
{ 64 * 1024, 0x00148000 }, /* SA41 */
{ 64 * 1024, 0x00150000 }, /* SA42 */
{ 64 * 1024, 0x00158000 }, /* SA43 */
{ 64 * 1024, 0x00160000 }, /* SA44 */
{ 64 * 1024, 0x00168000 }, /* SA45 */
{ 64 * 1024, 0x00170000 }, /* SA46 */
{ 64 * 1024, 0x00178000 }, /* SA47 */
{ 64 * 1024, 0x00180000 }, /* SA48 */
{ 64 * 1024, 0x00188000 }, /* SA49 */
{ 64 * 1024, 0x00190000 }, /* SA50 */
{ 64 * 1024, 0x00198000 }, /* SA51 */
{ 64 * 1024, 0x001a0000 }, /* SA52 */
{ 64 * 1024, 0x001a8000 }, /* SA53 */
{ 64 * 1024, 0x001b0000 }, /* SA54 */
{ 64 * 1024, 0x001b8000 }, /* SA55 */
{ 64 * 1024, 0x001c0000 }, /* SA56 */
{ 64 * 1024, 0x001c8000 }, /* SA57 */
{ 64 * 1024, 0x001d0000 }, /* SA58 */
{ 64 * 1024, 0x001d8000 }, /* SA59 */
{ 64 * 1024, 0x001e0000 }, /* SA60 */
{ 64 * 1024, 0x001e8000 }, /* SA61 */
{ 64 * 1024, 0x001f0000 }, /* SA62 */
{ 64 * 1024, 0x001f8000 }, /* SA63 */
{ 64 * 1024, 0x00200000 }, /* SA64 */
{ 64 * 1024, 0x00208000 }, /* SA65 */
{ 64 * 1024, 0x00210000 }, /* SA66 */
{ 64 * 1024, 0x00218000 }, /* SA67 */
{ 64 * 1024, 0x00220000 }, /* SA68 */
{ 64 * 1024, 0x00228000 }, /* SA69 */
{ 64 * 1024, 0x00230000 }, /* SA70 */
{ 64 * 1024, 0x00238000 }, /* SA71 */
{ 64 * 1024, 0x00240000 }, /* SA72 */
{ 64 * 1024, 0x00248000 }, /* SA73 */
{ 64 * 1024, 0x00250000 }, /* SA74 */
{ 64 * 1024, 0x00258000 }, /* SA75 */
{ 64 * 1024, 0x00260000 }, /* SA76 */
{ 64 * 1024, 0x00268000 }, /* SA77 */
{ 64 * 1024, 0x00270000 }, /* SA78 */
{ 64 * 1024, 0x00278000 }, /* SA79 */
{ 64 * 1024, 0x00280000 }, /* SA80 */
{ 64 * 1024, 0x00288000 }, /* SA81 */
{ 64 * 1024, 0x00290000 }, /* SA82 */
{ 64 * 1024, 0x00298000 }, /* SA83 */
{ 64 * 1024, 0x002a0000 }, /* SA84 */
{ 64 * 1024, 0x002a8000 }, /* SA85 */
{ 64 * 1024, 0x002b0000 }, /* SA86 */
{ 64 * 1024, 0x002b8000 }, /* SA87 */
{ 64 * 1024, 0x002c0000 }, /* SA88 */
{ 64 * 1024, 0x002c8000 }, /* SA89 */
{ 64 * 1024, 0x002d0000 }, /* SA90 */
{ 64 * 1024, 0x002d8000 }, /* SA91 */
{ 64 * 1024, 0x002e0000 }, /* SA92 */
{ 64 * 1024, 0x002e8000 }, /* SA93 */
{ 64 * 1024, 0x002f0000 }, /* SA94 */
{ 64 * 1024, 0x002f8000 }, /* SA95 */
{ 64 * 1024, 0x00300000 }, /* SA96 */
{ 64 * 1024, 0x00308000 }, /* SA97 */
{ 64 * 1024, 0x00310000 }, /* SA98 */
{ 64 * 1024, 0x00318000 }, /* SA99 */
{ 64 * 1024, 0x00320000 }, /* SA100 */
{ 64 * 1024, 0x00328000 }, /* SA101 */
{ 64 * 1024, 0x00330000 }, /* SA102 */
{ 64 * 1024, 0x00338000 }, /* SA103 */
{ 64 * 1024, 0x00340000 }, /* SA104 */
{ 64 * 1024, 0x00348000 }, /* SA105 */
{ 64 * 1024, 0x00350000 }, /* SA106 */
{ 64 * 1024, 0x00358000 }, /* SA107 */
{ 64 * 1024, 0x00360000 }, /* SA108 */
{ 64 * 1024, 0x00368000 }, /* SA109 */
{ 64 * 1024, 0x00370000 }, /* SA110 */
{ 64 * 1024, 0x00378000 }, /* SA111 */
{ 64 * 1024, 0x00380000 }, /* SA112 */
{ 64 * 1024, 0x00388000 }, /* SA113 */
{ 64 * 1024, 0x00390000 }, /* SA114 */
{ 64 * 1024, 0x00398000 }, /* SA115 */
{ 64 * 1024, 0x003a0000 }, /* SA116 */
{ 64 * 1024, 0x003a8000 }, /* SA117 */
{ 64 * 1024, 0x003b0000 }, /* SA118 */
{ 64 * 1024, 0x003b8000 }, /* SA119 */
{ 64 * 1024, 0x003c0000 }, /* SA120 */
{ 64 * 1024, 0x003c8000 }, /* SA121 */
{ 64 * 1024, 0x003d0000 }, /* SA122 */
{ 64 * 1024, 0x003d8000 }, /* SA123 */
{ 64 * 1024, 0x003e0000 }, /* SA124 */
{ 64 * 1024, 0x003e8000 }, /* SA125 */
{ 64 * 1024, 0x003f0000 }, /* SA126 */
{ 64 * 1024, 0x003f8000 }, /* SA127 */
};
static const int AMD_FLASH_SECTORS = sizeof(sector) / sizeof(struct amd_flash_sector_info);
#define SOFFSET(n) (sector[n].offset)
#define SADDR(n) (SOFFSET(n) >> AMD_FLASH_BUS_SHIFT)
#define SSIZE(n) (sector[n].size)
#define AMD_FLASH_DEVICES 1
static AMD_FLASH_CELL *pFlash;
typedef struct romram
{
uint32_t flash_address;
uint32_t ram_address;
char *name;
} ROMRAM;
static const struct romram flash_areas[] =
{
{ 0xe0000000, 0x00e00000, "BaS" }, /* BaS */
{ 0xe0600000, 0x00e00000, "EmuTOS" }, /* EmuTOS */
{ 0xe0400000, 0x00e00000, "FireTOS" }, /* FireTOS */
{ 0xe0700000, 0x00e00000, "FPGA" }, /* FPGA config */
};
static const int num_flash_areas = sizeof(flash_areas) / sizeof(struct romram);
#define FLASH_ADDRESS BOOTFLASH_BASE_ADDRESS
/*
* erase a flash sector
*
* sector_num is the index into the sector table above.
*
* FIXME: need to disable data cache to ensure proper operation
*/
void amd_flash_sector_erase(int n)
{
volatile AMD_FLASH_CELL status;
(void) num_flash_areas; /* to make compiler happy */
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xAA);
pFlash[0x2AA] = AMD_FLASH_CMD_DATA(0x55);
pFlash[0x555] = AMD_FLASH_CMD_DATA(0x80);
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xAA);
pFlash[0x2AA] = AMD_FLASH_CMD_DATA(0x55);
pFlash[SADDR(n)] = AMD_FLASH_CMD_DATA(0x30);
do
status = pFlash[SADDR(n)];
while ((status & AMD_FLASH_CMD_DATA(0x80)) != AMD_FLASH_CMD_DATA(0x80));
/*
* Place device in read mode
*/
pFlash[0] = AMD_FLASH_CMD_DATA(0xAA);
pFlash[0] = AMD_FLASH_CMD_DATA(0x55);
pFlash[0] = AMD_FLASH_CMD_DATA(0xF0);
}
int amd_flash_erase(void *start, int bytes, void (*putchar)(int))
{
int i, ebytes = 0;
if (bytes == 0)
return 0;
for (i = 0; i < AMD_FLASH_SECTORS; i++)
{
if (start >= (void *)((void *) pFlash + SOFFSET(i)) &&
start <= (void *)((void *) pFlash + SOFFSET(i) + (SSIZE(i) - 1)))
{
break;
}
}
while (ebytes < bytes)
{
if (putchar != NULL)
{
putchar('.');
}
amd_flash_sector_erase(i);
ebytes += SSIZE(i);
i++;
}
if (putchar != NULL)
{
putchar(10); /* LF */
putchar(13); /* CR */
}
return ebytes;
}
void amd_flash_program_cell(AMD_FLASH_CELL *dst, AMD_FLASH_CELL data)
{
volatile AMD_FLASH_CELL status;
int retry;
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xAA);
pFlash[0x2AA] = AMD_FLASH_CMD_DATA(0x55);
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xA0);
*dst = data;
/*
* Wait for program operation to finish
* (Data# Polling Algorithm)
*/
retry = 0;
while (1)
{
status = *dst;
if ((status & AMD_FLASH_CMD_DATA(0x80)) ==
(data & AMD_FLASH_CMD_DATA(0x80)))
{
break;
}
if (status & AMD_FLASH_CMD_DATA(0x20))
{
status = *dst;
if ((status & AMD_FLASH_CMD_DATA(0x80)) ==
(data & AMD_FLASH_CMD_DATA(0x80)))
{
break;
}
if (++retry > 1024)
{
break;
}
}
}
}
int amd_flash_program(void *dest, void *source, int bytes, int erase, void (*func)(void), void (*putchar)(int))
{
AMD_FLASH_CELL *src;
AMD_FLASH_CELL *dst;
int hashi = 1;
int hashj = 0;
char hash[5];
hash[0] = 8; /* Backspace */
hash[1] = 124;/* "|" */
hash[2] = 47; /* "/" */
hash[3] = 45; /* "-" */
hash[4] = 92; /* "\" */
src = (AMD_FLASH_CELL *)source;
dst = (AMD_FLASH_CELL *)dest;
/*
* Place device in read mode
*/
pFlash[0] = AMD_FLASH_CMD_DATA(0xAA);
pFlash[0] = AMD_FLASH_CMD_DATA(0x55);
pFlash[0] = AMD_FLASH_CMD_DATA(0xF0);
/*
* Erase device if necessary
*/
if (erase)
{
amd_flash_erase(dest, bytes, putchar);
}
/*
* Program device
*/
while (bytes > 0)
{
amd_flash_program_cell(dst, *src);
/* Verify Write */
if (*dst == *src)
{
bytes -= AMD_FLASH_CELL_BYTES;
*dst++, *src++;
if ((putchar != NULL))
{
/* Hash marks to indicate progress */
if (hashj == 0x1000)
{
hashj = -1;
putchar(hash[0]);
putchar(hash[hashi]);
hashi++;
if (hashi == 5)
{
hashi = 1;
}
}
hashj++;
}
}
else
break;
}
/*
* Place device in read mode
*/
pFlash[0] = AMD_FLASH_CMD_DATA(0xAA);
pFlash[0] = AMD_FLASH_CMD_DATA(0x55);
pFlash[0] = AMD_FLASH_CMD_DATA(0xF0);
if (putchar != NULL)
{
putchar(hash[0]);
}
/*
* If a function was passed in, call it now
*/
if ((func != NULL))
{
func();
}
return ((int)src - (int)source);
}

449
flash/s19reader.c Normal file
View File

@@ -0,0 +1,449 @@
/*
* s19reader.c
*
* Created on: 17.12.2012
* Author: mfro
* The ACP Firebee project
*
* This file is part of BaS_gcc.
*
* BaS_gcc is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* BaS_gcc is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012 M. Froeschle
*/
#include <bas_types.h>
#include "bas_printf.h"
#include "bas_string.h"
#include "sd_card.h"
#include "diskio.h"
#include "ff.h"
#include "s19reader.h"
#include "dma.h"
#include "cache.h"
// #define DEBUG
#include "debug.h"
/*
* 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_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_ADDR24(a) (0x10000 * (a)[2] + 0x100 * \
(a)[3] + (a)[4]) /* 3 byte address field */
#define SREC_ADDR32(a) (0x1000000 * a[2] + 0x10000 * \
(a)[3] + 0x100 * (a)[4] + (a)[5]) /* 4 byte address field */
#define SREC_DATA16(a) ((uint8_t *)&((a)[4])) /* address of first byte of data in a record */
#define SREC_DATA24(a) ((uint8_t *)&((a)[5])) /* address of first data byte in 24 bit record */
#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_DATA24_SIZE(a) (SREC_COUNT((a)) - 4) /* 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
*/
static uint8_t nibble_to_byte(uint8_t nibble)
{
if ((nibble >= '0') && (nibble <= '9'))
return nibble - '0';
else if ((nibble >= 'A' && nibble <= 'F'))
return 10 + nibble - 'A';
else if ((nibble >= 'a' && nibble <= 'f'))
return 10 + nibble - 'a';
return 0;
}
/*
* convert two hex characters into byte
*/
static uint8_t hex_to_byte(uint8_t hex[2])
{
return 16 * (nibble_to_byte(hex[0])) + (nibble_to_byte(hex[1]));
}
#ifdef _NOT_USED_
/*
* convert four hex characters into a 16 bit word
*/
static uint16_t hex_to_word(uint8_t hex[4])
{
return 256 * hex_to_byte(&hex[0]) + hex_to_byte(&hex[2]);
}
/*
* convert eight hex characters into a 32 bit word
*/
static uint32_t hex_to_long(uint8_t hex[8])
{
return 65536 * hex_to_word(&hex[0]) + hex_to_word(&hex[4]);
}
#endif /* _NOT_USED_ */
/*
* compute the record checksum
*
* it consists of the one's complement of the byte sum of the data from the count field until the end
*/
static uint8_t checksum(uint8_t arr[])
{
int i;
uint8_t cs = SREC_COUNT(arr);
for (i = 0; i < SREC_COUNT(arr) - 1; i++)
{
cs += arr[i + 2];
}
return ~cs;
}
#ifdef _NOT_USED_
void print_record(uint8_t *arr)
{
switch (SREC_TYPE(arr))
{
case 0:
{
xprintf("type 0x%x ", SREC_TYPE(arr));
xprintf("count 0x%x ", SREC_COUNT(arr));
xprintf("addr 0x%x ", SREC_ADDR16(arr));
xprintf("module %11.11s ", SREC_DATA16(arr));
xprintf("chk 0x%x 0x%x\r\n", SREC_CHECKSUM(arr), checksum(arr));
}
break;
case 3:
case 7:
{
xprintf("type 0x%x ", SREC_TYPE(arr));
xprintf("count 0x%x ", SREC_COUNT(arr));
xprintf("addr 0x%x ", SREC_ADDR32(arr));
xprintf("data %02x,%02x,%02x,%02x,... ",
SREC_DATA32(arr)[0], SREC_DATA32(arr)[1], SREC_DATA32(arr)[3], SREC_DATA32(arr)[4]);
xprintf("chk 0x%x 0x%x\r\n", SREC_CHECKSUM(arr), checksum(arr));
}
break;
default:
xprintf("unsupported report type %d in print_record\r\n", arr[0]);
break;
}
}
#endif /* _NOT_USED_ */
/*
* convert an S-record line into its corresponding byte vector (ASCII->binary)
*/
static void line_to_vector(uint8_t *buff, uint8_t *vector)
{
int i;
int length;
uint8_t *vp = vector;
length = hex_to_byte(buff + 2);
buff++;
*vp++ = nibble_to_byte(*buff); /* record type. Only one single nibble */
buff++;
for (i = 0; i <= length; i++)
{
*vp++ = hex_to_byte(buff);
buff += 2;
}
}
/*
* 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
* and to use the supplied callback routine to copy the buffer to the destination once the S-record line is converted.
* 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, void **start_address, uint32_t *actual_length, memcpy_callback_t callback)
{
FRESULT fres;
FIL file;
err_t ret = OK;
uint32_t length = 0;
if ((fres = f_open(&file, filename, FA_READ) == FR_OK))
{
uint8_t line[255];
int lineno = 0;
int data_records = 0;
bool found_block_header = false;
bool found_block_end = false;
bool found_block_data = false;
*actual_length = 0;
while (ret == OK && (uint8_t *) f_gets((char *) line, sizeof(line), &file) != NULL)
{
lineno++;
uint8_t vector[80];
memset(vector, 0, sizeof(vector));
line_to_vector(line, vector); /* vector now contains the decoded contents of line, from line[1] on */
if (line[0] == 'S')
{
if (SREC_CHECKSUM(vector) != checksum(vector))
{
xprintf("invalid checksum 0x%x (should be 0x%x) in line %d\r\n",
SREC_CHECKSUM(vector), checksum(vector), lineno);
ret = FAIL;
}
switch (vector[0])
{
case 0: /* block header */
found_block_header = true;
if (found_block_data || found_block_end)
{
xprintf("S7 or S3 record found before S0: S-records corrupt?\r\n");
ret = FAIL;
}
break;
case 2: /* three byte address field data record */
if (!found_block_header || found_block_end)
{
xprintf("S2 record found before S0 or after S7: S-records corrupt?\r\n");
ret = FAIL;
}
ret = callback((uint8_t *) SREC_ADDR24(vector), SREC_DATA24(vector), SREC_DATA24_SIZE(vector));
length += SREC_DATA24_SIZE(vector);
data_records++;
break;
case 3: /* four byte address field data record */
if (!found_block_header || found_block_end)
{
xprintf("S3 record found before S0 or after S7: S-records corrupt?\r\n");
ret = FAIL;
}
length += SREC_DATA32_SIZE(vector);
ret = callback((uint8_t *) SREC_ADDR32(vector), SREC_DATA32(vector), SREC_DATA32_SIZE(vector));
data_records++;
break;
case 7: /* four byte address field end record */
if (!found_block_header || found_block_end)
{
xprintf("S7 record found before S0 or after S7: S-records corrupt?\r\n");
}
else
{
// xprintf("S7 record (end) found after %d valid data blocks\r\n", data_records);
*start_address = (void *) SREC_ADDR32(vector);
xprintf("%d blocks read. Found start address %p\r\n", data_records, *start_address);
}
break;
case 8: /* three byte address field end record */
if (!found_block_header || found_block_end)
{
xprintf("S8 record found before S0 or after S8: S-records corrupt?\r\n");
}
else
{
// xprintf("S8 record (end) found after %d valid data blocks\r\n", data_records);
*start_address = (void *) SREC_ADDR24(vector);
}
break;
default:
xprintf("unsupported record type (%d) found in line %d\r\n", vector[0], lineno);
xprintf("offending line: \r\n");
xprintf("%s\r\n", line);
ret = FAIL;
break;
}
}
else
{
xprintf("illegal character ('%c') found on line %d: S-records corrupt?\r\n", line[0], lineno);
ret = FAIL;
break;
}
}
f_close(&file);
}
else
{
xprintf("could not open file %s\r\n", filename);
ret = FILE_OPEN;
}
*actual_length = length;
return ret;
}
/*
* this callback just does nothing besides returning OK. Meant to do a dry run over the file to check its integrity
*/
static err_t simulate()
{
err_t ret = OK;
return ret;
}
#ifdef _NOT_USED_
static err_t flash(uint8_t *dst, uint8_t *src, uint32_t length)
{
err_t ret = OK;
/* TODO: do the actual flash */
amd_flash_program(dst, src, length, false, NULL, xputchar);
return ret;
}
#endif /* _NOT_USED_ */
/*
* this callback verifies the data against the S-record file contents after a write to destination
*/
static err_t verify(uint8_t *dst, uint8_t *src, size_t length)
{
uint8_t *end = src + length;
do
{
if (*src++ != *dst++)
{
xprintf("data differs at %p (expected 0x%02x, got 0x%02x)\r\n",
*(src - 1), *(dst - 1));
return FAIL;
}
} while (src < end);
return OK;
}
/*
* needed to avoid missing type cast warning below
*/
err_t srec_memcpy(uint8_t *dst, uint8_t *src, size_t n)
{
err_t e = OK;
xprintf(".");
dbg("\r\ncopy from %p to %p, length %d", src, dst, n);
// dma_memcpy((void *) dst, (void *) src, n);
memcpy((void *) dst, (void *) src, n);
return e;
}
void srec_execute(char *flasher_filename)
{
DRESULT res;
FRESULT fres;
FATFS fs;
FIL file;
err_t err;
void *start_address;
uint32_t length;
disk_initialize(0);
res = disk_status(0);
if (res == RES_OK)
{
fres = f_mount(0, &fs);
if (fres == FR_OK)
{
if ((fres = f_open(&file, flasher_filename, FA_READ) != FR_OK))
{
xprintf("flasher file %s not present on disk\r\n", flasher_filename);
}
else
{
f_close(&file);
/* first pass: parse and check for inconsistencies */
xprintf("check file integrity: ");
err = read_srecords(flasher_filename, &start_address, &length, simulate);
if (err == OK)
{
/* next pass: copy data to destination */
xprintf("OK (start address=%p, length = %ld).\r\ncopy data: ", start_address, length);
err = read_srecords(flasher_filename, &start_address, &length, srec_memcpy);
if (err == OK)
{
/* next pass: verify data */
xprintf("OK.\r\nverify data: ");
err = read_srecords(flasher_filename, &start_address, &length, verify);
if (err == OK)
{
xprintf("OK.\r\n");
typedef void void_func(void);
void_func *func;
xprintf("target successfully written and verified. Start address: %p\r\n", start_address);
func = start_address;
flush_and_invalidate_caches();
(*func)();
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
}
else
{
// xprintf("could not mount FAT FS\r\n");
}
f_mount(0, NULL);
}
else
{
// xprintf("could not initialize SD card\r\n");
}
}