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.DataStructure; using LFP_Manager.Function; using LFP_Manager.Utils; using static System.Data.Entity.Infrastructure.Design.Executor; namespace LFP_Manager { public delegate void AutoTxCanSetEnvent(bool autoTx); public delegate void SendDataCanEvent(uint header, byte[] data); public partial class fmxFwUpdate : DevExpress.XtraEditors.XtraForm { #region DEFINES const int FW_UPDATE_START_ADDR = 0x8012000; const int FW_UPDATE_END_ADDR = 0x801FFFF; const int FW_UPDATE_SECTOR_SIZE = 0x20000; const int FW_UPDATE_PACKET_SIZE = 0x800; #endregion #region VARIABLES private uint SystemId = 0; private byte[] fwdata; private byte[] fwver; private bool StopUpdate = true; private uint SectorEraseAddr = 0; private uint SetAddr = 0; private uint SetLength = 0; private int WR_PACKET_DELAY = 1; private DateTime UpdateStartTime; private TimeSpan UpdateTime; private CommConfig Config; public event AutoTxCanSetEnvent OnAutoTxCanSet = null; public event SendDataCanEvent OnSendDataCan = null; #endregion #region CONSTRUCTORS public fmxFwUpdate(uint MdID, CommConfig aConfig) { InitializeComponent(); SystemId = MdID; teModuleNo.Text = string.Format("{0}", SystemId); fwdata = null; fwver = null; btnFwUpdate.Enabled = false; Config = aConfig; if (csCanConstData.CanDeviceInfo.DeviceIds[Config.CanDevice] == csCanConstData.CanDeviceInfo.VCI_VALUE_CAN4_1) WR_PACKET_DELAY = 10; else WR_PACKET_DELAY = 1; } #endregion #region KEY EVENT FUNCTION private void TextBox_KeyPress(object sender, KeyPressEventArgs e) { csUtils.TypingOnlyNumber(sender, e, true, true); } #endregion #region BUTTON EVENTS private void btnClose_Click(object sender, EventArgs e) { Close(); } private void btnFwUpdate_Click(object sender, EventArgs e) { if (teModuleNo.Text == "") { MessageBox.Show("Please check module no", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } uint sId = Convert.ToUInt32(teModuleNo.Text); if ((sId == 0) || (sId > 18)) { MessageBox.Show("Please check module no", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } SystemId = sId; if (StopUpdate) { teModuleNo.Enabled = false; if (OnSendDataCan != null) { if (OnAutoTxCanSet != null) { OnAutoTxCanSet(false); } if ((fwdata != null) && (fwdata.Length > 0)) { UpdateStartTime = DateTime.Now; PACKET_DN packet = csCanFwUpdateFunction.FwUpdateStartPacket(SystemId, fwver, (UInt32)fwdata.Length); OnSendDataCan(packet.hdr, packet.data); } StopUpdate = false; btnFwUpdate.Text = "Cancel Update"; } } else { teModuleNo.Enabled = true; StopUpdate = true; SectorEraseAddr = 0; SetAddr = 0; SetLength = 0; FirmwareUpdateTimeoutClear(); pgUpdate.Position = 0; lbUpdateStatus.Text = "Update Status : Cancel By User"; btnFwUpdate.Text = "Firmware Update"; if (OnAutoTxCanSet != null) { OnAutoTxCanSet(true); } } } private void btnFind_Click(object sender, EventArgs e) { OpenFileDialog oDialog; oDialog = new OpenFileDialog(); oDialog.DefaultExt = "*.*"; oDialog.Filter = "bin files (*.bin)|*.bin|All files (*.*)|*.*"; if (oDialog.ShowDialog() == DialogResult.OK) { edFilename.Text = oDialog.FileName; FileStream fwFile = new FileStream(edFilename.Text, FileMode.Open, FileAccess.Read); long fsize = fwFile.Length; if (fsize > 0) { fwdata = new byte[fsize]; fwFile.Seek(0, SeekOrigin.Begin); fwFile.Read(fwdata, 0, (int)fsize); } fwFile.Close(); byte[] bName = csUtils.StringToByte(Path.GetFileName(edFilename.Text)); if (bName.Length > 8) { fwver = new byte[4]; for (int i = 0; i < 4; i++) fwver[i] = (byte)(bName[bName.Length - 1 - 3 - 4 + i] - 0x30); UInt32 nPC = (UInt32)((fwdata[0] << 0) | (fwdata[1] << 8) | (fwdata[2] << 16) | (fwdata[3] << 24)); UInt32 nSP = (UInt32)((fwdata[4] << 0) | (fwdata[5] << 8) | (fwdata[6] << 16) | (fwdata[7] << 24)); if ((nPC >= 0x20000000) && (nPC <= 0x20100000) && (nSP >= 0x08000000) && (nSP <= 0x08100000)) { btnFwUpdate.Enabled = true; } else { nPC = (UInt32)((fwdata[0 + 64] << 0) | (fwdata[1 + 64] << 8) | (fwdata[2 + 64] << 16) | (fwdata[3 + 64] << 24)); nSP = (UInt32)((fwdata[4 + 64] << 0) | (fwdata[5 + 64] << 8) | (fwdata[6 + 64] << 16) | (fwdata[7 + 64] << 24)); if ((nPC >= 0x20000000) && (nPC <= 0x20100000) && (nSP >= 0x08000000) && (nSP <= 0x08100000)) { fsize -= 64; byte[] fwdataB = new byte[fsize]; for (int i = 0; i < fsize; i++) { fwdataB[i] = fwdata[i + 64]; } fwdata = new byte[fsize]; for (int i = 0; i < fsize; i++) { fwdata[i] = fwdataB[i]; } btnFwUpdate.Enabled = true; } else { btnFwUpdate.Enabled = false; } } lbFileInfo.Text = String.Format("File Information"); lbFileInfo.Text += String.Format("\r\n - Filename: {0}", Path.GetFileName(edFilename.Text)); lbFileInfo.Text += String.Format("\r\n - File Version: V{0}.{1}.{2}.{3}", fwver[0], fwver[1], fwver[2], fwver[3]); lbFileInfo.Text += String.Format("\r\n - File Size: {0:#,##0} bytes", fsize); lbFileInfo.Text += String.Format("\r\n - File Size: {0:#,##0} bytes", fsize); lbFileInfo.Text += String.Format("\r\n - Packet Size: {0:#,##0} packets", fsize / 2048); lbFileInfo.Text += String.Format("\r\n - Last packet: {0:#,##0}", fsize % 2048); lbFileInfo.Text += String.Format("\r\n - PC: 0x{0:X8}", nPC); lbFileInfo.Text += String.Format("\r\n - SP: 0x{0:X8}", nSP); lbUpdateProgress.Text = String.Format("{0:#,##0}/{1:#,##0} bytes", 0, fsize); pgUpdate.Properties.Maximum = (int)fsize; } } } private void btnRestart_Click(object sender, EventArgs e) { PACKET_DN packet = csCanFwUpdateFunction.UpdateRestartPacket(SystemId, 1); OnSendDataCan?.Invoke(packet.hdr, packet.data); } #endregion #region FORM EVENT private void fmxFwUpdate_Activated(object sender, EventArgs e) { if (OnAutoTxCanSet != null) { OnAutoTxCanSet(false); } } private void fmxFwUpdate_FormClosed(object sender, FormClosedEventArgs e) { if (OnAutoTxCanSet != null) { OnAutoTxCanSet(true); } } #endregion #region PUBLIC FUNCTION public void RecvData(UInt32 rhdr, byte[] rdata) { PACKET_HEADER_DN dnHdr = csCanFwUpdateFunction.CovertPtoH(rhdr); 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 (dnHdr.SID == SystemId) { FirmwareUpdateTimeoutClear(); switch (dnHdr.FC) { case csCanFwUpdateFunction.DL_START_CODE: FwUpdateStartProcess(dnHdr, rdata); break; case csCanFwUpdateFunction.DL_SECTOR_ERASE_CODE: SectorEraseProcess(dnHdr, rdata); break; case csCanFwUpdateFunction.DL_SET_ADDRESS_CODE: SeAddrProcess(dnHdr, rdata); break; case csCanFwUpdateFunction.DL_WRITE_DATA_CSUM_CODE: WritedataChkSumProcess(dnHdr, rdata); break; case csCanFwUpdateFunction.DL_IMAGE_CSUM_CODE: FwImageChkSumProcess(dnHdr, rdata); break; case csCanFwUpdateFunction.DL_RESTART_CODE: FirmwareUpdateStop(); break; } } } } #endregion #region FW UPDATE PROCESS FUNCTIONS private void FwUpdateStartProcess(PACKET_HEADER_DN hdr, byte[] data) { byte rResult = data[7]; if (rResult == 0) { if (OnSendDataCan != null) { if ((fwdata != null) && (fwdata.Length > 0)) { UpdateStartTime = DateTime.Now; SectorEraseAddr = FW_UPDATE_START_ADDR; PACKET_DN packet = csCanFwUpdateFunction.SectorErasePacket(SystemId, FW_UPDATE_START_ADDR); OnSendDataCan?.Invoke(packet.hdr, packet.data); } } } else { MessageBox.Show(String.Format("FwUpdateStartProcess Fail - {0}", rResult)); } } private void SectorEraseProcess(PACKET_HEADER_DN hdr, byte[] data) { UInt32 rAddr = (UInt32)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0)); byte rResult = data[7]; UInt32 eSize = rAddr - FW_UPDATE_START_ADDR + FW_UPDATE_SECTOR_SIZE; if (rResult == 0) { if (eSize < fwdata.Length) { SectorEraseAddr += FW_UPDATE_SECTOR_SIZE; PACKET_DN packet = csCanFwUpdateFunction.SectorErasePacket(SystemId, SectorEraseAddr); OnSendDataCan?.Invoke(packet.hdr, packet.data); } else { SetAddr = FW_UPDATE_START_ADDR; SetLength = 2048 / 8; PACKET_DN packet = csCanFwUpdateFunction.SetAddrPacket(SystemId, SetAddr, SetLength); OnSendDataCan?.Invoke(packet.hdr, packet.data); } } else { MessageBox.Show(String.Format("SectorEraseProcess Fail - {0}", rResult)); } } private void SeAddrProcess(PACKET_HEADER_DN hdr, byte[] data) { byte rResult = data[7]; if (rResult == 0) { UInt32 csum32 = 0; UInt32 CurrentAddr = SetAddr - FW_UPDATE_START_ADDR; UInt32 CurrentLen = SetLength; byte[][] pData; PACKET_DN packet; pData = new byte[CurrentLen][]; for (int i = 0; i < CurrentLen; i++) { pData[i] = new byte[8]; for (int j = 0; j < 8; j++) { if ((CurrentAddr + (i * 8) + j) < fwdata.Length) pData[i][j] = fwdata[CurrentAddr + (i * 8) + j]; else pData[i][j] = 0x00; csum32 += (UInt32)pData[i][j]; } packet = csCanFwUpdateFunction.WritePacket(SystemId, (byte)i, pData[i]); OnSendDataCan?.Invoke(packet.hdr, packet.data); pgUpdate.Position += 8; UpdateTime = DateTime.Now - UpdateStartTime; lbUpdateTime.Text = String.Format("{0:mm}:{1:ss}", UpdateTime, UpdateTime); lbUpdateProgress.Text = String.Format("{0:#,##0}/{1:#,##0} bytes", pgUpdate.Position, fwdata.Length); Thread.Sleep(WR_PACKET_DELAY); Application.DoEvents(); if (StopUpdate) { return; } } packet = csCanFwUpdateFunction.WriteChkSumPacket(SystemId, SetAddr, csum32); OnSendDataCan?.Invoke(packet.hdr, packet.data); } else { MessageBox.Show(String.Format("SeAddrProcess Fail - {0}", rResult)); } } //private void WritedataChkSumProcess(PACKET_HEADER_DN hdr, byte[] data) //{ // byte rResult = data[7]; // if (rResult == 0) // { // UInt32 csum32 = 0; // CurrentAddr += 1; // byte[][] pData; // PACKET_DN packet; // int plen = 256; // int blen = (int)(fwdata.Length - (CurrentAddr * 2048)); // if (blen < 2048) // plen = ((blen % 8) > 0) ? (blen / 8) + 1 : blen / 8; // pData = new byte[plen][]; // for (int i = 0; i < plen; i++) // { // pData[i] = new byte[8]; // for (int j = 0; j < 8; j++) // { // pData[i][j] = fwdata[(CurrentAddr * 2048) + (i * 8) + j]; // csum32 += (UInt32)pData[i][j]; // } // packet = csCanFwUpdateFunction.WritePacket(1, (byte)i, pData[i]); // OnSendDataCan?.Invoke(packet.hdr, packet.data); // Thread.Sleep(1); // } // packet = csCanFwUpdateFunction.WriteChkSumPacket(1, csum32); // OnSendDataCan?.Invoke(packet.hdr, packet.data); // } //} private void WritedataChkSumProcess(PACKET_HEADER_DN hdr, byte[] data) { byte rResult = data[7]; if (rResult == 0) { UInt32 rAddr; UInt32 rlen, tlen; rAddr = (UInt32)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0) ); rlen = rAddr - SetAddr; tlen = rAddr - FW_UPDATE_START_ADDR; UpdateTime = DateTime.Now - UpdateStartTime; lbUpdateTime.Text = String.Format("{0:mm}:{0:ss}", UpdateTime); lbUpdateProgress.Text = String.Format("{0:#,##0}/{1:#,##0} bytes", tlen, fwdata.Length); pgUpdate.Position = (int)tlen; if (tlen < fwdata.Length) { // remain write data if (rlen == FW_UPDATE_PACKET_SIZE) { SetAddr = rAddr; UInt32 alen = (UInt32)(fwdata.Length - tlen); if (alen > FW_UPDATE_PACKET_SIZE) { SetLength = FW_UPDATE_PACKET_SIZE / 8; } else { if ((alen % 8) > 0) SetLength = alen / 8 + 1; else SetLength = alen / 8; } PACKET_DN packet = csCanFwUpdateFunction.SetAddrPacket(SystemId, SetAddr, SetLength); OnSendDataCan?.Invoke(packet.hdr, packet.data); } } else { // finished write data //string text = String.Format("Finished Write data - {0};{1}", tlen, fwdata.Length); //MessageBox.Show(text); UInt32 fwChkSum = 0; for (int i = 0; i < fwdata.Length; i++) { fwChkSum += (UInt32)(fwdata[i]); } PACKET_DN packet = csCanFwUpdateFunction.FwImageChkSumPacket(SystemId, (UInt32)fwdata.Length, fwChkSum); OnSendDataCan?.Invoke(packet.hdr, packet.data); } } else { MessageBox.Show(String.Format("WritedataChkSumProcess Fail - {0}", rResult)); } } private void FwImageChkSumProcess(PACKET_HEADER_DN hdr, byte[] data) { byte rResult = data[7]; if (rResult == 0) { PACKET_DN packet = csCanFwUpdateFunction.UpdateRestartPacket(SystemId, 3); OnSendDataCan?.Invoke(packet.hdr, packet.data); MessageBox.Show("Firmware Update Complete !!", "FwUpdate", MessageBoxButtons.OK, MessageBoxIcon.Information); lbUpdateStatus.Text = "Update Status : Complete"; } else { MessageBox.Show(String.Format("FwImageChkSumProcess Fail - {0}", rResult)); lbUpdateStatus.Text = "Update Status : Update failure (Image Checksum fail)"; } btnFwUpdate.Text = "Firmware Update"; } #endregion #region UPDATE FUNCTIONS private const int FirmwareUpdateTimeoutMax = 30; // 3 Sec private int FirmwareUpdateTimeout = 0; // 10 ms private void FirmwareUpdateStop() { StopUpdate = true; FirmwareUpdateTimeoutClear(); teModuleNo.Enabled = true; lbUpdateStatus.Text = "Update Status : Restart"; if (OnAutoTxCanSet != null) { OnAutoTxCanSet(true); } } private void FirmwareUpdateTimeoutClear() { FirmwareUpdateTimeout = 0; } #endregion #region TIMER EVENT private void tmrFirmwareUpdate_Tick(object sender, EventArgs e) { if (StopUpdate == false) { FirmwareUpdateTimeout++; if (FirmwareUpdateTimeout > FirmwareUpdateTimeoutMax) { FirmwareUpdateStop(); } } } #endregion } }