From b536d3bfd6cd5840c06f1b281ff6c2824142d8e7 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Mon, 13 Apr 2020 14:41:02 -0400 Subject: [PATCH] rc2014: complete the EEPROM recipe --- drv/at28.fs | 10 +++--- recipes/rc2014/eeprom/README.md | 60 ++++++++++++--------------------- tools/common.c | 4 ++- tools/upload.c | 1 + 4 files changed, 30 insertions(+), 45 deletions(-) diff --git a/drv/at28.fs b/drv/at28.fs index 7c3ce85..03a7228 100644 --- a/drv/at28.fs +++ b/drv/at28.fs @@ -2,12 +2,12 @@ operation while doing the right thing. Checks data integrity and ABORT on mismatch. ) -( a n -- ) +( n a -- ) : AT28! - 2DUP C! SWAP - ( as long as writing operation is running, IO/6 will toggle at each - read attempt. We know that write is finished when we read the same - value twice. ) + 2DUP C! + ( as long as writing operation is running, IO/6 will toggle at each + read attempt. We know that write is finished when we read the same + value twice. ) BEGIN ( n1 a ) DUP C@ ( n1 a n2 ) OVER C@ ( n1 a n2 n3 ) diff --git a/recipes/rc2014/eeprom/README.md b/recipes/rc2014/eeprom/README.md index fed51ae..5f8f115 100644 --- a/recipes/rc2014/eeprom/README.md +++ b/recipes/rc2014/eeprom/README.md @@ -7,7 +7,8 @@ itself. ## Gathering parts -* A RC2014 Classic that could install the base recipe +* A RC2014 Classic +* `stage3.bin` from the base recipe * An extra AT28C64B * 1x 40106 inverter gates * Proto board, RC2014 header pins, wires, IC sockets, etc. @@ -32,52 +33,33 @@ in write protection mode, but I preferred building my own module. I don't think you need a schematic. It's really simple. -## Building the kernel +## Using the at28 driver -For this recipe to work, we need a block device for the `at28w` program to read -from. The easiest way to go around would be to use a SD card, but maybe you -haven't built a SPI relay yet and it's quite a challenge to do so. +The AT28 driver is at `drv/at28.fs` and is a pure forth source file so it's +rather easy to set up from the base Stage 3 binary: -Therefore, for this recipe, we'll have `at28w` read from a memory map and we'll -upload contents to write to memory through our serial link. - -`at28w` is designed to be ran as a "user application", but in this case, because -we run from a kernel without a filesystem and that `pgm` can't run without it, -we'll integrate `at28w` directly in our kernel and expose it as an extra shell -command (renaming it to `a28w` to fit the 4 chars limit). - -For all this to work, you'll need [glue code that looks like this](glue.asm). -Running `make` in this directory will produce a `os.bin` with that glue code -that you can install in the same way you did with the basic RC2014 recipe. - -If your range is different than `0x2000-0x3fff`, you'll have to modify -`AT28W_MEMSTART` before you build. + cat ../stage3.bin ../pre.fs ../../../drv/at28.fs ../run.fs > os.bin + ../../../emul/hw/rc2014/classic os.bin ## Writing contents to the AT28 -The memory map is configured to start at `0xd000`. The first step is to upload -contents at that address as documented in ["Load code in RAM and run it"][load]. +The driver provides `AT28!` which can be plugged in adev's `A!*`. -You have to know the size of the contents you've loaded because you'll pass it -as at argument to `a28w`. You can run: +It's not in the Stage 3 binary, but because it's a small piece of Forth code, +let's just run its definition code: - Collapse OS - > bsel 0 - > seek 00 0000 - > a28w + cat ../../../drv/at28.fs | ./stripfc | ./exec -It takes a little while to write. About 1 second per 0x100 bytes (soon, I'll -implement page writing which should make it much faster). +Then, upload your binary to some place in memory, for example `a000`. To do so, +run this from your modern computer: -If the program doesn't report an error, you're all good! The program takes care -of verifying each byte, so everything should be in place. You can verify -yourself by `peek`-ing around the `0x2000-0x3fff` range. + ./upload a000 -Note that to write a single byte to the AT28 eeprom, you don't need a special -program. You can, while you're in the `0x2000-0x3fff` range, run `poke 1` and -send an arbitrary char. It will work. The problem is with writing multiple -bytes: you have to wait until the eeprom is finished writing before writing to -a new address, something a regular `poke` doesn't do but `at28w` does. - -[load]: ../../../doc/load-run-code.md +Then, activate `AT28!` with `' AT28! A!* !` and then run +`0xa000 0x2000 AMOVE`. `AT28!` checks every myte for integrity, +so it there's no error, you should be fine. Your content is now on the EEPROM! +Why not upload content directly to `0x2000` after having activated `AT28!`? +Technically, you could. It was my first idea too. However, at the time of this +writing, I always get weird mismatch errors about halfway through. Maybe that +the ACIA interrupt does something wrong... diff --git a/tools/common.c b/tools/common.c index 82824a7..d0979cf 100644 --- a/tools/common.c +++ b/tools/common.c @@ -8,7 +8,9 @@ void mread(int fd, char *s, int count) { while (count) { - while (read(fd, s, 1) == 0); + while (read(fd, s, 1) == 0) { + usleep(1000); + } s++; count--; } diff --git a/tools/upload.c b/tools/upload.c index 3d34168..d0cac13 100644 --- a/tools/upload.c +++ b/tools/upload.c @@ -65,6 +65,7 @@ int main(int argc, char **argv) // we don't exit now because we need to "consume" our whole program. returncode = 1; } + usleep(1000); // let it breathe } mread(fd, s, 2); // "> " prompt sendcmdp(fd, "FORGET _");