cancel
Showing results for 
Search instead for 
Did you mean: 

Write memory bootloader command issue

Zer0-bit
Associate II

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 ?

 

0 REPLIES 0