496 lines
18 KiB
C#
496 lines
18 KiB
C#
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
|
||
}
|
||
} |