diff --git a/Makefile b/Makefile index d97ffbc..67f0fbd 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,8 @@ CSRCS= \ $(SRCDIR)/unicode.c \ $(SRCDIR)/ff.c \ $(SRCDIR)/sd_card.c \ - $(SRCDIR)/wait.c + $(SRCDIR)/wait.c \ + $(SRCDIR)/s19reader.c ASRCS= \ $(SRCDIR)/startcf.S \ diff --git a/sources/main.c b/sources/main.c index 0c0ba4a..680a0e3 100644 --- a/sources/main.c +++ b/sources/main.c @@ -15,7 +15,7 @@ void die ( /* Stop with dying message */ FRESULT rc /* FatFs return value */ ) { - printf("Failed with rc=%u.\n", rc); + xprintf("Failed with rc=%u.\n", rc); for (;;) ; } @@ -34,11 +34,11 @@ int main (void) f_mount(0, &Fatfs); /* Register volume work area (never fails) */ - printf("\nOpen an existing file (message.txt).\n"); + xprintf("\nOpen an existing file (message.txt).\n"); rc = f_open(&Fil, "MESSAGE.TXT", FA_READ); if (rc) die(rc); - printf("\nType the file content.\n"); + xprintf("\nType the file content.\n"); for (;;) { rc = f_read(&Fil, Buff, sizeof Buff, &br); /* Read a chunk of file */ if (rc || !br) break; /* Error or end of file */ @@ -47,39 +47,39 @@ int main (void) } if (rc) die(rc); - printf("\nClose the file.\n"); + xprintf("\nClose the file.\n"); rc = f_close(&Fil); if (rc) die(rc); - printf("\nCreate a new file (hello.txt).\n"); + xprintf("\nCreate a new file (hello.txt).\n"); rc = f_open(&Fil, "HELLO.TXT", FA_WRITE | FA_CREATE_ALWAYS); if (rc) die(rc); - printf("\nWrite a text data. (Hello world!)\n"); + xprintf("\nWrite a text data. (Hello world!)\n"); rc = f_write(&Fil, "Hello world!\r\n", 14, &bw); if (rc) die(rc); - printf("%u bytes written.\n", bw); + xprintf("%u bytes written.\n", bw); - printf("\nClose the file.\n"); + xprintf("\nClose the file.\n"); rc = f_close(&Fil); if (rc) die(rc); - printf("\nOpen root directory.\n"); + xprintf("\nOpen root directory.\n"); rc = f_opendir(&dir, ""); if (rc) die(rc); - printf("\nDirectory listing...\n"); + xprintf("\nDirectory listing...\n"); for (;;) { rc = f_readdir(&dir, &fno); /* Read a directory item */ if (rc || !fno.fname[0]) break; /* Error or end of dir */ if (fno.fattrib & AM_DIR) - printf(" %s\n", fno.fname); + xprintf(" %s\n", fno.fname); else - printf("%8lu %s\n", fno.fsize, fno.fname); + xprintf("%8lu %s\n", fno.fsize, fno.fname); } if (rc) die(rc); - printf("\nTest completed.\n"); + xprintf("\nTest completed.\n"); for (;;) ; } diff --git a/sources/s19reader.c b/sources/s19reader.c new file mode 100644 index 0000000..2e89145 --- /dev/null +++ b/sources/s19reader.c @@ -0,0 +1,256 @@ +/* + * s19reader.c + * + * Created on: 17.12.2012 + * Author: mfro + * (c) 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 . + * + * Copyright 2012 M. Froeschle + */ + +#include +#include +#include +#include +#include + +typedef enum { FALSE, TRUE } bool; +typedef enum { OK, FAIL } err_t; +#define NULL (void *) 0L + +typedef struct srec2 /* two byte address field */ +{ + uint8_t record_type; /* [0 + 1] for S0, S1, S9 */ + uint8_t length; /* [1 + 1] number of valid bytes following */ + uint16_t address; /* [2 + 2] */ + uint8_t data[64]; /* [4 + length] */ +} __attribute__((packed)) SREC2; +#define SREC2_DATALEN(a) ((a)->length - 2) +#define SREC2_CHECKSUM(a) ((a)->data[SREC2_DATALEN(a) - 1]) + +typedef struct srec4 /* four byte address field */ +{ + uint8_t record_type; /* [0 + 1] for S3, S7 */ + uint8_t length; /* [1 + 1] */ + uint32_t address; /* [2 + 4] */ + uint8_t data[64]; /* [6 + length] */ +} __attribute__((packed)) SREC4; +#define SREC4_DATALEN(a) ((a)->length - 4) +#define SREC4_CHECKSUM(a) ((a)->data[SREC4_DATALEN(a) - 1]) + + +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'; + else + { + /* FIXME: do a clean error exit */ + } +} + +uint8_t hex_to_byte(uint8_t hex[2]) +{ + return 16 * (nibble_to_byte(hex[0])) + (nibble_to_byte(hex[1])); +} + +uint16_t hex_to_word(uint8_t hex[4]) +{ + return 256 * hex_to_byte(&hex[0]) + hex_to_byte(&hex[2]); +} + +uint32_t hex_to_long(uint8_t hex[8]) +{ + return 65536 * hex_to_word(&hex[0]) + hex_to_word(&hex[4]); +} + +void print_record(uint8_t *arr) +{ + xprintf("S%d record:\r\n", arr[0]); + switch (arr[0]) { + case 0: + { + SREC2 *header = (SREC2 *) arr; + + xprintf("type: 0x%x\r\n", header->record_type); + xprintf("byte count: 0x%x\r\n", header->length); + xprintf("address: 0x%x\r\n", header->address); + xprintf("module name: %11.11s\r\n", header->data); + xprintf("checksum: 0x%x\r\n", SREC2_CHECKSUM(header)); + } + break; + + case 3: + { + SREC4 *header = (SREC4 *) arr; + xprintf("type: 0x%x\r\n", header->record_type); + xprintf("byte count: 0x%x\r\n", header->length); + xprintf("address: 0x08%x\r\n", header->address); + xprintf("data: %02x, %0sx, %02x, %02x, ...\r\n", header->data[0], header->data[1], header->data[2], header->data[3]); + xprintf("checksum: 0x%x\r\n", SREC4_CHECKSUM(header)); + } + break; + + default: + xprintf("unsupported report type %d in print_record\r\n", arr[0]); + break; + } +} + +void line_to_vector(uint8_t *line, uint8_t *vector) +{ + int i; + int length; + uint8_t *vp = vector; + + length = hex_to_byte(line + 2); + + line++; + *vp++ = nibble_to_byte(*line); /* record type. Only one single nibble */ + line++; + + xprintf(" "); + for (i = 0; i <= length; i++) + { + xprintf("%c%c", *line, *(line + 1)); + *vp++ = hex_to_byte(line); + line += 2; + } + xprintf("\r\r\n"); + for (i = 0; i < length + 2; i++) + xprintf("%02x", vector[i]); + xprintf("\r\r\n"); +} + +err_t read_srecords(char *filename, uint32_t *start_address, uint32_t *actual_length, uint8_t *buffer, uint32_t buffer_length) +{ + FRESULT fres; + FIL file; + err_t ret = OK; + + if ((fres = f_open(&file, filename, FA_READ) == FR_OK)) + { + uint8_t line[80]; + int lineno = 0; + int data_records = 0; + bool found_block_header = FALSE; + + xprintf("succesfully opened file \"%s\"\r\n", filename); + + while (ret == OK && (uint8_t *) f_gets((char *) line, sizeof(line), &file) != NULL) + { + lineno++; + uint8_t vector[64]; + + line_to_vector(line, vector); /* vector now contains the decoded contents of line, from line[1] on */ + + if (line[0] == 'S') + { + print_record(vector); + switch (line[1]) + { + case '0': /* block header */ + xprintf("S0 record (block header found)\r\n"); + found_block_header = TRUE; + break; + + case '1': + xprintf("S1 record (two byte address field) found\r\n"); + break; + case '2': + xprintf("S2 record (three byte address field) found\r\n"); + break; + case '3': + // xprintf("S3 record (four byte address field) found\r\n"); + if (found_block_header) + { + data_records++; + } + else + { + xprintf("found a data record without a block header before. Data is probably invalid\r\n"); + ret = FAIL; + } + break; + + case '5': + xprintf("S5 record (record count record) found\r\n"); + break; + case '7': + xprintf("S7 record (end of block) found after %d valid data blocks\r\n", data_records); + break; + case '8': + xprintf("S8 record (end of block) found\r\n"); + break; + case '9': + xprintf("S9 record (end of block) found\r\n"); + break; + default: + xprintf("unsupported record type (%c) found in line %d\r\n", line[1], lineno); + ret = FAIL; + break; + } + } + else + { + xprintf("illegal character ('%c') found on line %d. Probably not an S-Record file\r\n", line[0], lineno); + ret = FAIL; + break; + } + } + f_close(&file); + } + else + { + xprintf("could not open file %s\r\n", filename); + } + return ret; +} + +void flasher_load(void) +{ + DRESULT res; + FRESULT fres; + FATFS fs; + err_t err; + uint32_t start_address; + uint32_t length; + uint8_t buffer[2048]; + + xprintf("S-record reader\r\n"); + + disk_initialize(0); + res = disk_status(0); + xprintf("disk status of SD card is %d\r\r\n", res); + if (res == RES_OK) + { + fres = f_mount(0, &fs); + xprintf("mount status of SD card fs is %d\r\n", fres); + if (fres == FR_OK) + { + err = read_srecords("../BaS_gcc_trunk/ram.elf.s19", &start_address, &length, buffer, sizeof(buffer)); + } + f_mount(0, NULL); + } + +} + diff --git a/sources/sd_card.c b/sources/sd_card.c index 8dc693d..524c9f5 100644 --- a/sources/sd_card.c +++ b/sources/sd_card.c @@ -3,7 +3,25 @@ * * Created on: 16.12.2012 * Author: mfro + * + * 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 . + * + * Copyright 2012 M. Froeschle */ + #include #include #include