Implement WRITE; refactor address parsing
This commit is contained in:
parent
07e5b74e83
commit
4dfb0d7edf
|
|
@ -30,11 +30,11 @@ void executeCommand(CommandLine cmdLine) {
|
||||||
}
|
}
|
||||||
else if (strcmp(cmdLine.command, "WRITE") == 0) {
|
else if (strcmp(cmdLine.command, "WRITE") == 0) {
|
||||||
// WRITE command: Takes a hex address as argument, reads data from UART and writes it to the EEPROM.
|
// WRITE command: Takes a hex address as argument, reads data from UART and writes it to the EEPROM.
|
||||||
commandRead(cmdLine.arg);
|
commandWrite(cmdLine.arg);
|
||||||
}
|
}
|
||||||
else if (strcmp(cmdLine.command, "ERASE") == 0) {
|
else if (strcmp(cmdLine.command, "ERASE") == 0) {
|
||||||
// ERASE command: Takes a hex address range as argument and writes 0x00 bytes to the specified range.
|
// ERASE command: Takes a hex address range as argument and writes 0x00 bytes to the specified range.
|
||||||
commandRead(cmdLine.arg);
|
commandErase(cmdLine.arg);
|
||||||
}
|
}
|
||||||
else if (strcmp(cmdLine.command, "TESTREAD") == 0) {
|
else if (strcmp(cmdLine.command, "TESTREAD") == 0) {
|
||||||
// TESTREAD command: for testing purposes, reads a few bytes and returns them in a human readable format.
|
// TESTREAD command: for testing purposes, reads a few bytes and returns them in a human readable format.
|
||||||
|
|
@ -111,7 +111,9 @@ void commandRead(char* arg) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Read a single block with up to DATA_BLOCK_SIZE bytes
|
// Read a single block with up to DATA_BLOCK_SIZE bytes
|
||||||
range.from = eepromReadBlock(range, &buffer);
|
Address nextAddress = eepromReadBlock(range, &buffer);
|
||||||
|
range.isValid = nextAddress.isValid;
|
||||||
|
range.from = nextAddress.value;
|
||||||
|
|
||||||
if (binary_mode) {
|
if (binary_mode) {
|
||||||
// Send block as binary "package":
|
// Send block as binary "package":
|
||||||
|
|
@ -144,6 +146,8 @@ void commandWrite(char* arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse address
|
// Parse address
|
||||||
|
Address startAddress = parseSingleAddress(arg);
|
||||||
|
if (!startAddress.isValid) {
|
||||||
uartPutLine("ERROR invalid address format");
|
uartPutLine("ERROR invalid address format");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -154,8 +158,65 @@ void commandWrite(char* arg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO read data from input and write to EEPROM
|
// Create data buffer
|
||||||
uartPutLine("ERROR not implemented");
|
uint8_t byteBuffer[DATA_BLOCK_SIZE];
|
||||||
|
DataBuffer buffer = {
|
||||||
|
.data = byteBuffer,
|
||||||
|
.maxSize = DATA_BLOCK_SIZE,
|
||||||
|
.bytes = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// "OK" indicates that data can be sent now.
|
||||||
|
uartPutLine("OK START");
|
||||||
|
|
||||||
|
Address currentAddress = startAddress;
|
||||||
|
uint8_t block_length = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Reset buffer
|
||||||
|
buffer.bytes = 0;
|
||||||
|
|
||||||
|
// Read and check block length
|
||||||
|
block_length = uartGetChar();
|
||||||
|
|
||||||
|
if (block_length > buffer.maxSize) {
|
||||||
|
uartPutString("ERROR maximal block size is: ");
|
||||||
|
uartPutInteger(buffer.maxSize);
|
||||||
|
uartPutLine(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data bytes
|
||||||
|
while (buffer.bytes < block_length) {
|
||||||
|
buffer.data[buffer.bytes++] = uartGetChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write blocks to EEPROM until an "end block" (0 bytes) is received
|
||||||
|
if (buffer.bytes > 0) {
|
||||||
|
currentAddress = eepromWriteBlock(currentAddress, buffer);
|
||||||
|
|
||||||
|
// TODO wait necessary?
|
||||||
|
//_delay_ms(100);
|
||||||
|
|
||||||
|
if (!currentAddress.isValid) {
|
||||||
|
uartPutLine("ERROR reached end of EEPROM while writing block");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (currentAddress.value == 0 || currentAddress.value >= HIGHEST_VALID_ADDRESS) {
|
||||||
|
// Block was written completely, but reached end of EEPROM now. No further data allowed (except for 0 byte "end block").
|
||||||
|
currentAddress.isValid = false;
|
||||||
|
uartPutLine("OK STOP (end of EEPROM)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Next block of data can be sent now.
|
||||||
|
uartPutLine("OK CONTINUE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (block_length > 0);
|
||||||
|
|
||||||
|
// WRITE completed
|
||||||
|
uartPutLine("OK END");
|
||||||
}
|
}
|
||||||
|
|
||||||
void commandErase() {
|
void commandErase() {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,12 @@ typedef uint16_t address_t;
|
||||||
// Define highest valid address for the EEPROM
|
// Define highest valid address for the EEPROM
|
||||||
#define HIGHEST_VALID_ADDRESS 0x7fff
|
#define HIGHEST_VALID_ADDRESS 0x7fff
|
||||||
|
|
||||||
|
// Type definition for a single address (nullable)
|
||||||
|
typedef struct {
|
||||||
|
bool isValid;
|
||||||
|
address_t value;
|
||||||
|
} Address;
|
||||||
|
|
||||||
// Type definition for address ranges (from-to)
|
// Type definition for address ranges (from-to)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool isValid;
|
bool isValid;
|
||||||
|
|
|
||||||
|
|
@ -115,12 +115,16 @@ void eepromWriteByte(address_t address, uint8_t data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read multiple bytes from EEPROM into a buffer
|
// Read multiple bytes from EEPROM into a buffer
|
||||||
address_t eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) {
|
Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) {
|
||||||
// Set read mode
|
// Set read mode
|
||||||
eepromSetReadMode();
|
eepromSetReadMode();
|
||||||
|
|
||||||
buffer->bytes = 0;
|
buffer->bytes = 0;
|
||||||
|
|
||||||
|
if (!addressRange.isValid) {
|
||||||
|
return (Address) {false, 0};
|
||||||
|
}
|
||||||
|
|
||||||
address_t currentAddress = addressRange.from;
|
address_t currentAddress = addressRange.from;
|
||||||
address_t highestAddress = addressRange.to;
|
address_t highestAddress = addressRange.to;
|
||||||
|
|
||||||
|
|
@ -130,20 +134,41 @@ address_t eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) {
|
||||||
|
|
||||||
while (currentAddress <= highestAddress && buffer->bytes < buffer->maxSize) {
|
while (currentAddress <= highestAddress && buffer->bytes < buffer->maxSize) {
|
||||||
buffer->data[buffer->bytes++] = eepromReadByte(currentAddress++);
|
buffer->data[buffer->bytes++] = eepromReadByte(currentAddress++);
|
||||||
|
|
||||||
|
// Handle integer overflow
|
||||||
|
if (currentAddress == 0) {
|
||||||
|
return (Address) {false, 0};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentAddress;
|
return (Address) {true, currentAddress};
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Write multiple bytes from a buffer to EEPROM
|
// Write multiple bytes from a buffer to EEPROM
|
||||||
// address_t eepromWriteBlock(address_t currentAddress, DataBuffer buffer) {
|
Address eepromWriteBlock(Address startAddress, DataBuffer buffer) {
|
||||||
// // Set write mode
|
// Set write mode
|
||||||
// eepromSetWriteMode();
|
eepromSetWriteMode();
|
||||||
|
|
||||||
// for (uint8_t i = 0; currentAddress <= HIGHEST_VALID_ADDRESS && i < buffer.bytes; i++) {
|
if (!startAddress.isValid) {
|
||||||
// eepromWriteByte(currentAddress++, buffer.data[i]);
|
return (Address) {false, 0};
|
||||||
// // TODO address overflow
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// return currentAddress;
|
address_t currentAddress = startAddress.value;
|
||||||
// }
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < buffer.bytes && currentAddress <= HIGHEST_VALID_ADDRESS; i++) {
|
||||||
|
eepromWriteByte(currentAddress++, buffer.data[i]);
|
||||||
|
|
||||||
|
// Handle integer overflow
|
||||||
|
if (currentAddress == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < buffer.bytes) {
|
||||||
|
// There are unwritten bytes left -> must be an address overflow
|
||||||
|
return (Address) {false, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Address) {true, currentAddress};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ uint8_t eepromReadByte(address_t address);
|
||||||
void eepromWriteByte(address_t address, uint8_t data);
|
void eepromWriteByte(address_t address, uint8_t data);
|
||||||
|
|
||||||
// Read multiple bytes from EEPROM into a buffer
|
// Read multiple bytes from EEPROM into a buffer
|
||||||
address_t eepromReadBlock(AddressRange addressRange, DataBuffer* buffer);
|
Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer);
|
||||||
|
|
||||||
// // Write multiple bytes from a buffer to EEPROM
|
// Write multiple bytes from a buffer to EEPROM
|
||||||
// address_t eepromWriteBlock(address_t addressRange, DataBuffer buffer);
|
Address eepromWriteBlock(Address startAddress, DataBuffer buffer);
|
||||||
|
|
||||||
#endif /* EEPROM_H_ */
|
#endif /* EEPROM_H_ */
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
// Command parsing
|
||||||
|
// ---------------
|
||||||
|
|
||||||
// Read and parse command line and dispatch command
|
// Read and parse command line and dispatch command
|
||||||
void parseNextCommand() {
|
void parseNextCommand() {
|
||||||
const int bufferLength = 80;
|
const int bufferLength = 80;
|
||||||
|
|
@ -66,8 +69,11 @@ CommandLine tokenizeCommand(char* cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address parsing
|
// Address parsing
|
||||||
bool parseSingleAddressTo(char* addressStr, address_t* address) {
|
// ---------------
|
||||||
if (addressStr == NULL || strlen(addressStr) != 4 || address == NULL) {
|
|
||||||
|
// Validates a single 2-byte hexadecimal address string "XXXX".
|
||||||
|
bool validateAddressString(char* addressStr) {
|
||||||
|
if (addressStr == NULL || strlen(addressStr) != 4) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,18 +83,19 @@ bool parseSingleAddressTo(char* addressStr, address_t* address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*address = strtol(addressStr, NULL, 16);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a single 2-byte hexadecimal address string "XXXX:YYYY" to an actual address.
|
// Parses a single 2-byte hexadecimal address string "XXXX" to an actual address.
|
||||||
AddressRange parseSingleAddress(char* addressStr) {
|
Address parseSingleAddress(char* addressStr) {
|
||||||
AddressRange range = {true, 0, 0};
|
Address address = {false, 0};
|
||||||
if (!parseSingleAddressTo(addressStr, &range.from)) {
|
|
||||||
return (AddressRange) {false, 0, 0};
|
if (validateAddressString(addressStr)) {
|
||||||
|
address.isValid = true;
|
||||||
|
address.value = strtol(addressStr, NULL, 16);
|
||||||
}
|
}
|
||||||
range.to = range.from;
|
|
||||||
return range;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a hexadecimal address range string "XXXX:YYYY" to actual addresses.
|
// Parses a hexadecimal address range string "XXXX:YYYY" to actual addresses.
|
||||||
|
|
@ -98,25 +105,29 @@ AddressRange parseAddressRange(char* addressStr) {
|
||||||
return (AddressRange) {false, 0, 0};
|
return (AddressRange) {false, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(addressStr);
|
int length = strlen(addressStr);
|
||||||
if (len != 4 && len != 9) {
|
|
||||||
return (AddressRange) {false, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == 9) {
|
if (length == 4) {
|
||||||
if (addressStr[4] != ':') {
|
Address address = parseSingleAddress(addressStr);
|
||||||
return (AddressRange) {false, 0, 0};
|
|
||||||
|
return (AddressRange) {
|
||||||
|
.isValid = address.isValid,
|
||||||
|
.from = address.value,
|
||||||
|
.to = address.value
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
else if (length == 9 && addressStr[4] == ':') {
|
||||||
addressStr[4] = '\0';
|
addressStr[4] = '\0';
|
||||||
|
Address fromAddress = parseSingleAddress(addressStr);
|
||||||
|
Address toAddress = parseSingleAddress(addressStr + 5);
|
||||||
|
|
||||||
|
return (AddressRange) {
|
||||||
|
.isValid = fromAddress.isValid && toAddress.isValid,
|
||||||
|
.from = fromAddress.value,
|
||||||
|
.to = toAddress.value
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
AddressRange range = parseSingleAddress(addressStr);
|
|
||||||
|
|
||||||
if (range.isValid && len == 9) {
|
|
||||||
if (!parseSingleAddressTo(addressStr + 5, &range.to)) {
|
|
||||||
return (AddressRange) {false, 0, 0};
|
return (AddressRange) {false, 0, 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ void parseNextCommand();
|
||||||
CommandLine readNextCommand(char* buffer, uint8_t bufferLength);
|
CommandLine readNextCommand(char* buffer, uint8_t bufferLength);
|
||||||
CommandLine tokenizeCommand(char* cmd);
|
CommandLine tokenizeCommand(char* cmd);
|
||||||
|
|
||||||
bool parseSingleAddressTo(char* addressStr, address_t* address);
|
bool validateAddressString(char* addressStr);
|
||||||
AddressRange parseSingleAddress(char* addressStr);
|
Address parseSingleAddress(char* addressStr);
|
||||||
AddressRange parseAddressRange(char* addressStr);
|
AddressRange parseAddressRange(char* addressStr);
|
||||||
|
|
||||||
#endif /* PARSING_H_ */
|
#endif /* PARSING_H_ */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue