Я хочу, чтобы приложение обновляло прошивку устройства с помощью пользовательской Код C#.
Функциональность должна быть аналогична esptool.py. Но я предпочитаю не использовать ни его, ни какую-либо внешнюю библиотеку.
Судя по собранной информации, процесс обновления в общих чертах выглядит следующим образом:
- войти в режим загрузчика
- отправить команду синхронизации
- стереть флэш-память
- записать новую флэш-память
- перезагрузить устройство
Повсюду есть попытки, и они есть. явных ошибок не обнаружено.
Я подозреваю, что причина кроется в неточных номерах команд и/или неправильном времени.
Далее пишется полный код. Есть какие-нибудь советы?
Спасибо!
// Update call
StartCoroutine(UpdateFirmware());
// ====================================================================
IEnumerator UpdateFirmware()
{
serialPort.BaudRate = 921600;
serialPort.ReadTimeout = 1;
yield return EnterBootloaderMode();
yield return SendSyncCommand();
yield return EraseFlash();
for (int i = 0; i < 4; i++) yield return WriteFlash(i);
serialPort.BaudRate = 115200;
serialPort.ReadTimeout = 90;
yield return ResetDevice();
AddLog("Firmware update completed!");
yield return null;
}
// --------------------------------------------------------------------
IEnumerator EnterBootloaderMode()
{
serialPort.DtrEnable = false;
serialPort.RtsEnable = false;
yield return new WaitForSecondsRealtime(1.5f);
serialPort.DtrEnable = true;
serialPort.RtsEnable = false;
yield return new WaitForSecondsRealtime(1.5f);
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
yield return new WaitForSecondsRealtime(1.5f);
}
// --------------------------------------------------------------------
IEnumerator SendSyncCommand()
{
byte[] syncCommand = new byte[] { 0x07, 0x07, 0x12, 0x20, 0x55, 0x55, 0x55, 0x55 };
try
{
serialPort.Write(syncCommand, 0, syncCommand.Length);
serialPort.BaseStream.Flush();
}
catch { AddLog("Sync Failed"); yield break; }
yield return new WaitForSecondsRealtime(2.0f);
}
// --------------------------------------------------------------------
IEnumerator EraseFlash()
{
byte[] eraseCommand = new byte[] { 0xC0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 };
try
{
serialPort.Write(eraseCommand, 0, eraseCommand.Length);
serialPort.BaseStream.Flush();
}
catch { AddLog("Erase Failed"); yield break; }
yield return new WaitForSecondsRealtime(6.0f);
}
// --------------------------------------------------------------------
IEnumerator WriteFlash(int id)
{
int offset = 0;
int packetSize = 1024;
byte[] fileBytes = firmwareData[id];
while (offset < fileBytes.Length)
{
int remaining = fileBytes.Length - offset;
int size = remaining < packetSize ? remaining : packetSize;
byte[] packet = new byte[size];
Array.Copy(fileBytes, offset, packet, 0, size);
// Prepare the command
byte[] writeCommand = new byte[8 + 4 + packet.Length];
writeCommand[0] = 0x02; // OpCode for write flash
// Length of the data including the address (4 bytes for address + data length)
int dataLength = 4 + packet.Length;
writeCommand[1] = (byte)(dataLength & 0xFF);
writeCommand[2] = (byte)((dataLength >> 8) & 0xFF);
writeCommand[3] = (byte)((dataLength >> 16) & 0xFF);
writeCommand[4] = (byte)((dataLength >> 24) & 0xFF);
// Checksum (simple sum of all data bytes)
byte checksum = 0;
foreach (byte b in packet) checksum ^= b;
writeCommand[5] = checksum;
// Reserved bytes
writeCommand[6] = 0x00;
writeCommand[7] = 0x00;
// Flash address
int[] flashAddress = new int[] {0xe000, 0x1000, 0x10000, 0x8000};
writeCommand[8] = (byte)(flashAddress[id] & 0xFF);
writeCommand[9] = (byte)((flashAddress[id] >> 8) & 0xFF);
writeCommand[10] = (byte)((flashAddress[id] >> 16) & 0xFF);
writeCommand[11] = (byte)((flashAddress[id] >> 24) & 0xFF);
// Data payload
Array.Copy(packet, 0, writeCommand, 12, packet.Length);
// Send the command
try { serialPort.Write(writeCommand, 0, writeCommand.Length); }
catch { AddLog($"Error writing packet #" + id); yield break; }
// Wait a bit before sending the next packet
offset += size;
yield return new WaitForSecondsRealtime(0.01f);
}
}
// --------------------------------------------------------------------
IEnumerator ResetDevice()
{
serialPort.DtrEnable = false;
serialPort.RtsEnable = true;
yield return new WaitForSecondsRealtime(1.5f);
}
// --------------------------------------------------------------------
Подробнее здесь: https://stackoverflow.com/questions/790 ... are-update
Мобильная версия