I am very new to firmware updates and the whole zephyr rtos. I am trying to perform a firmware update using the mcumgr. I ran into some problems. I read the documentation, but it's not very well written and even the autor phrased that it isn't even complete. So the problem is that i split up my bin file into packets and add the header (i think this is working), but when the transfer completes, the firmware isn't uploaded to any slot on the device. I am learning and implementing this code from boogie https://github.com/boogie/mcumgr-web
This is my code. The DfuSend method runs on a button click.
public async void DfuSend()
{
if (SelectedFirmwareFile == null)
{
await Application.Current.MainPage.DisplayAlert("Error", "No file selected", "OK");
return;
}
var service = await Globals.ConnectedDevice.GetServiceAsync(GattIdentifiers.UartGattSMPServiceId);
if (service != null)
{
try
{
sendCharacteristic = await service.GetCharacteristicAsync(GattIdentifiers.UartGattSMPCharacteristicsId);
receiveCharacteristic = await service.GetCharacteristicAsync(GattIdentifiers.UartGattSMPCharacteristicsId);
uploadIsInProgress = true;
sendCharacteristic.WriteType = CharacteristicWriteType.WithoutResponse;
FirmwareFileBytes = File.ReadAllBytes(SelectedFirmwareFile.FullName);
while (uploadIsInProgress == true)
{
await _uploadNext();
HandleUploadProgress(_uploadOffset);
}
sendCharacteristic.WriteType = CharacteristicWriteType.WithResponse;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
else
{
await Application.Current.MainPage.DisplayAlert("Error", "No service found", "OK");
}
The header bytes definition:
byte MGMT_OP_READ = 0;
byte MGMT_OP_READ_RSP = 1;
byte MGMT_OP_WRITE = 2;
byte MGMT_OP_WRITE_RSP = 3;
// Groups
byte MGMT_GROUP_ID_OS = 0;
byte MGMT_GROUP_ID_IMAGE = 1;
byte MGMT_GROUP_ID_STAT = 2;
byte MGMT_GROUP_ID_CONFIG = 3;
byte MGMT_GROUP_ID_LOG = 4;
byte MGMT_GROUP_ID_CRASH = 5;
byte MGMT_GROUP_ID_SPLIT = 6;
byte MGMT_GROUP_ID_RUN = 7;
byte MGMT_GROUP_ID_FS = 8;
byte MGMT_GROUP_ID_SHELL = 9;
// OS group
byte OS_MGMT_ID_ECHO = 0;
byte OS_MGMT_ID_CONS_ECHO_CTRL = 1;
byte OS_MGMT_ID_TASKSTAT = 2;
byte OS_MGMT_ID_MPSTAT = 3;
byte OS_MGMT_ID_DATETIME_STR = 4;
byte OS_MGMT_ID_RESET = 5;
// Image group
byte IMG_MGMT_ID_STATE = 0;
byte IMG_MGMT_ID_UPLOAD = 1;
byte IMG_MGMT_ID_FILE = 2;
byte IMG_MGMT_ID_CORELIST = 3;
byte IMG_MGMT_ID_CORELOAD = 4;
byte IMG_MGMT_ID_ERASE = 5;
private int _seq = 0;
and the uploadnext method:
private async Task _uploadNext()
{
if (_uploadOffset >= SelectedFirmwareFile.Length)
{
uploadIsInProgress = false;
HandleUploadFinished();
return;
}
if (uploadIsInProgress == false)
return;
const int nmpOverhead = 8;
var message = new ImageData();
if (_uploadOffset == 0)
{
message.len = Convert.ToInt32(SelectedFirmwareFile.Length);
using (var sha = SHA256.Create())
{
message.sha = sha.ComputeHash(await File.ReadAllBytesAsync(SelectedFirmwareFile.FullName));
}
}
//the encode function that i am trying to implement
var length = _mtu - Encode(message).Length - nmpOverhead;
message.data = new byte[SelectedFirmwareFile.Length - _uploadOffset > length ? length : SelectedFirmwareFile.Length - _uploadOffset];
Array.Copy(await File.ReadAllBytesAsync(SelectedFirmwareFile.FullName), _uploadOffset, message.data, 0, message.data.Length);
_uploadOffset += message.data.Length;
await SendMessage(MGMT_OP_WRITE, MGMT_GROUP_ID_IMAGE, IMG_MGMT_ID_UPLOAD, message);
}
And then i need to send the packet and encode it using CBOR. There is my code for the SendMessage method (i am really sure that it doesn't work)
async Task SendMessage(byte op, byte group, byte id, ImageData data)
{
var cborMessage = CBORObject.FromObject(new { op, group, id, seq = _seq++, data });
await sendCharacteristic.WriteAsync(cborMessage.EncodeToBytes());
}
BTW the characteristics use the SMP id.
I'll appreciate every comment or an idea. Thank you and have a nice day