45eceaaf61
I got bitten again, I've over-designed my solution. The last time it happened, it was that memory mapping thing I was wanting to add. The indirect memory access feature I was adding was to solve a specific problem: Allow Collapse OS to cross-compile directly on a AT28 EEPROM. It began well. As long as we were staying in the assembler realm, things were looking good. However, when we got into the xcomp realm (B260), things became ugly, and I had to creep up indirection where I didn't want to. All of this because I wanted to solve my initial problem in a slightly more generalized way. The broad idea was that these indirect memory access could allow xcomp into a broad kind of memory-like devices. This idea broke on the "@" part of the equation. If I want indirections to be two-way and allow xcomp to work properly, I have to add this indirection to FIND (and possibly others) and this just isn't practical or elegant. So, I'm taking a step back and accepting that the solution I design for now is exclusively for the AT28. What I'm thinking is to add a low-level hook for memory writing, at the assembly level.
78 lines
2.0 KiB
C
78 lines
2.0 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "common.h"
|
|
|
|
/* Push specified file to specified device running Forth and verify
|
|
* that the sent contents is correct.
|
|
*/
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc != 4) {
|
|
fprintf(stderr, "Usage: ./upload device memptr fname\n");
|
|
return 1;
|
|
}
|
|
unsigned int memptr = strtol(argv[2], NULL, 16);
|
|
FILE *fp = fopen(argv[3], "r");
|
|
if (!fp) {
|
|
fprintf(stderr, "Can't open %s.\n", argv[3]);
|
|
return 1;
|
|
}
|
|
fseek(fp, 0, SEEK_END);
|
|
unsigned int bytecount = ftell(fp);
|
|
fprintf(stderr, "memptr: 0x%04x bytecount: 0x%04x.\n", memptr, bytecount);
|
|
if (!bytecount) {
|
|
// Nothing to read
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
if (memptr+bytecount > 0xffff) {
|
|
fprintf(stderr, "memptr+bytecount out of range.\n");
|
|
fclose(fp);
|
|
return 1;
|
|
}
|
|
rewind(fp);
|
|
int fd = ttyopen(argv[1]);
|
|
if (fd < 0) {
|
|
fprintf(stderr, "Could not open %s\n", argv[1]);
|
|
return 1;
|
|
}
|
|
char s[0x40];
|
|
sprintf(s,
|
|
": _ 0x%04x 0x%04x DO KEY DUP .x I C! LOOP ; _",
|
|
memptr+bytecount, memptr);
|
|
sendcmd(fd, s);
|
|
|
|
int returncode = 0;
|
|
while (fread(s, 1, 1, fp)) {
|
|
putc('.', stderr);
|
|
fflush(stderr);
|
|
unsigned char c = s[0];
|
|
write(fd, &c, 1);
|
|
usleep(1000); // let it breathe
|
|
mread(fd, s, 2); // read hex pair
|
|
s[2] = 0; // null terminate
|
|
unsigned char c2 = strtol(s, NULL, 16);
|
|
if (c != c2) {
|
|
// mismatch!
|
|
unsigned int pos = ftell(fp);
|
|
fprintf(stderr, "Mismatch at byte %d! %d != %d.\n", pos, c, c2);
|
|
// we don't exit now because we need to "consume" our whole program.
|
|
returncode = 1;
|
|
}
|
|
usleep(1000); // let it breathe
|
|
}
|
|
readprompt(fd);
|
|
sendcmdp(fd, "FORGET _");
|
|
fprintf(stderr, "Done!\n");
|
|
fclose(fp);
|
|
if (fd > 0) {
|
|
close(fd);
|
|
}
|
|
return returncode;
|
|
}
|
|
|