summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
Diffstat (limited to 'avr')
-rw-r--r--avr/Tupfile2
-rw-r--r--avr/cli.c18
-rw-r--r--avr/cli_readline.c11
-rw-r--r--avr/cmd_boot.c6
-rw-r--r--avr/cmd_fat.c106
-rw-r--r--avr/cmd_loadcpm3.c151
-rw-r--r--avr/cmd_loadihex.c261
-rw-r--r--avr/cmd_mem.c371
-rw-r--r--avr/cmd_misc.c45
-rw-r--r--avr/command.c6
-rw-r--r--avr/command_tbl.c37
-rw-r--r--avr/env.c39
-rw-r--r--avr/main.c21
-rw-r--r--avr/z180-serv.c300
-rw-r--r--avr/z80-if.c3
15 files changed, 1004 insertions, 373 deletions
diff --git a/avr/Tupfile b/avr/Tupfile
index 78e9744..0c35de4 100644
--- a/avr/Tupfile
+++ b/avr/Tupfile
@@ -7,7 +7,7 @@ FATFS = $(TOP)/fatfs/src/ff.c
SRC = main.c
SRC += cli.c cli_readline.c command.c command_tbl.c
SRC += cmd_help.c cmd_date.c cmd_mem.c cmd_boot.c cmd_gpio.c cmd_misc.c
-SRC += cmd_sd.c cmd_fat.c
+SRC += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c
SRC += env.c xmalloc.c con-utils.c print-utils.c getopt-min.c
SRC += timer.c serial.c i2c.c pcf8583.c mmc.c
SRC += background.c z180-serv.c z80-if.c gpio.c
diff --git a/avr/cli.c b/avr/cli.c
index 52c85db..6b26b6f 100644
--- a/avr/cli.c
+++ b/avr/cli.c
@@ -27,6 +27,9 @@
#include "con-utils.h"
#include "cli.h"
+
+/* FIXME: Quoting problems */
+
#define DEBUG_PARSER 0 /* set to 1 to debug */
#define debug_parser(fmt, args...) \
@@ -46,7 +49,7 @@ static int cli_parse_line(char *line, char *argv[])
inp++) {
switch (state) {
- case 0:
+ case 0: /* before arg string, waiting for arg start */
if (isblank(c))
continue;
@@ -55,7 +58,7 @@ static int cli_parse_line(char *line, char *argv[])
state = 1;
/* fall thru */
- case 1:
+ case 1: /* in arg string, waiting for end of arg string */
if (c == '\\') {
++state;
continue;
@@ -71,7 +74,7 @@ static int cli_parse_line(char *line, char *argv[])
}
break;
- case 3:
+ case 3: /* in quote */
if (c == '\\' && quote == '\"') {
++state;
continue;
@@ -82,7 +85,7 @@ static int cli_parse_line(char *line, char *argv[])
}
break;
- case 2:
+ case 2: /* waiting for next char */
case 4:
--state;
break;
@@ -252,12 +255,13 @@ static int cli_run_command(const char *cmd, int flag)
*/
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep == '\'') &&
- (*(sep - 1) != '\\'))
+ (sep != str) && /* past string start */
+ (*(sep - 1) != '\\')) /* and NOT escaped */
inquotes = !inquotes;
if (!inquotes &&
- (*sep == ';' || *sep == '\n') && /* separator */
- (sep != str) && /* past string start */
+ (*sep == ';' || *sep == '\n') && /* separator */
+ (sep != str) && /* past string start */
(*(sep - 1) != '\\')) /* and NOT escaped */
break;
}
diff --git a/avr/cli_readline.c b/avr/cli_readline.c
index 04d32b1..93a0355 100644
--- a/avr/cli_readline.c
+++ b/avr/cli_readline.c
@@ -12,7 +12,6 @@
*/
#include "common.h"
-
#include <string.h>
#include <stdio.h>
@@ -562,16 +561,8 @@ static int cli_readline_into_buffer(const FLASH char *const prompt, char *buffer
my_puts_P(tab_seq + (col & 07));
col += 8 - (col & 07);
} else {
- char buf[2];
-
- /*
- * Echo input using puts() to force an
- * LCD flush if we are using an LCD
- */
++col;
- buf[0] = c;
- buf[1] = '\0';
- my_puts(buf);
+ putchar(c);
}
*p++ = c;
++n;
diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c
index 301f4f5..f9f8f90 100644
--- a/avr/cmd_boot.c
+++ b/avr/cmd_boot.c
@@ -194,9 +194,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
pending = (Stat & S_CON_PENDING) != 0;
Stat &= ~S_CON_PENDING;
}
- if (pending)
- while ((ch = z80_memfifo_getc(fifo_conout)) >= 0)
+ if (pending) {
+ uint8_t count = 100;
+ while ((ch = z80_memfifo_getc(fifo_conout)) >= 0 && --count)
putchar(ch);
+ }
if ((ch = my_getchar(0)) >= 0) {
switch (state) {
diff --git a/avr/cmd_fat.c b/avr/cmd_fat.c
index 8ed7ae3..af2f772 100644
--- a/avr/cmd_fat.c
+++ b/avr/cmd_fat.c
@@ -22,8 +22,8 @@
#include "timer.h"
#include "debug.h"
-
-#define MAX_MEMORY (1ul << 20)
+/* TODO: use memory size test function (cmd_mem.c) */
+#define MAX_MEMORY (1ul << 19)
#define BUFFER_SIZE 512
@@ -157,7 +157,7 @@ FRESULT scan_files (
*/
command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS *FatFs, *fs;
+ FATFS *fs;
DWORD nfreeclst;
FRESULT res;
char *path;
@@ -165,64 +165,57 @@ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
(void) cmdtp; (void) flag; (void) argc;
- FatFs = (FATFS *) malloc(sizeof (FATFS));
path = (char *) malloc(BUFFER_SIZE);
- if (FatFs == NULL || path == NULL) {
+ if (path == NULL) {
printf_P(PSTR("fatstat: Out of Memory!\n"));
free(path);
- free(FatFs);
return CMD_RET_FAILURE;
}
- res = f_mount(FatFs, argv[1], 0);
+ res = f_getfree(argv[1], &nfreeclst, &fs);
if (!res) {
- res = f_getfree(argv[1], &nfreeclst, &fs);
- if (!res) {
- printf_P(PSTR(
- "FAT type: %u\n"
- "Bytes/Cluster: %lu\n"
- "Number of FATs: %u\n"
- "Root DIR entries: %u\n"
- "Sectors/FAT: %lu\n"
- "Number of clusters: %lu\n"
- "FAT start (lba): %lu\n"
- "DIR start (lba,cluster): %lu\n"
- "Data start (lba): %lu\n"),
- fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
- fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
- fs->fatbase, fs->dirbase, fs->database);
+ printf_P(PSTR(
+ "FAT type: %u\n"
+ "Bytes/Cluster: %lu\n"
+ "Number of FATs: %u\n"
+ "Root DIR entries: %u\n"
+ "Sectors/FAT: %lu\n"
+ "Number of clusters: %lu\n"
+ "FAT start (lba): %lu\n"
+ "DIR start (lba,cluster): %lu\n"
+ "Data start (lba): %lu\n"),
+ fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
+ fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
+ fs->fatbase, fs->dirbase, fs->database);
#if _USE_LABEL
- TCHAR label[12];
- DWORD serial;
- res = f_getlabel(argv[1], label, &serial);
- if (!res) {
- printf_P(PSTR(
- "Volume name: %s\n"
- "Volume S/N: %04X-%04X\n"),
- label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
- }
+ TCHAR label[12];
+ DWORD serial;
+ res = f_getlabel(argv[1], label, &serial);
+ if (!res) {
+ printf_P(PSTR(
+ "Volume name: %s\n"
+ "Volume S/N: %04X-%04X\n"),
+ label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
+ }
#endif
- if (!res) {
- my_puts_P(PSTR("\nCounting... "));
- statp.AccSize = statp.AccFiles = statp.AccDirs = 0;
- strcpy(path, argv[1]);
+ if (!res) {
+ my_puts_P(PSTR("\nCounting... "));
+ statp.AccSize = statp.AccFiles = statp.AccDirs = 0;
+ strcpy(path, argv[1]);
- res = scan_files(path, &statp);
- }
- if (!res) {
- printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
- "%lu KB total disk space.\n%lu KB available.\n"),
- statp.AccFiles, statp.AccSize, statp.AccDirs,
- (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2)
- );
- }
+ res = scan_files(path, &statp);
+ }
+ if (!res) {
+ printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
+ "%lu KB total disk space.\n%lu KB available.\n"),
+ statp.AccFiles, statp.AccSize, statp.AccDirs,
+ (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2)
+ );
}
}
free(path);
- free(FatFs);
- f_mount(NULL, argv[1], 0);
if (res) {
put_rc(res);
return CMD_RET_FAILURE;
@@ -237,7 +230,7 @@ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
*/
command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS FatFs, *fs;
+ FATFS *fs;
DIR Dir; /* Directory object */
FILINFO Finfo;
unsigned long p1;
@@ -251,9 +244,7 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
(void) cmdtp; (void) flag; (void) argc;
- res = f_mount(&FatFs, argv[1], 0);
- if (!res)
- res = f_opendir(&Dir, argv[1]);
+ res = f_opendir(&Dir, argv[1]);
if (res) {
put_rc(res);
return CMD_RET_FAILURE;
@@ -341,7 +332,6 @@ FRESULT mkpath(TCHAR *path)
*/
command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS *FatFs;
FIL File;
uint32_t addr;
unsigned long bytes;
@@ -376,21 +366,15 @@ command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
if (addr + bytes > MAX_MEMORY)
bytes = MAX_MEMORY - addr;
- FatFs = (FATFS *) malloc(sizeof (FATFS));
buffer = (uint8_t *) malloc(BUFFER_SIZE);
- if (FatFs == NULL || buffer == NULL) {
+ if (buffer == NULL) {
printf_P(PSTR("fatstat: Out of Memory!\n"));
- free(FatFs);
free(buffer);
return CMD_RET_FAILURE;
}
- res = f_mount(FatFs, argv[1], 0);
-
- if (!res) {
- if (dowrite) {
- res = mkpath(argv[1]);
- }
+ if (dowrite) {
+ res = mkpath(argv[1]);
}
if (!res) {
res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS
@@ -451,11 +435,9 @@ command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
bytes_rw, bytes_rw, timer ? (bytes_rw * 1000 / timer) : 0);
}
}
- f_mount(NULL, argv[1], 0);
}
free(buffer);
- free(FatFs);
if (buserr)
my_puts_P(PSTR("Bus timeout\n"));
diff --git a/avr/cmd_loadcpm3.c b/avr/cmd_loadcpm3.c
new file mode 100644
index 0000000..fd685b2
--- /dev/null
+++ b/avr/cmd_loadcpm3.c
@@ -0,0 +1,151 @@
+/*
+ * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "command.h"
+#include "env.h"
+#include "ff.h"
+#include "con-utils.h"
+#include "z80-if.h"
+#include "debug.h"
+
+
+#define RS 128 /* CP/M record size */
+
+/*
+ * Load Routine
+ *
+ * Input: addr = Page Address of load top
+ * len = Length in pages of module to read
+ *
+ */
+int load(FIL *File, uint16_t addr, uint8_t len)
+{
+ uint8_t buffer[RS];
+ unsigned int br; /* bytes read */
+ int res;
+
+ len *= 2; /* length in records of module */
+ //debug("## load: addr: 0x%.4X, records: 0x%.4X, (%u)\n", addr, len, len);
+
+ for (; len; len--) {
+ addr -= RS;
+ res = f_read(File, buffer, RS, &br);
+ if (res || br != RS) {
+ return 1;
+ }
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return 2;
+ }
+ z80_write_block(buffer, addr, RS);
+ z80_bus_cmd(Release);
+ //debug("## written: 0x%.4X\n", addr);
+ }
+
+ return 0;
+}
+
+
+command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint16_t mem_top;
+ uint8_t res_len;
+ uint16_t bank_top;
+ uint8_t bank_len;
+ uint16_t osentry_adr = 0;
+ long offset = 0;
+ char *fname;
+ FIL File;
+ /* TODO: put CONFIG_PATH_CPM3SYS in flash */
+ char default_fname[] = CONFIG_PATH_CPM3SYS;
+ unsigned int br; /* bytes read */
+ uint8_t buffer[RS];
+ int res;
+
+ (void) cmdtp; (void) flag;
+
+
+ if (argc > 1)
+ offset = strtoul(argv[1], NULL, 16);
+
+ fname = getenv(PSTR(ENV_PATH_CPM3SYS));
+
+ if (argc > 2) {
+ fname = argv[2];
+ }
+
+ if (fname == NULL || *fname == '\0')
+ fname = default_fname;
+
+ res = f_open(&File, fname, FA_READ );
+ if (res) {
+ printf_P(PSTR("Error: failed to open '%s'\n"), fname);
+ return CMD_RET_FAILURE;
+ }
+
+ printf_P(PSTR("Loading: '%s'...\n"), fname);
+
+ /* read the load record */
+ res = f_read(&File, buffer, RS, &br);
+ if (res || br != RS)
+ goto out;
+
+ mem_top = buffer[0] << 8;
+ res_len = buffer[1];
+ bank_top = buffer[2] << 8;
+ bank_len = buffer[3];
+ osentry_adr = buffer[4] + (buffer[5] << 8);
+
+ /* read display info */
+ res = f_read(&File, buffer, RS, &br);
+ if (res || br != RS)
+ goto out;
+
+ /* print the info */
+ buffer[RS-1] = '$';
+ uint8_t *p = memchr(buffer, '$', RS);
+ *p = '\0';
+ my_puts((char *)buffer);
+
+ /* Main System Load */
+
+ /* Load Common Portion of System */
+ if ((res = load(&File, mem_top, res_len)) != 0)
+ goto out;
+
+ /* Load Banked Portion of System */
+ res = load(&File, bank_top, bank_len);
+
+out:
+ f_close(&File);
+
+ if (res) {
+ printf_P(PSTR("Error: failed to read '%s'\n"), fname);
+ return CMD_RET_FAILURE;
+ } else {
+ if (res_len != 0)
+ setenv_hex(PSTR(ENV_STARTADDRESS), osentry_adr);
+ printf_P(PSTR("Loaded: Resident: "));
+ if (res_len != 0)
+ printf_P(PSTR("0x%.4X-0x%.4X, "), mem_top-res_len*256, mem_top-1);
+ else
+ printf_P(PSTR(" - "));
+ printf_P(PSTR("Banked: "));
+ if (bank_len != 0)
+ printf_P(PSTR("0x%.4X-0x%.4X\n"), bank_top-bank_len*256, bank_top-1);
+ else
+ printf_P(PSTR(" - \n"));
+
+ return CMD_RET_SUCCESS;
+ }
+}
diff --git a/avr/cmd_loadihex.c b/avr/cmd_loadihex.c
new file mode 100644
index 0000000..18d5331
--- /dev/null
+++ b/avr/cmd_loadihex.c
@@ -0,0 +1,261 @@
+/*
+ * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#include "command.h"
+#include "con-utils.h"
+#include "z80-if.h"
+#include "debug.h"
+
+
+uint32_t detect_ramsize(void)
+{
+ uint32_t addr;
+ uint8_t save_addr, save_0;
+ const uint8_t PATTERN_1 = 0x55;
+ const uint8_t PATTERN_2 = ~PATTERN_1;
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return 0;
+ }
+
+ save_0 = z80_read(0);
+ z80_write(0, PATTERN_1);
+
+ for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) {
+ save_addr = z80_read(addr);
+ z80_write(addr, PATTERN_2);
+ if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2)
+ break;
+ z80_write(addr, save_addr);
+ }
+ z80_write(0, save_0);
+ z80_bus_cmd(Release);
+
+ return addr;
+}
+
+typedef enum {
+ IHX_OK,
+ IHX_BROKEN,
+ IHX_CHKSUMERR
+} ihx_rstat_t;
+
+typedef struct {
+ ihx_rstat_t status;
+ int8_t type;
+ uint8_t len;
+ uint16_t address;
+ uint8_t data[256];
+} ihex_t;
+
+
+static
+int get_hexdigit(void) {
+
+ int c;
+ c = toupper(my_getchar(1));
+ if (isxdigit(c)) {
+ c -= '0';
+ if (c > 9)
+ c -= ('A' - '0' - 10);
+ return c;
+ } else
+ return -1;
+}
+
+static
+int get_hexbyte(void) {
+
+ uint8_t i,j;
+
+ if ((i = (uint8_t) get_hexdigit()) < 0x10)
+ if ((j = (uint8_t) get_hexdigit()) < 0x10) {
+ return (i<<4) + j;
+ }
+
+ return -1;
+}
+
+
+static
+int ihex_get_record(ihex_t *rec) {
+
+ int c;
+ uint8_t sum;
+
+ rec->status = IHX_BROKEN;
+ rec->len = 0;
+ rec->type = 0xff;
+
+ while ((c = my_getchar(0)) != ':') {
+ if (c == 0x03)
+ return -1; /* Control-C */
+ if (c == 0x04) {
+ rec->status = IHX_OK;
+ return 0; /*Control-D, EOF */
+ }
+ }
+
+ if ((c = get_hexbyte()) < 0) /* Start code */
+ return -1;
+ sum = c;
+ rec->len = c;
+ if ((c = get_hexbyte()) < 0) /* Byte Count */
+ return -1;
+ sum += c;
+ rec->address = c * 256;
+ if ((c = get_hexbyte()) < 0) /* Address */
+ return -1;
+ sum += c;
+ rec->address += c;
+ if ((c = get_hexbyte()) < 0) /* Record type */
+ return -1;
+ sum += c;
+ rec->type = c;
+
+ if (rec->len) { /* Record Data */
+ uint8_t n;
+
+ for (n = 0; n < rec->len; n++) {
+ if ((c = get_hexbyte()) < 0)
+ break;
+ sum += c;
+ rec->data[n] = c;
+ }
+
+ if (n < rec->len) {
+ return -1;
+ }
+ }
+
+ c = get_hexbyte(); /* Check sum */
+
+ if (c >= 0) {
+ sum += c;
+ if (sum == 0)
+ rec->status = IHX_OK;
+ else
+ rec->status = IHX_CHKSUMERR;
+ }
+
+ return rec->len;
+}
+
+
+command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ long offset = 0;
+ uint32_t base_address = 0;
+ uint32_t address_max = detect_ramsize();
+ uint32_t address_high = 0;
+ uint32_t address_low = address_max;
+ command_ret_t rcode = CMD_RET_FAILURE;
+ ihex_t rec;
+ bool firstrec = true;
+
+ (void) cmdtp; (void) flag;
+
+
+ if (argc > 1)
+ offset = strtol(argv[1], NULL, 16);
+
+ printf_P(PSTR("Waiting for Intel Hex Records...\n"));
+
+ while (ihex_get_record(&rec) > 0 &&
+ rec.status == IHX_OK &&
+ rec.type != 1 ) {
+
+ switch (rec.type) {
+ case 0: /* Data record */
+ if (firstrec) {
+ printf_P(PSTR("Loading: 0x....."));
+ firstrec = false;
+ }
+ if (rec.len) {
+ uint32_t addr = base_address + rec.address + offset;
+ if (addr < address_low)
+ address_low = addr;
+ if (addr+rec.len > address_high)
+ address_high = addr + rec.len;
+
+// debug("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n",
+// address_low, address_high, address_max, addr, rec.len);
+ printf_P(PSTR("\b\b\b\b\b%.5lX"), addr);
+ if (addr < address_max) {
+ uint32_t tmplen = address_max - addr;
+ if (rec.len > tmplen)
+ rec.len = tmplen;
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return CMD_RET_FAILURE;
+ }
+ z80_write_block(rec.data, /* src */
+ addr, /* dest */
+ rec.len); /* len */
+ z80_bus_cmd(Release);
+ }
+ }
+ break;
+
+#if 0
+ case 1: /* EOF record */
+ break;
+#endif
+ case 2: /* Extended Segment Address Record */
+ base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 4;
+ break;
+
+ case 4: /* Extended Linear Address Record */
+ base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
+ break;
+
+ case 3: /* Start Segment Address Record (ignored)*/
+ case 5: /* Start Linear Address Record (ignored)*/
+ break;
+
+ }
+ }
+
+ switch (rec.status) {
+ case IHX_OK:
+ rcode = CMD_RET_SUCCESS;
+ break;
+
+ case IHX_BROKEN:
+ case IHX_CHKSUMERR:
+ printf_P(PSTR("Broken Hex Record or loading interrupted!\n"));
+ break;
+ }
+
+
+ for (uint_fast8_t i=0; i<100; ++i) {
+ /* flush input buffer */
+ while (my_getchar(0) > 0)
+ ;
+ udelay(1000);
+ }
+
+
+ printf_P(PSTR("\nData loaded: "));
+ if (address_low >= MIN(address_high, address_max))
+ printf_P(PSTR("None.\n"));
+ else
+ printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low,
+ MIN(address_high, address_max) - 1);
+
+ if (address_high > address_max)
+ printf_P(PSTR("Data above highest RAM address "
+ "(in range 0x%.5lX - 0x%.5lX) ignored!\n"), address_max, address_high - 1);
+
+ return rcode;
+}
diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c
index 20a4412..53b1842 100644
--- a/avr/cmd_mem.c
+++ b/avr/cmd_mem.c
@@ -16,13 +16,15 @@
#include "common.h"
#include <stdlib.h>
#include <ctype.h>
+#include <avr/interrupt.h>
#include "command.h"
#include "cli_readline.h"
#include "print-utils.h"
#include "con-utils.h"
+#include "timer.h"
#include "z80-if.h"
-//#include "debug.h"
+#include "debug.h"
#ifndef CONFIG_SYS_MEMTEST_SCRATCH
@@ -222,55 +224,35 @@ command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
#ifdef CONFIG_MX_CYCLIC
command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- int i;
uint32_t count;
+ uint32_t ts;
+
+ (void) cmdtp;
+ (void) flag;
if (argc < 4)
return CMD_RET_USAGE;
count = strtoul(argv[3], NULL, 10);
+ clear_ctrlc(); /* forget any previous Control C */
for (;;) {
- do_mem_md (NULL, 0, 3, argv);
-
- /* delay for <count> ms... */
-/* TODO: use timer */
- for (i=0; i<count; i++)
- udelay (1000);
-
- /* check for ctrl-c to abort... */
- if (ctrlc()) {
- my_puts_P(PSTR("Abort\n"));
- return CMD_RET_SUCCESS;
- }
- }
-
- return CMD_RET_SUCCESS;
-}
-
-command_ret_t do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- int i;
- uint32_t count;
-
- if (argc < 4)
- return CMD_RET_USAGE;
- count = strtoul(argv[3], NULL, 10);
+ if (argv[0][1] == 'd')
+ do_mem_md (NULL, 0, 3, argv);
+ else
+ do_mem_mw (NULL, 0, 3, argv);
- for (;;) {
- do_mem_mw (NULL, 0, 3, argv);
/* delay for <count> ms... */
-/* TODO: use timer */
- for (i=0; i<count; i++)
- udelay (1000);
-
- /* check for ctrl-c to abort... */
- if (ctrlc()) {
- my_puts_P(PSTR("Abort\n"));
- return CMD_RET_SUCCESS;
- }
+ ts = get_timer(0);
+ do {
+ /* check for ctrl-c to abort... */
+ if (had_ctrlc() || ctrlc()) {
+ my_puts_P(PSTR("Abort\n"));
+ return CMD_RET_SUCCESS;
+ }
+ } while (get_timer(ts) < count);
}
return CMD_RET_SUCCESS;
@@ -417,27 +399,26 @@ command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;)
z80_read(addr);
- z80_bus_cmd(Release);
}
if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;) {
uint32_t i = length;
uint32_t p = addr;
while (i-- > 0)
z80_read(p++);
}
- z80_bus_cmd(Release);
return CMD_RET_SUCCESS;
}
-#ifdef CONFIG_LOOPW
command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
uint32_t addr, length;
@@ -457,7 +438,8 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
data = strtoul(argv[3], NULL, 16);
- /* We want to optimize the loops to run as fast as possible.
+ /*
+ * We want to optimize the loops to run as fast as possible.
* If we have only one object, just run infinite loops.
*/
if (length == 1) {
@@ -465,6 +447,7 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;)
z80_write(addr, data);
}
@@ -473,6 +456,7 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;) {
uint32_t i = length;
uint32_t p = addr;
@@ -480,35 +464,33 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
z80_write(p++, data);
}
}
-#endif /* CONFIG_LOOPW */
+
+//#define CONFIG_SYS_ALT_MEMTEST
#ifdef CONFIG_CMD_MEMTEST
-static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
- vu_long *dummy)
+static uint32_t mem_test_alt(uint32_t start_addr, uint32_t end_addr)
{
- vu_long *addr;
+ uint32_t addr;
+ uint32_t dummy;
uint32_t errs = 0;
- uint32_t val, readback;
- int j;
- vu_long offset;
- vu_long test_offset;
- vu_long pattern;
- vu_long temp;
- vu_long anti_pattern;
- vu_long num_words;
- static const FLASH uint32_t bitpattern[] = {
- 0x00000001, /* single bit */
- 0x00000003, /* two adjacent bits */
- 0x00000007, /* three adjacent bits */
- 0x0000000F, /* four adjacent bits */
- 0x00000005, /* two non-adjacent bits */
- 0x00000015, /* three non-adjacent bits */
- 0x00000055, /* four non-adjacent bits */
- 0xaaaaaaaa, /* alternating 1/0 */
+ uint32_t offset;
+ uint32_t test_offset;
+ uint8_t pattern;
+ uint8_t anti_pattern;
+ uint8_t temp;
+ uint32_t num_bytes;
+
+ static const FLASH uint8_t bitpattern[] = {
+ 0x01, /* single bit */
+ 0x03, /* two adjacent bits */
+ 0x07, /* three adjacent bits */
+ 0x0F, /* four adjacent bits */
+ 0x05, /* two non-adjacent bits */
+ 0x15, /* three non-adjacent bits */
+ 0x55, /* four non-adjacent bits */
+ 0xaa, /* alternating 1/0 */
};
- num_words = (end_addr - start_addr) / sizeof(vu_long);
-
/*
* Data line test: write a pattern to the first
* location, write the 1's complement to a 'parking'
@@ -526,35 +508,39 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add
* '0's and '0' bits through a field of '1's (i.e.
* pattern and ~pattern).
*/
- addr = buf;
- for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
- val = bitpattern[j];
- for (; val != 0; val <<= 1) {
- *addr = val;
- *dummy = ~val; /* clear the test data off the bus */
- readback = *addr;
- if (readback != val) {
+ addr = start_addr;
+ dummy = start_addr+1;
+ for (unsigned int j = 0; j < ARRAY_SIZE(bitpattern); j++) {
+ pattern = bitpattern[j];
+ for (; pattern != 0; pattern <<= 1) {
+ anti_pattern = ~pattern;
+ z80_write(addr, pattern);
+ z80_write(dummy, anti_pattern); /* clear the test data off the bus */
+ temp = z80_read(addr);
+ if (temp != pattern) {
printf_P(PSTR("FAILURE (data line): "
- "expected %05lx, actual %05lx\n"),
- val, readback);
+ "expected %02x, actual %02x\n"),
+ pattern, temp);
errs++;
- if (ctrlc())
- return -1;
}
- *addr = ~val;
- *dummy = val;
- readback = *addr;
- if (readback != ~val) {
+ z80_write(addr, anti_pattern);
+ z80_write(dummy, pattern); /* clear the test data off the bus */
+ temp = z80_read(addr);
+ if (temp != anti_pattern) {
printf_P(PSTR("FAILURE (data line): "
- "Is %05lx, should be %05lx\n"),
- readback, ~val);
+ "Is %02x, should be %02x\n"),
+ temp, anti_pattern);
errs++;
- if (ctrlc())
- return -1;
}
}
+
+ if (ctrlc())
+ return -1;
}
+ if (errs)
+ return errs;
+
/*
* Based on code whose Original Author and Copyright
* information follows: Copyright (c) 1998 by Michael
@@ -589,59 +575,61 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*/
- pattern = (vu_long) 0xaaaaaaaa;
- anti_pattern = (vu_long) 0x55555555;
- debug("%s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_words);
+ num_bytes = (end_addr - start_addr) / sizeof(uint8_t);
+
+ pattern = 0xaa;
+ anti_pattern = 0x55;
+
+// debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes);
/*
* Write the default pattern at each of the
* power-of-two offsets.
*/
- for (offset = 1; offset < num_words; offset <<= 1)
- addr[offset] = pattern;
+ for (offset = 1; offset < num_bytes; offset <<= 1)
+ z80_write(addr+offset, pattern);
/*
* Check for address bits stuck high.
*/
- test_offset = 0;
- addr[test_offset] = anti_pattern;
+ z80_write(start_addr, anti_pattern);
- for (offset = 1; offset < num_words; offset <<= 1) {
- temp = addr[offset];
+ for (offset = 1; offset < num_bytes; offset <<= 1) {
+ temp = z80_read(start_addr + offset);
if (temp != pattern) {
- printf_P(PSTR("\nFAILURE: Address bit stuck high @ 0x%.5lx:"
- " expected 0x%.5lx, actual 0x%.5lx\n"),
- start_addr + offset*sizeof(vu_long),
- pattern, temp);
+ printf_P(PSTR("FAILURE: Address bit stuck high @ 0x%.5lx:"
+ " expected 0x%.2x, actual 0x%.2x\n"),
+ start_addr + offset, pattern, temp);
errs++;
if (ctrlc())
return -1;
}
}
- addr[test_offset] = pattern;
+ z80_write(start_addr, pattern);
/*
* Check for addr bits stuck low or shorted.
*/
- for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
- addr[test_offset] = anti_pattern;
+ for (test_offset = 1; test_offset < num_bytes; test_offset <<= 1) {
+ z80_write(start_addr + test_offset, anti_pattern);
- for (offset = 1; offset < num_words; offset <<= 1) {
- temp = addr[offset];
+ for (offset = 1; offset < num_bytes; offset <<= 1) {
+ temp = z80_read(start_addr + offset);
if ((temp != pattern) && (offset != test_offset)) {
- printf_P(PSTR("\nFAILURE: Address bit stuck low or"
- " shorted @ 0x%.5lx: expected 0x%.5lx,"
- " actual 0x%.5lx\n"),
- start_addr + offset*sizeof(vu_long),
- pattern, temp);
+ printf_P(PSTR("FAILURE: Address bit stuck low or shorted"
+ " @ 0x%.5lx: expected 0x%.2x, actual 0x%.2x\n"),
+ start_addr + offset, pattern, temp);
errs++;
if (ctrlc())
return -1;
}
}
- addr[test_offset] = pattern;
+ z80_write(start_addr + test_offset, pattern);
}
+ if (errs)
+ return errs;
+
/*
* Description: Test the integrity of a physical
* memory device by performing an
@@ -654,111 +642,50 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*/
- num_words++;
+ num_bytes++;
/*
* Fill memory with a known pattern.
*/
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- addr[offset] = pattern;
- }
+ for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++)
+ z80_write(addr, pattern);
/*
* Check each location and invert it for the second pass.
*/
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- temp = addr[offset];
+ for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) {
+ temp = z80_read(addr);
if (temp != pattern) {
- printf_P(PSTR("\nFAILURE (read/write) @ 0x%.5lx:"
- " expected 0x%.5lx, actual 0x%.5lx)\n"),
- start_addr + offset*sizeof(vu_long),
- pattern, temp);
+ printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
+ " expected 0x%.2x, actual 0x%.2x)\n"),
+ addr, pattern, temp);
errs++;
if (ctrlc())
return -1;
}
anti_pattern = ~pattern;
- addr[offset] = anti_pattern;
+ z80_write(addr, anti_pattern);
}
/*
* Check each location for the inverted pattern and zero it.
*/
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- WATCHDOG_RESET();
+ for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) {
anti_pattern = ~pattern;
- temp = addr[offset];
+ temp = z80_read(addr);
if (temp != anti_pattern) {
- printf_P(PSTR("\nFAILURE (read/write): @ 0x%.5lx:"
- " expected 0x%.5lx, actual 0x%.5lx)\n"),
- start_addr + offset*sizeof(vu_long),
- anti_pattern, temp);
+ printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
+ " expected 0x%.2x, actual 0x%.2x)\n"),
+ start_addr, anti_pattern, temp);
errs++;
if (ctrlc())
return -1;
}
- addr[offset] = 0;
+ z80_write(addr, 0);
}
- return 0;
-}
-
-static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
- vu_long pattern, int iteration)
-{
- vu_long *end;
- vu_long *addr;
- uint32_t errs = 0;
- uint32_t incr, length;
- uint32_t val, readback;
-
- /* Alternate the pattern */
- incr = 1;
- if (iteration & 1) {
- incr = -incr;
- /*
- * Flip the pattern each time to make lots of zeros and
- * then, the next time, lots of ones. We decrement
- * the "negative" patterns and increment the "positive"
- * patterns to preserve this feature.
- */
- if (pattern & 0x80000000)
- pattern = -pattern; /* complement & increment */
- else
- pattern = ~pattern;
- }
- length = (end_addr - start_addr) / sizeof(uint32_t);
- end = buf + length;
- printf_P(PSTR("\rPattern %08lX Writing..."
- "%12s"
- "\b\b\b\b\b\b\b\b\b\b"),
- pattern, "");
-
- for (addr = buf, val = pattern; addr < end; addr++) {
- *addr = val;
- val += incr;
- }
-
- my_puts_P(PSTR("Reading..."));
-
- for (addr = buf, val = pattern; addr < end; addr++) {
- readback = *addr;
- if (readback != val) {
- uint32_t offset = addr - buf;
-
- printf_P(PSTR("\nMem error @ 0x%08X: "
- "found %08lX, expected %08lX\n"),
- (unsigned int)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
- readback, val);
- errs++;
- if (ctrlc())
- return -1;
- }
- val += incr;
- }
-
- return 0;
+ return errs;
}
/*
@@ -769,77 +696,61 @@ static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_a
command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
- uint32_t start, end;
- vu_long *buf, *dummy;
- int iteration_limit;
-/* TODO: command_ret_t */
+ uint32_t start = 0;
+ uint32_t end;
+ unsigned int iteration_limit = 0;
+ unsigned int iteration;
+ uint32_t errs = 0; /* number of errors */
int ret;
- uint32_t errs = 0; /* number of errors, or -1 if interrupted */
- uint32_t pattern;
- int iteration;
-#if defined(CONFIG_SYS_ALT_MEMTEST)
- const int alt_test = 1;
-#else
- const int alt_test = 0;
-#endif
+
+ (void) cmdtp;
+ (void) flag;
if (argc > 1)
start = strtoul(argv[1], NULL, 16);
- else
- start = CONFIG_SYS_MEMTEST_START;
if (argc > 2)
end = strtoul(argv[2], NULL, 16);
else
- end = CONFIG_SYS_MEMTEST_END;
+ end = CONFIG_SYS_RAMSIZE_MAX - 1;
if (argc > 3)
- pattern = (uint32_t)strtoul(argv[3], NULL, 16);
- else
- pattern = 0;
+ iteration_limit = (unsigned int) strtoul(argv[3], NULL, 16);
- if (argc > 4)
- iteration_limit = (uint32_t)strtoul(argv[4], NULL, 16);
- else
- iteration_limit = 0;
+ printf_P(PSTR("Testing %05lx ... %05lx:\n"), start, end);
+// debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
- printf_P(PSTR("Testing %08x ... %08x:\n"), (unsigned int)start, (unsigned int)end);
- debug("%s:%d: start %#05lx end %#05lx\n", __func__, __LINE__,
- start, end);
+ clear_ctrlc(); /* forget any previous Control C */
-/* TODO: */
-// buf = map_sysmem(start, end - start);
-// dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
for (iteration = 0;
!iteration_limit || iteration < iteration_limit;
iteration++) {
- if (ctrlc()) {
- errs = -1UL;
- break;
- }
printf_P(PSTR("Iteration: %6d\r"), iteration + 1);
- debug("\n");
- if (alt_test) {
- errs = mem_test_alt(buf, start, end, dummy);
- } else {
- errs = mem_test_quick(buf, start, end, pattern,
- iteration);
+// debug("\n");
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return CMD_RET_FAILURE;
}
- if (errs == -1UL)
+ errs += mem_test_alt(start, end);
+ z80_bus_cmd(Release);
+
+ if (had_ctrlc() || ctrlc()) {
break;
+ }
}
- if (errs == -1UL) {
+ if (had_ctrlc()) {
/* Memory test was aborted - write a newline to finish off */
- putc('\n');
- ret = 1;
+ putchar('\n');
+ ret = CMD_RET_FAILURE;
} else {
printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
iteration, errs);
- ret = errs != 0;
+ ret = errs ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
}
- return ret; /* not reached */
+ return ret;
}
#endif /* CONFIG_CMD_MEMTEST */
diff --git a/avr/cmd_misc.c b/avr/cmd_misc.c
index b29aedd..c9a3c45 100644
--- a/avr/cmd_misc.c
+++ b/avr/cmd_misc.c
@@ -9,46 +9,43 @@
#include "common.h"
#include <stdlib.h>
+#include <stdbool.h>
#include "command.h"
#include "timer.h"
#include "con-utils.h"
+#include "getopt-min.h"
command_ret_t do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- uint_fast8_t putnl = 1;
+ bool put_newline = true;
(void) cmdtp; (void) flag;
- for (uint_fast8_t i = 1; i < argc; i++) {
+ /* reset getopt() */
+ optind = 1;
+
+ int opt;
+ while ((opt = getopt(argc, argv, PSTR("n"))) != -1) {
+ switch (opt) {
+ case 'n':
+ put_newline = false;
+ break;
+ default: /* '?' */
+ return CMD_RET_USAGE;
+ }
+ }
- uint_fast8_t backslash = 0;
- char *p = argv[i];
- char c;
+ for (uint_fast8_t i = optind; i < argc; i++) {
- if (i != 1)
+ if (i != optind)
putchar(' ');
- while ((c = *p++) != '\0') {
-
- if(backslash) {
- backslash = 0;
- if (c == 'c') {
- putnl = 0;
- continue;
- } else
- putchar('\\');
- } else {
- if (c == '\\') {
- backslash = 1;
- continue;
- }
- }
- putchar(c);
- }
+
+ my_puts(argv[i]);
}
- if (putnl)
+ if (put_newline)
putchar('\n');
return CMD_RET_SUCCESS;
diff --git a/avr/command.c b/avr/command.c
index b6fa418..ed25dee 100644
--- a/avr/command.c
+++ b/avr/command.c
@@ -120,7 +120,7 @@ command_ret_t _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp,
*/
for (i = 1; i < argc; ++i) {
if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL) {
- rcode = cmd_usage(cmdtp);
+ cmd_usage(cmdtp);
} else {
printf_P(PSTR("Unknown command '%s' - try 'help'"
" without arguments.\n\n"), argv[i]
@@ -149,8 +149,8 @@ cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
for (cmdtp = table;
cmdtp != table + table_len;
cmdtp++) {
- if (strncmp_P (cmd, cmdtp->name, len) == 0) {
- if (len == strlen (cmdtp->name))
+ if (strncmp_P(cmd, cmdtp->name, len) == 0) {
+ if (len == strlen_P(cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
diff --git a/avr/command_tbl.c b/avr/command_tbl.c
index cbd2382..3273093 100644
--- a/avr/command_tbl.c
+++ b/avr/command_tbl.c
@@ -16,6 +16,8 @@ extern command_ret_t do_env_default(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_env_set(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_env_save(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_loadf(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_loadcpm3(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_loadihex(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_go(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_restart(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_console(cmd_tbl_t *, int, int, char * const []);
@@ -79,9 +81,10 @@ CMD_TBL_ITEM(
),
CMD_TBL_ITEM(
echo, CONFIG_SYS_MAXARGS, 1, do_echo,
- "echo args to console",
- "[args..]\n"
- " - echo args to console; \\c suppresses newline"
+ "display a line of text",
+ "[-n] [argument ...]\n"
+ " - echo the argument(s) to console.\n"
+ " -n do not output the trailing newline"
),
CMD_TBL_ITEM(
sleep , 2, 1, do_sleep,
@@ -131,6 +134,20 @@ CMD_TBL_ITEM(
""
),
CMD_TBL_ITEM(
+ loadcpm3, 3, 0, do_loadcpm3,
+ "load CPM3.SYS file",
+ "[offset] [filename]\n"
+ " - Load CP/M 3 system file from FAT filesystem. This command makes\n"
+ " CPMLDR superfluous. Default filename is '"CONFIG_PATH_CPM3SYS"', but\n"
+ " uses environment variable '"ENV_PATH_CPM3SYS"', if set."
+),
+CMD_TBL_ITEM(
+ loadi, 2, 0, do_loadihex,
+ "load intel hex file over serial line",
+ "[[-]offset]\n"
+ " - load Intel-Hex-Record file over serial line with offset 'offset'"
+),
+CMD_TBL_ITEM(
go, 2, 0, do_go,
"start application at address 'addr'",
"addr\n"
@@ -149,7 +166,7 @@ CMD_TBL_ITEM(
""
),
CMD_TBL_ITEM(
- connect, 1, 1, do_console,
+ connect, 1, 0, do_console,
"Connect to CPU console i/o",
""
),
@@ -211,23 +228,21 @@ CMD_TBL_ITEM(
" - set address offset for memory commands to 'offset'"
),
CMD_TBL_ITEM(
- loop, 3, 1, do_mem_loop,
+ mloop, 3, 1, do_mem_loop,
"infinite loop on address range",
"address number_of_bytes"
),
-#ifdef CONFIG_LOOPW
CMD_TBL_ITEM(
- loopw, 4, 1, do_mem_loopw,
+ mloopw, 4, 1, do_mem_loopw,
"infinite write loop on address range",
"address number_of_bytes data_to_write"
),
-#endif /* CONFIG_LOOPW */
#ifdef CONFIG_CMD_MEMTEST
CMD_TBL_ITEM(
- mtest, 5, 1, do_mem_mtest,
+ mtest, 4, 1, do_mem_mtest,
"simple RAM read/write test",
- "[start [end [pattern [iterations]]]]"
+ "[start [end [iterations]]]"
),
#endif /* CONFIG_CMD_MEMTEST */
@@ -238,7 +253,7 @@ CMD_TBL_ITEM(
"address count delay(ms)"
),
CMD_TBL_ITEM(
- mwc, 4, 1, do_mem_mwc,
+ mwc, 4, 1, do_mem_mdc,
"memory write cyclic",
"address value delay(ms)"
),
diff --git a/avr/env.c b/avr/env.c
index 7be7d03..a947583 100644
--- a/avr/env.c
+++ b/avr/env.c
@@ -31,13 +31,17 @@
#define DELIM "\0"
const FLASH char default_env[] = {
- "bootdelay=" "3" DELIM
- "bootcmd=" "reset; loadf; go ${startaddr}" DELIM
- "baudrate=" "115200" DELIM
- "startaddr=" "0" DELIM
+ ENV_BAUDRATE "=" "115200" DELIM
+ ENV_BOOTDELAY "=" "3" DELIM
+ ENV_BOOTCMD "=" "reset; loadf; go ${startaddr}" DELIM
+ ENV_PATH_CPM3SYS "=" CONFIG_PATH_CPM3SYS DELIM
+ ENV_PINALIAS "=" "0:PG5,1:PG4,2:PB4,3:PB5,4:PB6,5:PB7,"
+ "6:PG3,7:PG2,8:PG1,9:PG0,10:PE7" DELIM
+ ENV_STARTADDRESS "=" "0" DELIM
DELIM
};
+
/* EEPROM storage */
typedef struct environment_s {
uint16_t crc; /* CRC16 over data bytes */
@@ -452,7 +456,6 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[])
env_item_t e, *ep;
(void) flag;
- debug("Initial value for argc=%d\n", argc);
name = argv[1];
value = argv[2];
@@ -519,15 +522,35 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[])
* @return 0 if ok, 1 on error
*/
static
-int setenv(const char *varname, const char *varvalue)
+int setenv(const MEMX char *varname, const char *varvalue)
{
- const char * const argv[3] = { NULL, varname, varvalue };
+ int rc;
+
+#ifdef __MEMX
+ char *tmpname = NULL;
+ if (__builtin_avr_flash_segment(varname) != -1) {
+ tmpname = malloc(strlen_P(varname)+1);
+ if (tmpname == NULL) {
+ printf_P(PSTR("setenv: Out of Memory!\n"));
+ return 1;
+ }
+ strcpy_P(tmpname, varname);
+ } else
+ tmpname = (char *) varname;
+#endif
+
+ const char * const argv[3] = { NULL, tmpname, varvalue };
int argc = 3;
if (varvalue == NULL || varvalue[0] == '\0')
--argc;
- return (int) _do_env_set(0, argc, (char * const *)argv);
+ rc = (int) _do_env_set(0, argc, (char * const *)argv);
+
+#ifdef __MEMX
+ free(tmpname);
+#endif
+ return rc;
}
/**
diff --git a/avr/main.c b/avr/main.c
index f4d4c6f..3852e75 100644
--- a/avr/main.c
+++ b/avr/main.c
@@ -12,7 +12,7 @@
#include <stdio.h>
#include "config.h"
-#include "debug.h"
+#include "ff.h"
#include "z80-if.h"
#include "i2c.h"
#include "con-utils.h"
@@ -24,6 +24,7 @@
#include "gpio.h"
#include "time.h"
#include "rtc.h"
+#include "debug.h"
uint8_t mcusr __attribute__ ((section (".noinit")));
@@ -145,6 +146,17 @@ void setup_system_time(void)
set_system_time(mk_gmtime(&rtc_time) );
}
+
+
+static void setup_fatfs(void)
+{
+ static FATFS FatFs0;
+ static FATFS FatFs1;
+
+ f_mount(&FatFs0, "0:", 0);
+ f_mount(&FatFs1, "1:", 0);
+}
+
/*--------------------------------------------------------------------------*/
/* Stored value of bootdelay, used by autoboot_command() */
@@ -261,14 +273,9 @@ int main(void)
print_reset_reason();
#endif
-#if DEBUG
- unsigned long i_speed = getenv_ulong(PSTR("i2c_clock"), 10, CONFIG_SYS_I2C_CLOCK);
- debug("### Setting I2C clock Frequency to %lu Hz.\n", i_speed);
- i2c_init(i_speed);
-#else
i2c_init(CONFIG_SYS_I2C_CLOCK);
-#endif
setup_system_time();
+ setup_fatfs();
printf_P(PSTR("\nATMEGA1281+Z8S180 Stamp Monitor\n\n"));
diff --git a/avr/z180-serv.c b/avr/z180-serv.c
index e0b763f..9b4228a 100644
--- a/avr/z180-serv.c
+++ b/avr/z180-serv.c
@@ -5,13 +5,28 @@
*/
#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
#include <util/atomic.h>
#include "background.h"
+#include "env.h"
+#include "ff.h"
#include "serial.h"
#include "z80-if.h"
#include "debug.h"
+#include "print-utils.h"
#include "z180-serv.h"
+#include "timer.h"
+
+
+#define DEBUG_CPM_SDIO 0 /* set to 1 to debug */
+
+#define debug_cpmsd(fmt, args...) \
+ debug_cond(DEBUG_CPM_SDIO, fmt, ##args)
+
+
/*--------------------------------------------------------------------------*/
@@ -52,6 +67,25 @@ uint32_t msg_to_addr(uint8_t *msg)
}
+static int msg_xmit_header(uint8_t func, uint8_t subf, int len)
+{
+ z80_memfifo_putc(fifo_msgout, 0xAE);
+ z80_memfifo_putc(fifo_msgout, len+2);
+ z80_memfifo_putc(fifo_msgout, func);
+ z80_memfifo_putc(fifo_msgout, subf);
+
+ return 0;
+}
+
+int msg_xmit(uint8_t func, uint8_t subf, int len, uint8_t *msg)
+{
+ msg_xmit_header(func, subf, len);
+ while (len--)
+ z80_memfifo_putc(fifo_msgout, *msg++);
+
+ return 0;
+}
+
void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
{
(void)len;
@@ -68,6 +102,241 @@ void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
putchar(*msg++);
}
+/* echo message */
+void do_msg_echo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf;
+
+ /* send re-echo */
+ msg_xmit(1, 3, len, msg);
+}
+
+/* ---------------------------------------------------------------------------*/
+
+#define MAX_DRIVE 4
+#define BLOCK_SIZE 512
+#define TPA_BASE 0x10000
+#define COMMON_BASE 0xC000
+
+struct cpm_drive_s {
+ uint8_t drv;
+ uint8_t device;
+ char *img_name;
+ FIL fd;
+};
+
+static uint8_t disk_buffer[BLOCK_SIZE];
+static struct cpm_drive_s drv_table[MAX_DRIVE];
+
+/*
+ db 2 ; disk command
+ ds 1 ; subcommand (login/read/write)
+ ds 1 ; @adrv (8 bits) +0
+ ds 1 ; @rdrv (8 bits) +1
+ ds 3 ; @xdph (24 bits) +2
+*/
+
+void do_msg_cpm_login(uint8_t subf, int len, uint8_t * msg)
+{
+
+ FRESULT res = 0;
+ uint8_t rc = 0;
+ uint8_t drv;
+ char *np;
+ uint8_t result_msg[3];
+
+ (void)subf;
+
+ if (len != 5) { /* TODO: check adrv, rdrv */
+ rc = 0x01;
+ goto out;
+ }
+
+ debug_cpmsd("\n## %7lu login: %c:\n", get_timer(0), msg[0]+'A');
+
+
+ drv = msg[0];
+ if ( drv>= MAX_DRIVE) {
+ rc = 0x02;
+ goto out;
+ }
+
+/*
+ uint32_t dph = ((uint32_t)msg[4] << 16) + ((uint16_t)msg[3] << 8) + msg[2];
+*/
+
+ if (drv_table[drv].img_name != NULL) {
+ debug_cpmsd("## %7lu close: '%s'\n", get_timer(0), drv_table[drv].img_name);
+ f_close(&drv_table[drv].fd);
+ free(drv_table[drv].img_name);
+ drv_table[drv].img_name = NULL;
+ }
+
+ strcpy_P((char *)disk_buffer, PSTR("dsk0"));
+ disk_buffer[3] = msg[0] + '0';
+ if (((np = getenv((char*)disk_buffer)) == NULL) ||
+ ((drv_table[drv].img_name = strdup(np)) == NULL)) {
+ rc = 0x03;
+ goto out;
+ }
+
+
+ res = f_open(&drv_table[drv].fd, drv_table[drv].img_name,
+ FA_WRITE | FA_READ);
+
+ debug_cpmsd("## %7lu open: '%s', (env: '%s'), res: %d\n", get_timer(0),
+ drv_table[drv].img_name, disk_buffer, res);
+
+out:
+
+ if (res)
+ rc |= 0x80;
+
+ result_msg[0] = rc;
+ result_msg[1] = res;
+ result_msg[2] = res >> 8;
+
+ if (rc) {
+ debug_cpmsd("## %7lu error rc: %.02x, res: %d\n", get_timer(0), rc, res);
+ };
+
+ /* send result*/
+ msg_xmit(2, subf, sizeof(result_msg), result_msg);
+}
+
+
+/*
+ db 2 ; disk command
+ ds 1 ; subcommand (login/read/write)
+ ds 1 ; @adrv (8 bits) +0
+ ds 1 ; @rdrv (8 bits) +1
+ ds 2 ; @trk (16 bits) +2
+ ds 2 ; @sect(16 bits) +4
+ ds 1 ; @cnt (8 bits) +6
+ ds 3 ; phys. transfer addr +7
+*/
+
+#define ADRV 0
+#define RDRV 1
+#define TRK 2
+#define SEC 4
+#define CNT 6
+#define ADDR 7
+
+void do_msg_cpm_rw(uint8_t subf, int len, uint8_t * msg)
+{
+ uint8_t drv;
+ uint32_t addr;
+ uint32_t pos;
+ uint8_t secs;
+ bool dowrite = (subf == 2);
+ FRESULT res = 0;
+ uint8_t rc = 0;
+ bool buserr = 0;
+ uint8_t result_msg[3];
+
+ if (len != 10) { /* TODO: check adrv, rdrv */
+ rc = 0x01;
+ goto out;
+ }
+
+ drv = msg[ADRV];
+ if ( drv>= MAX_DRIVE) {
+ rc = 0x02;
+ goto out;
+ }
+
+ secs = msg[CNT];
+ addr = ((uint32_t)msg[ADDR+2] << 16) + ((uint16_t)msg[ADDR+1] << 8) + msg[ADDR];
+
+
+ /* TODO: tracks per sector from dpb */
+ pos = (((uint16_t)(msg[TRK+1] << 8) + msg[TRK]) * 8
+ + ((uint32_t)(msg[SEC+1] << 8) + msg[SEC])) * BLOCK_SIZE;
+
+ debug_cpmsd("## %7lu cpm_rw: %s %c: trk:%4d, sec: %d, pos: %.8lx, secs: %2d, "
+ "addr: %.5lx\n", get_timer(0), dowrite ? "write" : " read",
+ msg[ADRV]+'A', ((uint16_t)(msg[TRK+1] << 8) + msg[TRK]), msg[SEC],
+ pos, msg[CNT], addr);
+
+ res = f_lseek(&drv_table[drv].fd, pos);
+ while (!res && secs--) {
+ unsigned int cnt, br;
+
+ /* check bank boundary crossing */
+ cnt = 0;
+ if (addr < (TPA_BASE + COMMON_BASE) &&
+ (addr + BLOCK_SIZE) > (TPA_BASE + COMMON_BASE)) {
+ cnt = (TPA_BASE + COMMON_BASE) - addr;
+ }
+
+ if (cnt) {
+ debug_cpmsd("## %67c addr: %.5lx, cnt: %3d\n", ' ', addr, cnt);
+ debug_cpmsd("## %67c addr: %.5lx, cnt: %3d\n", ' ', addr+cnt-TPA_BASE, BLOCK_SIZE-cnt);
+ }
+
+ if (dowrite) {
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ } else {
+ if (cnt) {
+ z80_read_block(disk_buffer, addr, cnt);
+ addr = addr + cnt - TPA_BASE;
+ }
+ z80_read_block(disk_buffer+cnt, addr, BLOCK_SIZE - cnt);
+ z80_bus_cmd(Release);
+ }
+ res = f_write(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &br);
+ } else {
+ res = f_read(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &br);
+ if (res == FR_OK && br == BLOCK_SIZE) {
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ } else {
+ if (cnt) {
+ z80_write_block(disk_buffer, addr, cnt);
+ addr = addr + cnt - TPA_BASE;
+ }
+ z80_write_block(disk_buffer+cnt, addr, BLOCK_SIZE - cnt);
+ z80_bus_cmd(Release);
+ }
+ }
+ }
+
+ if (br != BLOCK_SIZE) {
+ debug_cpmsd("## %7lu f_read res: %d, bytes rd/wr: %u\n", get_timer(0), res, br);
+ dump_ram(disk_buffer, 0, 64, "Read Data");
+ res = -1;
+ }
+
+ addr += BLOCK_SIZE;
+ }
+
+ if (dowrite && !res)
+ res = f_sync(&drv_table[drv].fd);
+
+out:
+ if (buserr) {
+ debug_cpmsd("Bus timeout\n");
+ rc = 0x03;
+ }
+ if (res)
+ rc |= 0x80;
+
+ result_msg[0] = rc;
+ result_msg[1] = res;
+ result_msg[2] = res >> 8;
+
+ if (rc) {
+ debug_cpmsd("###%7lu error rc: %.02x, res: %d\n", get_timer(0), rc, res);
+ }
+
+ /* send result*/
+ msg_xmit(2, subf, sizeof(result_msg), result_msg);
+}
+
const FLASH struct msg_item z80_messages[] =
{
@@ -77,6 +346,15 @@ const FLASH struct msg_item z80_messages[] =
{ 1,
1, 1,
do_msg_char_out},
+ { 1,
+ 2, 2,
+ do_msg_echo},
+ { 2,
+ 0, 0,
+ do_msg_cpm_login},
+ { 2,
+ 1, 2,
+ do_msg_cpm_rw},
{ 0xff, /* end mark */
0, 0,
0},
@@ -178,18 +456,27 @@ int msg_handling(int state)
if (pending) {
switch (state) {
- case 0:
+ case 0: /* need init */
+ /* Get address of fifo_list */
z80_bus_cmd(Request);
- uint32_t addr = z80_read(0x40) +
+ uint32_t fifo_list = z80_read(0x40) +
((uint16_t) z80_read(0x41) << 8) +
((uint32_t) z80_read(0x42) << 16);
z80_bus_cmd(Release);
- if (addr != 0) {
- z80_memfifo_init(fifo_msgin, addr);
- state = 1;
+ if (fifo_list != 0) {
+ /* Get address of fifo 0 */
+ z80_bus_cmd(Request);
+ uint32_t fifo_addr = z80_read(fifo_list) +
+ ((uint16_t) z80_read(fifo_list+1) << 8) +
+ ((uint32_t) z80_read(fifo_list+2) << 16);
+ z80_bus_cmd(Release);
+ if (fifo_addr != 0) {
+ z80_memfifo_init(fifo_msgin, fifo_addr);
+ state = 1;
+ }
}
break;
- case 1:
+ case 1: /* awaiting messages */
check_msg_fifo();
break;
}
@@ -218,6 +505,7 @@ void restart_z180_serv(void)
for (int i = 0; i < NUM_FIFOS; i++)
z80_memfifo_init(i, 0);
bg_setstat(handle_msg_handling, 0);
+
}
/*--------------------------------------------------------------------------*/
diff --git a/avr/z80-if.c b/avr/z80-if.c
index d5dc2d7..21ffeac 100644
--- a/avr/z80-if.c
+++ b/avr/z80-if.c
@@ -560,10 +560,9 @@ void z80_memfifo_init(const fifo_t f, uint32_t addr)
{
fifo_dsc[f].base = addr;
- if (addr != 0) {
-
DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, addr);
+ if (addr != 0) {
z80_bus_cmd(Request);
fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK);
fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN);