2024-09-13 01:17 AM - edited 2024-09-13 01:39 AM
Hi everyone, long story short is that i'm trying to use the system bootloader capabilities to handle updates over UART which open the possibility of OTA and everything goes smoothly until i need to write the new data, i've been pulling my hair off for 2 days now and can't get what i'm doing wrong, there's a very big possibility i'm just reading the datasheet wrong as well.
The write to user space code:
bool writeMemory(const uint32_t startAddress, const String& filepath) {
File file = tempFS.open(filepath);
if (!file.available())
{
LOG_ERROR("Failed to open binary file.");
return false;
}
uint32_t totalBytes = file.size();
LOG_INFO("Core file read: %d", totalBytes);
// Send Write Memory command: 0x31 and complement 0xCE
if (!sendCommand(0x31, 0xCE))
{
LOG_ERROR("Failed to send write memory command.");
return false;
}
LOG_INFO("Sent START_WRITE command.");
uint32_t currentAddress = startAddress;
const size_t sizeofBuf = 256u; // must be multiple of 4
uint8_t buffer[sizeofBuf] = {};
while (file.available()) {
// Read a chunk of data (up to 255 bytes)
size_t bytesRead = file.read(buffer, sizeofBuf);
LOG_INFO("We have %d bytes read.", bytesRead);
uint8_t padding = bytesRead % 4; // Ensure is a multiple of 4
// Calculate padding needed to make N+1 a multiple of 4
uint8_t N = bytesRead - 1 + padding; // Number of data bytes
// Send target address for this chunk
if (!sendAddress(currentAddress)) {
LOG_ERROR("Failed to send memory address.");
return false;
}
LOG_INFO("Sent ADDRESS command for address 0x%08X.", currentAddress);
// Send number of bytes to write
Serial1.write(N);
Serial1.flush();
LOG_INFO("Sent DATA_LENGTH: %d bytes.", N);
uint8_t checksum = N;
// Write the data and calculate the checksum
for (size_t i = 0; i < bytesRead; i++) {
Serial1.write(buffer[i]);
checksum ^= buffer[i]; // XOR each byte for checksum
}
// LOG_INFO("Checksum before padding: 0x%02X.", checksum);
// Add padding if needed
if (padding > 0) {
for (size_t i = 0; i < padding; i++) {
Serial1.write(0x00); // Send padding byte
checksum ^= 0x00; // XOR with 0 has no effect but for clarity
}
// LOG_INFO("Checksum after padding: 0x%02X.", checksum);
}
Serial1.flush();
// Send the checksum
Serial1.write(checksum);
Serial1.flush(); // Ensure all bytes are sent
LOG_INFO("Sent DATA with checksum: 0X%04X.", checksum);
// Wait for ACK after sending each chunk
if (!waitForAck()) {
LOG_ERROR("ACK not received.");
return false;
}
// Increment the address by the number of bytes read plus padding
currentAddress += N;
}
return true;
}
And here's the LOG output:
I (ota.cpp:495): Core firmware update initiated!
I (ota.cpp:496): COre firmware file size: 275856
E (ota.cpp:314): Bootloader communication established.
I (ota.cpp:174): Sent extended erase cmd.
I (ota.cpp:187): Sent special erase type: 0xFFFF
I (ota.cpp:194): Sent checksum: 0x00
I (ota.cpp:330): Flash space erased sucessfully.
I (ota.cpp:213): Core file read: 275856
I (ota.cpp:221): Sent START_WRITE command.
I (ota.cpp:232): We have 256 bytes read.
I (ota.cpp:245): Sent ADDRESS command for address 0x08000000.
I (ota.cpp:250): Sent DATA_LENGTH: 255 bytes.
I (ota.cpp:276): Sent DATA with checksum: 0X004B.
I (ota.cpp:232): We have 256 bytes read.
E (ota.cpp:31): Received NACK byte: 0x1F
E (ota.cpp:31): Received NACK byte: 0x1F
E (ota.cpp:31): Received NACK byte: 0x1F
E (ota.cpp:31): Received NACK byte: 0x1F
E (ota.cpp:31): Received NACK byte: 0x1F
E (ota.cpp:31): Received NACK byte: 0x1F
As you can see it writes once then struggles to loop again due to receiving NACKs on the second attempt to send the new address, is there a desired delay i should use between operations ?