Finished first working version of the CLI. Dumps do not work if we select a byte count of 32768 (the max count). Programs are extremely slow compared to dumps, find the bottleneck.
This commit is contained in:
parent
e8bcd7c994
commit
58c74ebc86
4 changed files with 212 additions and 45 deletions
|
|
@ -23,6 +23,60 @@ bool isFirstWrite = true;
|
||||||
|
|
||||||
static char printBuff[128];
|
static char printBuff[128];
|
||||||
|
|
||||||
|
void program();
|
||||||
|
void dump();
|
||||||
|
|
||||||
|
void dumpFirts256Bytes() {
|
||||||
|
byte data;
|
||||||
|
Serial.println("Reading EEPROM");
|
||||||
|
for (int addr = 0; addr < 256; addr += 16) {
|
||||||
|
sprintf(printBuff, "%04x:", addr);
|
||||||
|
Serial.print(printBuff);
|
||||||
|
for (int offset = 0; offset < 16; offset++) {
|
||||||
|
sprintf(printBuff, " %02x", readEEPROM(addr + offset));
|
||||||
|
Serial.print(printBuff);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
pinMode(SHIFT_DATA, OUTPUT);
|
||||||
|
pinMode(SHIFT_CLK, OUTPUT);
|
||||||
|
pinMode(SHIFT_LATCH, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(EEPROM_WE, HIGH);
|
||||||
|
pinMode(EEPROM_WE, OUTPUT);
|
||||||
|
|
||||||
|
// Setting an invalid value.
|
||||||
|
lastOp = -1;
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
static byte command;
|
||||||
|
// The loop function only process commands.
|
||||||
|
while (Serial.available() == 0);
|
||||||
|
|
||||||
|
command = Serial.read();
|
||||||
|
|
||||||
|
switch(command) {
|
||||||
|
case 0x00:
|
||||||
|
// Program the eeprom.
|
||||||
|
program();
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
// Dump the eeprom.
|
||||||
|
dump();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Ignore invalid commands.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void latchOutput() {
|
void latchOutput() {
|
||||||
static byte latchMask = 0b00010000;
|
static byte latchMask = 0b00010000;
|
||||||
|
|
||||||
|
|
@ -119,12 +173,6 @@ byte readEEPROM(int address) {
|
||||||
return readBus(address);
|
return readBus(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a single byte of data to the specified address.
|
|
||||||
* If cooldown is true, the function adds a delay to avoid
|
|
||||||
* reading incorrect data after a write.
|
|
||||||
*/
|
|
||||||
void writeEEPROM(int address, byte data, bool pollOnPageChange) {
|
void writeEEPROM(int address, byte data, bool pollOnPageChange) {
|
||||||
// Since we're performing page writes, we must poll the data when we change page.
|
// Since we're performing page writes, we must poll the data when we change page.
|
||||||
if (
|
if (
|
||||||
|
|
@ -176,47 +224,36 @@ void disableSoftwareProtection() {
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpFirts256Bytes() {
|
void program() {
|
||||||
byte data;
|
// For now, the programmer will always write to the whole eeprom.
|
||||||
Serial.println("Reading EEPROM");
|
byte value;
|
||||||
for (int addr = 0; addr < 256; addr += 16) {
|
// The program will write byte by byte.
|
||||||
sprintf(printBuff, "%04x:", addr);
|
for (long addr = 0; addr < 32768; addr++) {
|
||||||
Serial.print(printBuff);
|
// Wait for next value.
|
||||||
for (int offset = 0; offset < 16; offset++) {
|
while(Serial.available() == 0);
|
||||||
sprintf(printBuff, " %02x", readEEPROM(addr + offset));
|
value = Serial.read();
|
||||||
Serial.print(printBuff);
|
writeEEPROM(addr, value, true);
|
||||||
}
|
// Send ack.
|
||||||
Serial.println();
|
Serial.write(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFirst256Bytes() {
|
void dump() {
|
||||||
Serial.println("Writing EEPROM");
|
long startAddress = 0;
|
||||||
for (uint16_t addr = 0; addr < 256; addr++) {
|
long byteCount = 0;
|
||||||
writeEEPROM(addr, 255 - addr, true);
|
byte value;
|
||||||
|
// Wait and read the starting address to dump.
|
||||||
|
while (Serial.available() < 2);
|
||||||
|
startAddress |= Serial.read();
|
||||||
|
startAddress |= Serial.read() << 8;
|
||||||
|
|
||||||
|
// Wait and read the byte count.
|
||||||
|
while (Serial.available() < 2);
|
||||||
|
byteCount |= Serial.read();
|
||||||
|
byteCount |= Serial.read() << 8;
|
||||||
|
|
||||||
|
for (int address = startAddress; address < startAddress + byteCount; address++ ) {
|
||||||
|
value = readEEPROM(address);
|
||||||
|
Serial.write(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
|
||||||
// put your setup code here, to run once:
|
|
||||||
pinMode(SHIFT_DATA, OUTPUT);
|
|
||||||
pinMode(SHIFT_CLK, OUTPUT);
|
|
||||||
pinMode(SHIFT_LATCH, OUTPUT);
|
|
||||||
|
|
||||||
digitalWrite(EEPROM_WE, HIGH);
|
|
||||||
pinMode(EEPROM_WE, OUTPUT);
|
|
||||||
|
|
||||||
// Setting an invalid value.
|
|
||||||
lastOp = -1;
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
|
||||||
|
|
||||||
writeFirst256Bytes();
|
|
||||||
Serial.println("Done writiing.");
|
|
||||||
dumpFirts256Bytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// put your main code here, to run repeatedly:
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
130
cli/cli.py
130
cli/cli.py
|
|
@ -0,0 +1,130 @@
|
||||||
|
import argparse
|
||||||
|
import time
|
||||||
|
import serial
|
||||||
|
|
||||||
|
|
||||||
|
def get_parsed_args():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparsers = parser.add_subparsers(title="Operation to perform", dest="operation")
|
||||||
|
|
||||||
|
program_parser = subparsers.add_parser("program")
|
||||||
|
dump_parser = subparsers.add_parser("dump")
|
||||||
|
|
||||||
|
# Parser for the "program" subcommand.
|
||||||
|
program_parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--file",
|
||||||
|
help="Binary file containing the program",
|
||||||
|
type=argparse.FileType("rb"),
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
program_parser.add_argument(
|
||||||
|
"-p", "--port", help="Serial port where programmer is located", required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parser for the dump subcommand.
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--file",
|
||||||
|
help="The file where the binary dump will be stored",
|
||||||
|
type=argparse.FileType("wb"),
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-p", "--port", help="Serial port where programmer is located", required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--start",
|
||||||
|
help="The address where to start dumping",
|
||||||
|
type=int,
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"-c",
|
||||||
|
"--byte-count",
|
||||||
|
help="The amount of bytes to dump",
|
||||||
|
type=int,
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dump_parser.add_argument(
|
||||||
|
"--display",
|
||||||
|
help="Print the dump to the screen after storing it to the file",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def program(args):
|
||||||
|
print("Programming...")
|
||||||
|
with serial.Serial(args.port, 115200) as ser:
|
||||||
|
# Give a chance to the arduino to reset.
|
||||||
|
# TODO: Arduino resets by default when opening a serial
|
||||||
|
# connection, there's ways to avoid this. Investigate more.
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Sending command
|
||||||
|
ser.write((0).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
bytesToWrite = args.file.read()
|
||||||
|
# Forward the bytes from the selected file
|
||||||
|
for i in range(32 * 1024):
|
||||||
|
# Show progress.
|
||||||
|
if i % 1024 == 0:
|
||||||
|
print(".", end="")
|
||||||
|
value = (bytesToWrite[i]).to_bytes(1, "big")
|
||||||
|
ser.write(value)
|
||||||
|
if value != ser.read():
|
||||||
|
# There was an error with the ack, finish early.
|
||||||
|
break
|
||||||
|
print("Done programming!")
|
||||||
|
|
||||||
|
|
||||||
|
def dump(args):
|
||||||
|
print("Dumping...")
|
||||||
|
with serial.Serial(args.port, 115200) as ser:
|
||||||
|
address = int(args.start)
|
||||||
|
byte_count = int(args.byte_count)
|
||||||
|
|
||||||
|
# Give a chance to the arduino to reset.
|
||||||
|
# TODO: Arduino resets by default when opening a serial
|
||||||
|
# connection, there's ways to avoid this. Investigate more.
|
||||||
|
print("Waiting for the arduino to reset...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Sending command
|
||||||
|
ser.write((1).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
# Sending address, low byte first.
|
||||||
|
ser.write((address & 0xFF).to_bytes(1, "big"))
|
||||||
|
ser.write(((address & 0xFF00) >> 8).to_bytes(1, "big"))
|
||||||
|
# Sending byte count, low byte first.
|
||||||
|
ser.write((byte_count & 0xFF).to_bytes(1, "big"))
|
||||||
|
ser.write(((byte_count & 0xFF00) >> 8).to_bytes(1, "big"))
|
||||||
|
|
||||||
|
# Read the stream coming from the Arduino and forward them
|
||||||
|
# to the user-selected dump file.
|
||||||
|
for _ in range(byte_count):
|
||||||
|
args.file.write(ser.read())
|
||||||
|
print("Done dumping!")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = get_parsed_args()
|
||||||
|
|
||||||
|
if args.operation == "program":
|
||||||
|
program(args)
|
||||||
|
elif args.operation == "dump":
|
||||||
|
dump(args)
|
||||||
|
else:
|
||||||
|
print("Unrecognized command, exiting now...")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
cli/dump.bin
Normal file
BIN
cli/dump.bin
Normal file
Binary file not shown.
BIN
cli/program.bin
Normal file
BIN
cli/program.bin
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue