Files
DT_BR_GUI/LFP_Manager/Forms/fmxFwUpdate.cs
2025-12-17 12:40:51 +09:00

496 lines
18 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using LFP_Manager.Function;
using LFP_Manager.Utils;
namespace LFP_Manager
{
public delegate void AutoTxSetEnvent(bool autoTx);
public delegate void SendDataUartEvent(ushort dev_addr, byte[] data, bool ReplyFlag, int type);
public partial class fmxFwUpdate : XtraForm
{
#region DEFINES
const int FW_UPDATE_START_ADDR = 0x08080000;
const int FW_UPDATE_END_ADDR = 0x080E0000 - 1;
const int FW_UPDATE_SECTOR_SIZE = 0x20000;
const int FW_UPDATE_PACKET_SIZE = 0x800;
const int APP_TO_BOOT = 0;
const int BOOT_TO_APP = 1;
#endregion
#region VARIABLES
private UInt32 SystemId = 0;
private byte[] fwdata;
private int fwsize;
private int FwStartAddr = 0;
private int FwCurrPosition = 0;
private int FwSentLength = 0;
private bool StopUpdate = true;
private DateTime UpdateStartTime;
private TimeSpan UpdateTime;
public event AutoTxSetEnvent OnAutoTxSet = null;
public event SendDataUartEvent OnSendUartData = null;
#endregion
#region CONSTRUCTORS
public fmxFwUpdate(int sID)
{
InitializeComponent();
SystemId = (UInt32)sID;
edTargetID.Text = sID.ToString();
fwdata = null;
fwsize = 0;
btnFwUpdate.Enabled = false;
lcItemFlashErase.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
lcItemFlashWrite.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
lcItemGotoBoot.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
lcItemGotoApp.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
}
#endregion
#region BUTTON EVENTS
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void btnFwUpdate_Click(object sender, EventArgs e)
{
if (edTargetID.Text == "")
{
MessageBox.Show("Please check target id !!");
return;
}
SystemId = Convert.ToUInt32(edTargetID.Text);
if (StopUpdate == true)
{
// Working mode change (Application --> Boot) - It need to be wait more than 1.5sec
OnAutoTxSet?.Invoke(false);
DisplayLabelUpdate("Goto Bootloader Mode");
RequestModeChange(APP_TO_BOOT);
UpdateStartTime = DateTime.Now;
btnFwUpdate.Text = "Cancel Update";
btnFwUpdate.Enabled = false;
for (int i = 0; i < 2000; i += 100)
{
Thread.Sleep(100);
Application.DoEvents();
}
btnFwUpdate.Enabled = true;
// Flash Erase
RequestFlashErase();
}
else
{
StopFwUpdate();
}
}
private void StopFwUpdate()
{
StopUpdate = true;
btnFwUpdate.Text = "Firmware Update";
pgUpdate.Position = 0;
//pgUpdate.Properties.Maximum = 0;
//lbUpdateProgress.Text = "-/-";
lbUpdateStatus.Text = "Stop Update";
}
public static byte[] ToByteArray(String HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
private void btnFind_Click(object sender, EventArgs e)
{
OpenFileDialog oDialog;
oDialog = new OpenFileDialog();
oDialog.DefaultExt = "*.*";
oDialog.Filter = "hex files (*.hex)|*.hex|All files (*.*)|*.*";
if (oDialog.ShowDialog() == DialogResult.OK)
{
edFilename.Text = oDialog.FileName;
int addr1 = 0;
int addr2 = 0;
string[] aline = File.ReadLines(edFilename.Text).ToArray();
for (int i = 0; i < aline.Length; i++)
{
byte[] a = ToByteArray(aline[i].Substring(1, aline[i].Length - 1));
switch (a[3])
{
case 0: // data record
addr2 = (int)((a[1] << 8) | a[2]) + a[0];
if (FwStartAddr == 0)
FwStartAddr = (int)((a[1] << 8) | a[2]);
break;
case 1: // End of file record. Usually, it is 00000001FF
break;
case 2: // Extended Segment address record. This indicates segment base address when 16 bits is not enough for addressing memory;
break;
case 3: // Start segment address record. Indicates initial segment base address.
break;
case 4: // Extended Linear Address Record allows 32 bit addressing.
addr1 = (int)((a[4] << 8) | a[5]);
break;
case 5: // Start Linear Address Record.
break;
}
}
int FwImageSize = (int)((addr1 << 16) + addr2 - FwStartAddr);
if ((FwImageSize % 128) > 0)
{
FwImageSize = ((FwImageSize / 128) + 1) * 128;
}
else
{
FwImageSize = ((FwImageSize / 128) + 0) * 128;
}
addr1 = 0;
addr2 = 0;
fwsize = FwImageSize;
fwdata = new byte[fwsize];
for (int i = 0; i < fwdata.Length; i++)
{
fwdata[i] = 0xFF;
}
for (int i = 0; i < aline.Length; i++)
{
byte[] a = ToByteArray(aline[i].Substring(1, aline[i].Length - 1));
switch (a[3])
{
case 0: // data record
addr2 = (int)((a[1] << 8) | a[2]);
int len = a[0];
for (int j = 0; j < len; j++)
{
fwdata[((addr1 << 16) + addr2) - FwStartAddr + j] = a[4 + j];
}
break;
case 1: // End of file record. Usually, it is 00000001FF
break;
case 2: // Extended Segment address record. This indicates segment base address when 16 bits is not enough for addressing memory;
break;
case 3: // Start segment address record. Indicates initial segment base address.
break;
case 4: // Extended Linear Address Record allows 32 bit addressing.
addr1 = (int)((a[4] << 8) | a[5]);
break;
case 5: // Start Linear Address Record.
break;
}
}
string strName = Path.GetFileName(edFilename.Text);
lbFileInfo.Text = string.Format("File Information");
lbFileInfo.Text += string.Format("\r\n - Filename: {0}", strName);
lbFileInfo.Text += string.Format("\r\n - File Version: {0}", strName.Substring(0, 12));
lbFileInfo.Text += string.Format("\r\n - File Size: {0:#,##0} bytes", fwsize);
lbFileInfo.Text += string.Format("\r\n - Packet Size: {0:#,##0} packets", fwsize / 128);
lbFileInfo.Text += string.Format("\r\n - Last packet: {0:#,##0}", fwsize % 128);
lbFileInfo.Text += string.Format("\r\n - Start Addr : 0x{0:X8}", FwStartAddr);
lbUpdateProgress.Text = string.Format("{0:#,##0}/{1:#,##0} bytes", 0, fwsize);
pgUpdate.Properties.Maximum = (int)fwsize;
btnFwUpdate.Enabled = true;
}
}
#endregion
#region FORM EVENT
private void fmxFwUpdate_Activated(object sender, EventArgs e)
{
//OnAutoTxSet?.Invoke(false);
}
private void fmxFwUpdate_FormClosed(object sender, FormClosedEventArgs e)
{
OnAutoTxSet?.Invoke(true);
}
#endregion
#region PUBLIC FUNCTION
void DisplayLabelUpdate(string msg)
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate ()
{
lbUpdateStatus.Text = string.Format("Update Status : {0}", msg);
}));
}
else
{
lbUpdateStatus.Text = string.Format("Update Status : {0}", msg);
}
}
void DisplayUpdateProgress()
{
if (this.InvokeRequired)
{
_ = this.Invoke(new MethodInvoker(delegate ()
{
lbUpdateProgress.Text = string.Format("{0:#,##0}/{1:#,##0} bytes", FwCurrPosition, fwsize);
pgUpdate.Position = FwCurrPosition;
UpdateTime = DateTime.Now - UpdateStartTime;
lbUpdateTime.Text = string.Format("{0:mm}:{0:ss}", UpdateTime);
}));
}
else
{
lbUpdateProgress.Text = string.Format("{0:#,##0}/{1:#,##0} bytes", FwCurrPosition, fwsize);
pgUpdate.Position = FwCurrPosition;
UpdateTime = DateTime.Now - UpdateStartTime;
lbUpdateTime.Text = string.Format("{0:mm}:{0:ss}", UpdateTime);
}
}
public void RecvData(byte[] rdata)
{
//lbUpdateStatus.Text = String.Format("Recv Data: 0x{0:X8} {1:X2} {2:X2} {3:X2} {4:X2} {5:X2} {6:X2} {7:X2} {8:X2}"
// , rhdr, rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6], rdata[7]);
if (StopUpdate == false)
{
if (rdata[0] == 0x7F)
{
switch (rdata[1])
{
case 0x43: // Erase Flash
if (rdata[2] == 0x79)
{
// Erase Success
DisplayLabelUpdate("Flash Erase Success");
byte[] sdata = new byte[128];
FwCurrPosition = 0;
for (int i = 0; i < sdata.Length; i++)
{
sdata[i] = fwdata[FwCurrPosition + i];
}
RequestFlashWrite(FwStartAddr + FwCurrPosition, sdata);
}
else if (rdata[2] == 0x1F)
{
// Erase Fail
DisplayLabelUpdate("Flash Erase Fail");
StopUpdate = true;
}
break;
case 0x31: // Write Flash
if (rdata[2] == 0x79)
{
// Write Success
string str = string.Format("Flash Write Success - {0}/{1}", FwCurrPosition, FwSentLength);
DisplayLabelUpdate(str);
DisplayUpdateProgress();
FwCurrPosition += FwSentLength;
int Remain = fwdata.Length - FwCurrPosition;
if (Remain > 0)
{
int len = (Remain > 128) ? 128 : Remain;
byte[] sdata = new byte[len];
for (int i = 0; i < sdata.Length; i++)
{
sdata[i] = fwdata[FwCurrPosition + i];
}
RequestFlashWrite(FwStartAddr + FwCurrPosition, sdata);
}
else
{
RequestModeChange(BOOT_TO_APP);
// Write Success
str = string.Format("Complete Update - {0}/{1}", FwCurrPosition, FwSentLength);
DisplayLabelUpdate(str);
DisplayUpdateProgress();
//MessageBox.Show("Complete Firmware Update", "Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else if (rdata[2] == 0x1F)
{
// Write Fail
DisplayLabelUpdate("Flash Write Fail");
StopUpdate = true;
}
break;
}
}
}
}
#endregion
#region UART PACKET FUNCTION
private void RequestModeChange(int mode)
{
byte[] sdata = null;
byte[] crc;
if (mode == 0)
{
// Normal mode --> Bootloader mode
sdata = new byte[8];
sdata[0] = (byte)SystemId; // Dev Address
sdata[1] = 0x50; // Function Code
sdata[2] = 0x80; // Address H
sdata[3] = 0x00; // Address L
sdata[4] = 0x00; // Number of Register H
sdata[5] = 0x00; // Number of Register L
crc = csSerialCommFunction.GetCRC(sdata, 6);
sdata[6] = crc[1]; // CRCH
sdata[7] = crc[0]; // CRCL
StopUpdate = false;
}
else if (mode == 1)
{
// Bootloader mode --> Normal mode
sdata = new byte[5];
sdata[0] = 0x7F; // Dev Address
sdata[1] = 0x21; // Function Code,,+
sdata[2] = 0xDE; // Sub Code
crc = csSerialCommFunction.GetCRC(sdata, 3);
sdata[3] = crc[1]; // CRCH
sdata[4] = crc[0]; // CRCL
StopFwUpdate();
}
OnSendUartData?.Invoke((ushort)SystemId, sdata, false, 0);
}
private void RequestFlashErase()
{
byte[] sdata = null;
byte[] crc;
// Flash Erase
sdata = new byte[5];
sdata[0] = 0x7F; // Dev Address
sdata[1] = 0x43; // Function Code
sdata[2] = 0xBC; // Sub Code
crc = csSerialCommFunction.GetCRC(sdata, 3);
sdata[3] = crc[1]; // CRCH
sdata[4] = crc[0]; // CRCL
OnSendUartData?.Invoke((ushort)SystemId, sdata, true, 0);
}
private void RequestFlashWrite(int addr, byte[] data)
{
byte[] sdata = null;
byte[] crc;
// Flash Write
sdata = new byte[6 + 128 + 2];
for (int i = 0; i < sdata.Length; i++)
{
sdata[i] = 0xFF;
}
sdata[0] = 0x7F; // Dev Address
sdata[1] = 0x31; // Function Code
sdata[2] = 0xCE; // Sub Code
sdata[3] = (byte)(addr >> 16); // Addr H
sdata[4] = (byte)(addr >> 8); // Addr L MSB
sdata[5] = (byte)(addr & 0xff); // Addr L LSB
for (int i = 0; i < data.Length; i++)
{
sdata[6 + i] = data[i];
}
crc = csSerialCommFunction.GetCRC(sdata, sdata.Length - 2);
sdata[sdata.Length - 2] = crc[1]; // CRCH
sdata[sdata.Length - 1] = crc[0]; // CRCL
FwSentLength = data.Length;
OnSendUartData?.Invoke((ushort)SystemId, sdata, false, 0);
}
#endregion
#region BUTTON EVENT
private void btnGotoBoot_Click(object sender, EventArgs e)
{
OnAutoTxSet?.Invoke(false);
RequestModeChange(APP_TO_BOOT);
UpdateStartTime = DateTime.Now;
}
private void btnGotoApp_Click(object sender, EventArgs e)
{
RequestModeChange(BOOT_TO_APP);
}
private void btnFlashErase_Click(object sender, EventArgs e)
{
RequestFlashErase();
}
private void btnFlashWrite_Click(object sender, EventArgs e)
{
byte[] sdata = new byte[128];
FwCurrPosition = 0;
for (int i = 0; i < sdata.Length; i++)
{
sdata[i] = fwdata[FwCurrPosition + i];
}
RequestFlashWrite(FwStartAddr + FwCurrPosition, sdata);
}
#endregion
}
}