private void writeFileToFlash(bool setAddresses) { if (!selectC2Device()) return; if (FileName.Text.Length == 0) { if (openFileDialog.ShowDialog() == DialogResult.OK) { FileName.Text = openFileDialog.FileName; setAddresses = true; } else return; } try { int flashSize = CurrentC2Device.Bottom; byte[] flash_buffer = new byte[flashSize]; for (int idx = 0; idx < flash_buffer.Length; idx++) flash_buffer[idx] = 0xFF; List<HexRange> ranges = new List<HexRange>(); bool enableFlash = false; int startAddress = -1, endAddress = -1; if (!validInt(StartAddr.Text, out startAddress) || !validInt(EndAddr.Text, out endAddress)) return; if (Path.GetExtension(FileName.Text).Equals(".hex", StringComparison.InvariantCultureIgnoreCase)) { int minAddress = int.MaxValue, maxAddress = int.MinValue; bool fail = false; #region Load HEX file using (TextReader s = new StreamReader(FileName.Text)) { string line; int lineNumber = 0; int count = 0; int ext_address = 0, seg_address = 0, address = 0; byte command = 0; byte checksum = 0; int pos; byte data; while ((line = s.ReadLine()) != null) { ++lineNumber; line = line.Trim(); if (line.Length == 0 || !line.StartsWith(":")) continue; if (line.Length < 11) { fail = true; } else { fail |= !int.TryParse(line.Substring(1, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out count); fail |= !int.TryParse(line.Substring(3, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address); fail |= !byte.TryParse(line.Substring(7, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out command); fail |= !byte.TryParse(line.Substring(line.Length - 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out checksum); } if (fail) { MessageBox.Show(string.Format("Can't parse line {0}", lineNumber)); break; } int calculatedCheckSum = count + ((address >> 8) & 0xFF) + (address & 0xFF) + command; pos = 9; if (command == 2 || command == 4) { if (line.Length != 15) fail = true; else if(command == 2) fail |= !int.TryParse(line.Substring(pos, 4), NumberStyles.HexNumber, null, out seg_address); else fail |= !int.TryParse(line.Substring(pos, 4), NumberStyles.HexNumber, null, out ext_address); if (fail) { if(command == 2) MessageBox.Show(string.Format("Bad extended segment address record at line {0}.", lineNumber)); else MessageBox.Show(string.Format("Bad extended linear address record at line {0}.", lineNumber)); } } else if (command == 0) { if (count > 0) { int next = address + count; bool add = true; foreach (HexRange range in ranges) { if (range.Next == address) { range.Count += count; add = false; break; } else if (next == range.Address) { range.Address = address; range.Count += count; add = false; break; } fail = range.IsInner(address) || range.IsInner(next); if (fail) break; } if (fail) { MessageBox.Show(string.Format("Address range overlapped at line {0}.", lineNumber)); break; } if (add) ranges.Add(new HexRange(address, count)); } for (; count > 0; --count) { if (address >= flashSize) { MessageBox.Show(string.Format("Address {0} outside flash size at line {1}.", addressToText(address), lineNumber)); fail = true; break; } if (CurrentC2Device.LockType == "FLT_SINGLE" && address == CurrentC2Device.SingleLock) { if (MessageBox.Show(string.Format("File write to LOCK byte ({0:X4}).\nAre you sure ?", address), "Attention", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly) != DialogResult.OK) { fail = true; break; } } if (address < minAddress) minAddress = address; if (address > maxAddress) maxAddress = address; fail |= !byte.TryParse(line.Substring(pos, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data); pos += 2; if (fail) { MessageBox.Show(string.Format("Bad data \"{0}\" at line {1}.", line.Substring(pos, 2), lineNumber)); break; } flash_buffer[address++] = data; calculatedCheckSum += (int)data; } } if (fail) break; fail |= (((calculatedCheckSum + checksum) & 0xFF) != 0); if (fail) { MessageBox.Show(string.Format("Bad checksum {0:X2}:{1:X2} at line {2}.", checksum, calculatedCheckSum, lineNumber)); break; } // EOF record if (command == 1) break; } s.Close(); } #endregion #region Collapse HEX ranges and check overlap if (!fail) { if (ranges.Count == 0) { MessageBox.Show("No data to write in file"); fail = true; } else { for (int i = 0; i < ranges.Count; i++) { HexRange rangeI = ranges[i]; for (int j = 0; j < ranges.Count; j++) { if (i == j) continue; HexRange rangeJ = ranges[j]; if (rangeI.Next == rangeJ.Address) { rangeI.Count += rangeJ.Count; ranges.RemoveAt(j); i = -1; break; } if (rangeJ.Next == rangeI.Address) { rangeJ.Count += rangeI.Count; ranges.RemoveAt(i); i = -1; break; } fail = rangeI.IsInner(rangeJ.Address) || rangeI.IsInner(rangeJ.Next); if (fail) { MessageBox.Show(string.Format("Addresses overlapped {0}:{1} and {2}:{3}", addressToText(rangeI.Address), addressToText(rangeI.Next), addressToText(rangeJ.Address), addressToText(rangeJ.Next) )); break; } } if (fail) break; } } } #endregion #region Check Addresses and ranges if (!fail) { if (setAddresses) { if (ranges.Count > 0) { startAddress = minAddress; endAddress = maxAddress; StartAddr.Text = addressToText(minAddress); EndAddr.Text = addressToText(maxAddress); } } else if (endAddress > maxAddress || startAddress < minAddress) { MessageBox.Show("File data less than bytes to write"); fail = true; } else { HexRange range = new HexRange(startAddress, endAddress - startAddress + 1); for (int i = 0; i < ranges.Count; ++i) { HexRange rangeS = ranges[i]; if (!range.IsOverlapped(rangeS)) { ranges.RemoveAt(i); --i; } } } } if (!fail) { if (ranges.Count == 0) { MessageBox.Show("No data to write in file"); fail = true; } else enableFlash = true; } #endregion } else if (Path.GetExtension(FileName.Text).Equals(".bin", StringComparison.InvariantCultureIgnoreCase)) { #region Load BIN file using (Stream s = File.OpenRead(FileName.Text)) { enableFlash = true; int fileLength = (int)s.Length; if (setAddresses) { endAddress = startAddress + fileLength - 1; if (startAddress >= flashSize) { MessageBox.Show("Invalid start address"); enableFlash = false; } else if (endAddress >= flashSize) { if (MessageBox.Show("File data more than available flash.\nWrite partial content ?", "Attension", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly) != DialogResult.OK) enableFlash = false; else { endAddress = flashSize - startAddress - 1; fileLength = flashSize - startAddress; } } else EndAddr.Text = addressToText(endAddress); } else if ((endAddress - startAddress + 1) > fileLength) { MessageBox.Show("File data less than bytes to write"); enableFlash = false; } if (enableFlash) s.Read(flash_buffer, startAddress, fileLength); s.Close(); } #endregion } else { MessageBox.Show("Insupported file type"); } if (enableFlash) { if (startAddress < 0 || endAddress < 0 || startAddress >= flashSize || endAddress >= flashSize ) MessageBox.Show("File data more than available flash."); else { int byteCount = endAddress - startAddress + 1; if (MessageBox.Show( string.Format( "Continue write {0} bytes\nfrom {1} to {2}", addressToText(byteCount), addressToText(startAddress), addressToText(endAddress)), "Attention", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK) { float delta = ((float)(progress.Maximum - progress.Minimum)) / (float)byteCount; int writtenBytes = 0; Response response = null; int addressAt = startAddress; int totalBytes = byteCount; ranges.Clear(); while (byteCount > 0) { int count = (byteCount > 128) ? 128 : byteCount; #region Auto erase page if (cbAutoErase.Checked) { // Check for page erase bool erase = true; foreach (HexRange range in ranges) { if (range.IsInner(startAddress)) { erase = false; break; } } if (erase) { response = sendCommand(0, C2_ERASE_PAGE, (byte)((startAddress >> 9) & 0xFF)); if (response.Result != ResponseCode.COMMAND_OK) break; ranges.Add(new HexRange(startAddress & ~(CurrentC2Device.FlashSectorSize - 1), CurrentC2Device.FlashSectorSize)); } // Also check end address to erase erase = true; endAddress = startAddress + count - 1; foreach (HexRange range in ranges) { if (range.IsInner(endAddress)) { erase = false; break; } } if (erase) { response = sendCommand(0, C2_ERASE_PAGE, (byte)((endAddress >> 9) & 0xFF)); if (response.Result != ResponseCode.COMMAND_OK) break; ranges.Add(new HexRange(endAddress & ~(CurrentC2Device.FlashSectorSize - 1), CurrentC2Device.FlashSectorSize)); } } #endregion response = sendCommand(0, flash_buffer, startAddress, count, C2_WRITE_FLASH, (byte)(startAddress & 0xFF), (byte)((startAddress >> 8) & 0xFF), (byte)count); if (response.Result != ResponseCode.COMMAND_OK) break; startAddress += count; byteCount -= count; writtenBytes += count; if (writtenBytes % 512 == 0) { progress.Value = (int)(delta * ((float)(writtenBytes))); status.Text = string.Format("Writing {0} bytes at {1} ({2}%)...", addressToText(count), addressToText(startAddress), (int)(100 * writtenBytes / totalBytes)); Application.DoEvents(); } } progress.Value = progress.Minimum; if (C2_Disconnect_Target() && C2_Connect_Target() && C2_Device_Info() && response != null) { if(response.Result != ResponseCode.COMMAND_OK) setStatus("C2_WRITE_FLASH", response); else status.Text = string.Format("Writing {0} bytes at {1} complete.", addressToText(totalBytes), addressToText(addressAt)); } } } } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
public bool IsOverlapped(HexRange range) { if (range.Address >= next) return false; if (range.Next <= address) return false; if (this.IsInner(range.Address) || this.IsInner(range.Next - 1)) return true; if (range.IsInner(address) || range.IsInner(next - 1)) return true; return false; }