/// <summary> /// Programs the flash in the ECU by sending a BIN file in pieces to the bootloader running in the ECUs SRAM /// </summary> /// <param name="filename"></param> /// <param name="type"></param> /// <returns></returns> public bool ProgramFlashBin(string filename, ECUType type) { // if can connection is available, upload the bootloader // now upload all the records in the S19 bootloader file // if all else fails, revert back to S19 files, so convert the bin to S19 and program that // with ProgramFlash function! FileInfo fi = new FileInfo(filename); using (FileStream fs = File.OpenRead(filename)) { CastInfoEvent("Start upload of new program...", ActivityType.StartFlashing); int start = (type == ECUType.T52ECU) ? 0x60000 : 0x40000; int bytesread = 0; while ((start + bytesread) < 0x80000) { // read a section of 0x80 bytes from the BIN file and keep it in a buffer to send to the T5 ECU byte[] bytes = new byte[0x80]; // something has gone wrong if we cannot read another 0x80 bytes!! if (fs.Read(bytes, 0,/*bytesread,*/ 0x80) != 0x80) //<GS-22092010> parameter error! { string BytesSoFar = bytesread.ToString("X6"); CastInfoEvent("Reading the BIN File Failed after: 0x" + BytesSoFar + " Bytes !!!", ActivityType.UploadingFlash); return false; } // send a bootloader address message byte[] result = sendBootloaderAddressCommand((start + bytesread), 0x80); //DEBUG ONLY //string extraInfo = string.Empty; //foreach (byte b in result) //{ // extraInfo += b.ToString("X2") + " "; //} //CastInfoEvent("send address A5 command: " + extraInfo, ActivityType.UploadingFlash); //DEBUG ONLY bytesread += 0x80; byte[] dataframe = new byte[8]; // Construct and send the bootloader frames // NOTE the last frame sent may have less than 7 real data bytes but 7 bytes are always sent. In this case the unnecessary bytes // are repeated from the previous frame. This is OK because the T5 ECU knows how many bytes to expect (because the count of bytes // in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame. for (int i = 0; i < 0x80; i++) { // set the index number if (i % 7 == 0) dataframe.SetValue((byte)(i), 0); // put bytes them in the dataframe! dataframe.SetValue(bytes[i], (i % 7) + 1); // send a bootloader frame whenever 7 bytes or a block of 0x80 bytes have been read from the BIN file if ((i % 7 == 6) || (i == 0x80 - 1)) { byte[] result2 = sendBootloaderDataCommand(dataframe, 8); //DEBUG ONLY //string extraInfo = string.Empty; //foreach (byte b in result2) //{ // extraInfo += b.ToString("X2") + " "; //} //CastInfoEvent("send data command: " + extraInfo, ActivityType.UploadingFlash); //DEBUG ONLY if ((byte)result2.GetValue(6) != 0x00) { string BytesSoFar = bytesread.ToString("X6"); CastInfoEvent("FLASHing Failed after: 0x" + BytesSoFar + " Bytes !!!", ActivityType.UploadingFlash); return false; } } // show progress information } int prgs = (type == ECUType.T52ECU) ? ((bytesread * 100) / 0x20000) : ((bytesread * 100) / 0x40000); CastProgressWriteEvent(prgs); CastBytesTransmitted(bytesread); // // Rewind to start of file if FLASHing a T5.2 BIN file to A T5.5 ECU // to FLASH 2 copies of the BIN File to T5.5's larger FLASH chips // if ((type != ECUType.T52ECU) && (bytesread == 0x20000) && (fi.Length == 0x20000)) { fs.Seek(0, SeekOrigin.Begin); } } CastInfoEvent("Flash programming finished", ActivityType.FinishedFlashing); } return true; }
private void getECUinfo() { statusActivity.Text = "getting Footer"; byte[] footer = t5can.getECUFooter(); byte[] chiptypes = t5can.GetChipTypes(); statusActivity.Text = "IDLE"; string swversion = t5can.getIdentifierFromFooter(footer, ECUIdentifier.Dataname); string romoffset = t5can.getIdentifierFromFooter(footer, ECUIdentifier.ROMoffset); string checksum = t5can.ReturnChecksum(); statusSWVersion.Text = "SW Version: " + swversion; statusChecksum.Text = "Checksum: " + checksum; // identify ECU string flashzize = "256 kB"; switch (chiptypes[0]) { case 0xB8: // Intel/CSI/OnSemi 28F512 case 0x25: // AMD 28F512 statusFLASHType.Text = "Type: 28F512"; flashzize = "128 kB"; break; case 0x5D: // Atmel 29C512 statusFLASHType.Text = "Type: 29C512"; flashzize = "128 kB"; break; case 0xB4: // Intel/CSI/OnSemi 28F010 case 0xA7: // AMD 28F010 statusFLASHType.Text = "Type: 28F010"; break; case 0x20: // AMD/ST 29F010 case 0xA4: // AMIC 29F010 statusFLASHType.Text = "Type: 29F010"; break; case 0xD5: // Atmel 29C010 statusFLASHType.Text = "Type: 29C010"; break; case 0xB5: // SST 39F010 statusFLASHType.Text = "Type: 39F010"; break; default: statusFLASHType.Text = "Type: 0x" + chiptypes[0].ToString("X2") + " - Unknown"; flashzize = "Unknown"; break; } statusFLASHSize.Text = "Size: " + flashzize; switch (chiptypes[1]) { case 0x89: // Intel statusFLASHMake.Text = "Make: Intel"; break; case 0x01: // AMD statusFLASHMake.Text = "Make: AMD/Spansion"; break; case 0x31: // CSI/OnSemi statusFLASHMake.Text = "Make: CSI"; break; case 0x1F: // Atmel statusFLASHMake.Text = "Make: Atmel"; break; case 0xBF: // SST/Microchip statusFLASHMake.Text = "Make: SST/Microchip"; break; case 0x20: // ST statusFLASHMake.Text = "Make: ST Microelectronics"; break; case 0x37: // AMIC statusFLASHMake.Text = "Make: AMIC"; break; default: statusFLASHMake.Text = "Make: 0x" + chiptypes[1].ToString("X2") + " - Unknown"; break; } switch (flashzize) { case "128 kB": switch (romoffset) { case "060000": ECU_type = ECUType.T52ECU; statusECU.Text = "ECU Type: Trionic 5.2"; AddToLog("This is a Trionic 5.2 ECU with 128 kB of FLASH"); break; default: ECU_type = ECUType.Unknown; statusECU.Text = "ECU Type: Unknown"; AddToLog("!!! ERROR !!! This type of ECU is unknown"); break; } break; case "256 kB": switch (romoffset) { case "040000": ECU_type = ECUType.T55ECU; statusECU.Text = "ECU Type: Trionic 5.5"; AddToLog("This is a Trionic 5.5 ECU with 256 kB of FLASH"); break; case "060000": ECU_type = ECUType.T55AST52; statusECU.Text = "ECU Type: T5.5 as T5.2"; AddToLog("This is a Trionic 5.5 ECU with a T5.2 BIN"); break; default: ECU_type = ECUType.Unknown; statusECU.Text = "ECU Type: Unknown"; AddToLog("!!! ERROR !!! This type of ECU is unknown"); break; } break; default: ECU_type = ECUType.Unknown; statusECU.Text = "ECU Type: Unknown"; AddToLog("!!! ERROR !!! This type of ECU is unknown"); break; } AddToLog("Part Number: " + t5can.getIdentifierFromFooter(footer, ECUIdentifier.Partnumber)); AddToLog("Software ID: " + t5can.getIdentifierFromFooter(footer, ECUIdentifier.SoftwareID)); AddToLog("SW Version: " + swversion); AddToLog("Engine Type: " + t5can.getIdentifierFromFooter(footer, ECUIdentifier.EngineType)); AddToLog("IMMO Code: " + t5can.getIdentifierFromFooter(footer, ECUIdentifier.ImmoCode)); AddToLog("Other Info: " + t5can.getIdentifierFromFooter(footer, ECUIdentifier.Unknown)); AddToLog("ROM Start: 0x" + romoffset); AddToLog("Code End: 0x" + t5can.getIdentifierFromFooter(footer, ECUIdentifier.CodeEnd)); AddToLog("ROM End: 0x" + t5can.getIdentifierFromFooter(footer, ECUIdentifier.ROMend)); AddToLog("Checksum: " + checksum); }
/// <summary> /// Gets the checksum from the ECU, dumps it to the console and tries to get the ECU out of the bootloader routine /// </summary> /// <param name="type"></param> /// <param name="path"></param> public void GetChecksumWithBootloader(ECUType type, string path) { UploadBootLoader(); DumpChecksum(); sendC2Command(); }
/// <summary> /// Programs the flash in the ECU by sending the S19 file in pieces to the bootloader running in the ECUs SRAM /// </summary> /// <param name="filename"></param> /// <param name="type"></param> /// <returns></returns> public bool ProgramFlash(string filename, ECUType type) { // if can connection is available, upload the bootloader // now upload all the records in the S19 bootloader file FileInfo fi = new FileInfo(filename); using (StreamReader sr = new StreamReader(filename)) { string line = string.Empty; int bytestransmitted = 0; int bytesread = 0; while ((line = sr.ReadLine()) != null) { bytesread += line.Length + 2; if (line.StartsWith("S0")) { //if (!BinaryReflection.IsAppDebugMode(Application.ExecutablePath)) { // maybe not necessary t5can.sendBootloaderAddressCommand(0, 0); } // AddToLog("Starting upload of new flash"); CastInfoEvent("Start upload of new program...", ActivityType.StartFlashing); } else if (line.StartsWith("S2")) { int len = Convert.ToInt32(line.Substring(2, 2), 16); byte[] data = new byte[len - 4]; // substract address (3 bytes) and checksum (1 byte) Int32 address = Convert.ToInt32(line.Substring(4, 6), 16); // add flash start offset address address += ((type == ECUType.T52ECU)) ? 0x60000 : 0x40000; for (int t = 0; t < len - 4; t++) { int bytevalue = Convert.ToInt32(line.Substring((t * 2) + 10, 2), 16); data.SetValue((byte)bytevalue, t); } int framecount = 1 + (len - 4) / 7; int bytessent = 0; sendBootloaderAddressCommand(address, (byte)(len - 4)); /** option 1 **/ for (int frame = 0; frame < framecount; frame++) { byte[] dataframe = new byte[8]; dataframe.SetValue((byte)(frame * 7), 0); for (int bcnt = 0; bcnt < 7; bcnt++) { byte currbyte = 0; if (bytessent < data.Length) currbyte = (byte)data.GetValue(bytessent); bytessent++; dataframe.SetValue(currbyte, bcnt + 1); } sendBootloaderDataCommand(dataframe, 8); } /** end option 1 **/ /** option 2 **/ /*for (int frame = 0; frame < framecount; frame++) { int dtlen = data.Length - bytessent; if (dtlen > 7) dtlen = 7; t5can.sendBootloaderAddressCommand(address, (byte)dtlen); byte[] dataframe = new byte[8]; int bscnt = 0; for (int bcnt = 0; bcnt < 7; bcnt++) { byte currbyte = 0; if (bytessent < data.Length) { currbyte = (byte)data.GetValue(bytessent); bscnt++; } bytessent++; dataframe.SetValue(currbyte, bcnt + 1); } dataframe.SetValue((byte)(bscnt), 0); t5can.sendBootloaderDataCommand(dataframe, 8); address += 7; // last one don't care because it will be recalculated //Thread.Sleep(10); } */ /** end option 2 **/ bytestransmitted += (len - 4); int prgs = (bytesread * 100) / (int)fi.Length; CastProgressWriteEvent(prgs); CastBytesTransmitted(bytestransmitted); } else if (line.StartsWith("S8")) { // terminate session with boot vector address to run SRAM from // S8040060C4D7 //int address = Convert.ToInt32(line.Substring(4, 6), 16); // C1 00 00 60 C4 00 00 06 //t5can.sendBootVectorAddressSRAM(address); //Thread.Sleep(500); //DumpChecksum(); //Thread.Sleep(100); CastInfoEvent("Flash programming finished", ActivityType.FinishedFlashing); } else { //AddToLog("Unknown S record seen: " + line); } } } //progressBar1.Value = 0; // reset //sendC2Command(); // reset ECU return true; }
/// <summary> /// Dumps the flash contents of a ECU to a binary file. Be sure to pass the correct ECUType /// </summary> /// <param name="flashfile"></param> /// <param name="type"></param> public void DumpECU(string flashfile, ECUType type) { // set FLASH chip start address and length according to ECUType UInt32 start = (type == ECUType.T55ECU) ? (UInt32)0x40000 : (UInt32)0x60000; UInt32 length = (type == ECUType.T55ECU) ? (UInt32)0x40000 : (UInt32)0x20000; byte[] buffer = new byte[length]; Console.WriteLine("Start ECU dump"); string path = Path.GetDirectoryName(flashfile); Console.WriteLine("Path = " + path); CastInfoEvent("Downloading flash from ECU", ActivityType.StartDownloadingFlash); //TODO: hier het aantal keren dat gelezen moet worden nog aanpassen aan het ECUType //TODO: specify the times that must be read even adjust the ECUType byte[] buffer2 = new byte[6]; UInt32 address = (start + 5); for (int i = 0; i < (length / 6); i++) { buffer2 = this.sendReadCommand(address); address += 6; for (int j = 0; j < 6; j++) buffer[(i * 6) + j] = buffer2[j]; CastProgressWriteEvent((int)((i * 600) / length)); CastBytesTransmitted((int)(address - (start + 5))); } // Mop up the last few bytes if not an exact multiple of 6 // It has to be done this way because the T5 ECU resets if // you try to read past the end of the FLASH addresses if ((length % 6) > 0) { buffer2 = this.sendReadCommand(start + length - 1); for (int j = (int)(6 - (length % 6)); j < 6; j++) buffer[length - 6 + j] = buffer2[j]; } CastInfoEvent("Finished downloading flash from ECU", ActivityType.FinishedDownloadingFlash); CastProgressWriteEvent(100); CastBytesTransmitted((int)length); //DownloadFlashContent(); FileStream fs = new FileStream(flashfile, FileMode.Create); using (BinaryWriter bw = new BinaryWriter(fs)) { bw.Write(buffer); } fs.Close(); fs.Dispose(); }
public ChecksumResult VerifyECU(ECUType ecutype, string path) { ChecksumResult result = ChecksumResult.Valid; UploadBootLoader(); // DumpChecksum(); if (!VerifyChecksum()) { result = ChecksumResult.Invalid; } ExitBootloader(); return result; }
/// <summary> /// Upgrades the ECU with the given file. Be sure to pass the right ECUType /// </summary> /// <param name="flashfile"></param> /// <param name="ecutype"></param> public UpgradeResult UpgradeECU(string flashfile, ECUType ecutype) { UpgradeResult result = UpgradeResult.Success; string path = Path.GetDirectoryName(flashfile); //ecutype = DetermineConnectedECUType(); //<GS-22032011> Does not matter anymore what ECUtype is in the box? // hier nog controleren of de lengte van de bin wel past bij het ECUType FileInfo fi = new FileInfo(flashfile); switch (ecutype) { case ECUType.T52ECU: if (fi.Length != 0x20000) return UpgradeResult.InvalidFile; break; case ECUType.T55ECU: case ECUType.T55AST52: if ((fi.Length != 0x20000) && (fi.Length != 0x40000)) return UpgradeResult.InvalidFile; //if (fi.Length != 0x40000) return UpgradeResult.InvalidFile; break; default: return UpgradeResult.InvalidFile; } if (!EraseFlash()) { return UpgradeResult.EraseFailed; } if (!ProgramFlashBin(flashfile, ecutype)) { return UpgradeResult.ProgrammingFailed; } if (!VerifyChecksum()) { result = UpgradeResult.ChecksumFailed; } CastProgressWriteEvent(100); return result; }
/// <summary> /// Upgrades the ECU with the given file. Be sure to pass the right ECUType /// </summary> /// <param name="bootloaderfile"></param> /// <param name="flashfile"></param> /// <param name="filetype"></param> /// <param name="ecutype"></param> public UpgradeResult UpgradeECU(string flashfile, FileType filetype, ECUType ecutype) { UpgradeResult result = UpgradeResult.Success; string path = Path.GetDirectoryName(flashfile); //ecutype = DetermineConnectedECUType(); //<GS-22032011> Does not matter anymore what ECUtype is in the box? // hier nog controleren of de lengte van de bin wel past bij het ECUType FileInfo fi = new FileInfo(flashfile); if (ecutype == ECUType.T52ECU) { if (fi.Length != 0x20000) return UpgradeResult.InvalidFile; } else { if (fi.Length != 0x40000) return UpgradeResult.InvalidFile; } if (ecutype == ECUType.Autodetect || ecutype == ECUType.Unknown) { return UpgradeResult.InvalidECUType; } /*if (isT52ECU()) { ecutype = ECUType.T52ECU; }*/ //CastInfoEvent("Created bootloader: " + bootloader, ActivityType.ConvertingFile); UploadBootLoader(); //DumpChecksum(); VerifyChecksum(); if (!EraseFlash()) { return UpgradeResult.EraseFailed; } if (filetype == FileType.BinaryFile) { if (!ProgramFlashBin(flashfile, ecutype)) { return UpgradeResult.ProgrammingFailed; } } else ProgramFlash(flashfile, ecutype); if (!VerifyChecksum()) { result = UpgradeResult.ChecksumFailed; } ExitBootloader(); CastProgressWriteEvent(100); return result; }