public static List<ProgrammableRegion> BuildFLASHImages(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { string bspPath = bspDict["SYS:BSP_ROOT"]; string toolchainPath = bspDict["SYS:TOOLCHAIN_ROOT"]; string freq, mode, size; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_freq", out freq); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_mode", out mode); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_size", out size); string partitionTable, bootloader, txtAppOffset; bspDict.TryGetValue("com.sysprogs.esp32.partition_table_file", out partitionTable); bspDict.TryGetValue("com.sysprogs.esp32.bootloader_file", out bootloader); bspDict.TryGetValue("com.sysprogs.esp32.app_offset", out txtAppOffset); uint appOffset; if (txtAppOffset == null) appOffset = 0; else if (txtAppOffset.StartsWith("0x")) uint.TryParse(txtAppOffset.Substring(2), NumberStyles.HexNumber, null, out appOffset); else uint.TryParse(txtAppOffset, out appOffset); if (appOffset == 0) throw new Exception("Application FLASH offset not defined. Please check your settings."); partitionTable = VariableHelper.ExpandVariables(partitionTable, bspDict, debugMethodConfig); bootloader = VariableHelper.ExpandVariables(bootloader, bspDict, debugMethodConfig); if (!string.IsNullOrEmpty(partitionTable) && !Path.IsPathRooted(partitionTable)) partitionTable = Path.Combine(bspDict["SYS:PROJECT_DIR"], partitionTable); if (!string.IsNullOrEmpty(bootloader) && !Path.IsPathRooted(bootloader)) bootloader = Path.Combine(bspDict["SYS:PROJECT_DIR"], bootloader); if (string.IsNullOrEmpty(partitionTable) || !File.Exists(partitionTable)) throw new Exception("Unspecified or missing partition table file: " + partitionTable); if (string.IsNullOrEmpty(bootloader) || !File.Exists(bootloader)) throw new Exception("Unspecified or missing bootloader file: " + bootloader); List<ProgrammableRegion> regions = new List<ProgrammableRegion>(); using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); var img = ESP8266BinaryImage.MakeESP32ImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size)); //Bootloader/partition table offsets are hardcoded in ESP-IDF regions.Add(new ProgrammableRegion { FileName = bootloader, Offset = 0x1000, Size = GetFileSize(bootloader) }); regions.Add(new ProgrammableRegion { FileName = partitionTable, Offset = 0x8000, Size = GetFileSize(partitionTable) }); string fn = pathBase + "-esp32.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)appOffset, Size = (int)fs.Length }); } } return regions; }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { List<CustomStartStep> cmds = new List<CustomStartStep>(); cmds.Add(new CustomStartStep("mon esp108 chip_reset")); string bspPath = bspDict["SYS:BSP_ROOT"]; string val; if (bspDict.TryGetValue("com.sysprogs.esp32.load_flash", out val) && val == "1") { //Not a FLASHless project, FLASH loading required if (debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.program_flash", out val) && val != "0") { string loader = bspPath + @"\sysprogs\flashprog\ESP32FlashProg.bin"; if (!File.Exists(loader)) throw new Exception("FLASH loader not found: " + loader); var parsedLoader = new ParsedFLASHLoader(loader); //List<ProgrammableRegion> regions = new List<ProgrammableRegion>(); //regions.Add(new ProgrammableRegion { FileName = @"E:\temp\esp\build\bootloader\bootloader.bin", Offset = 0x1000, Size = 4224 }); //regions.Add(new ProgrammableRegion { FileName = @"E:\temp\esp\build\blink.bin", Offset = 0x10000, Size = 245328 }); //regions.Add(new ProgrammableRegion { FileName = @"E:\temp\esp\build\partitions_singleapp.bin", Offset = 0x4000, Size = 96 }); var regions = BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); int eraseBlockSize = int.Parse(debugMethodConfig["com.sysprogs.esp8266.xt-ocd.erase_sector_size"]); cmds.Add(parsedLoader.QueueInvocation(0, "$$com.sysprogs.esp8266.xt-ocd.prog_sector_size$$", "0", null, 0, 0, true)); for (int pass = 0; pass < 2; pass++) foreach (var region in regions) parsedLoader.QueueRegionProgramming(cmds, region, eraseBlockSize, pass == 0); } cmds.Add(new CustomStartStep("mon esp108 chip_reset")); } else { cmds.Add(new CustomStartStep("load")); } return new CustomStartupSequence { Steps = cmds }; }
public static List <ProgrammableRegion> BuildFLASHImages(string targetPath, Dictionary <string, string> bspDict, Dictionary <string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { string bspPath = bspDict["SYS:BSP_ROOT"]; string toolchainPath = bspDict["SYS:TOOLCHAIN_ROOT"]; string freq, mode, size; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_freq", out freq); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_mode", out mode); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_size", out size); string partitionTable, bootloader, txtAppOffset; bspDict.TryGetValue("com.sysprogs.esp32.partition_table_file", out partitionTable); bspDict.TryGetValue("com.sysprogs.esp32.bootloader_file", out bootloader); bspDict.TryGetValue("com.sysprogs.esp32.app_offset", out txtAppOffset); uint appOffset; if (txtAppOffset == null) { appOffset = 0; } else if (txtAppOffset.StartsWith("0x")) { uint.TryParse(txtAppOffset.Substring(2), NumberStyles.HexNumber, null, out appOffset); } else { uint.TryParse(txtAppOffset, out appOffset); } if (appOffset == 0) { throw new Exception("Application FLASH offset not defined. Please check your settings."); } partitionTable = VariableHelper.ExpandVariables(partitionTable, bspDict, debugMethodConfig); bootloader = VariableHelper.ExpandVariables(bootloader, bspDict, debugMethodConfig); if (!string.IsNullOrEmpty(partitionTable) && !Path.IsPathRooted(partitionTable)) { partitionTable = Path.Combine(bspDict["SYS:PROJECT_DIR"], partitionTable); } if (!string.IsNullOrEmpty(bootloader) && !Path.IsPathRooted(bootloader)) { bootloader = Path.Combine(bspDict["SYS:PROJECT_DIR"], bootloader); } if (string.IsNullOrEmpty(partitionTable) || !File.Exists(partitionTable)) { throw new Exception("Unspecified or missing partition table file: " + partitionTable); } if (string.IsNullOrEmpty(bootloader) || !File.Exists(bootloader)) { throw new Exception("Unspecified or missing bootloader file: " + bootloader); } List <ProgrammableRegion> regions = new List <ProgrammableRegion>(); using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); var img = ESP8266BinaryImage.MakeESP32ImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size)); //Bootloader/partition table offsets are hardcoded in ESP-IDF regions.Add(new ProgrammableRegion { FileName = bootloader, Offset = 0x1000, Size = GetFileSize(bootloader) }); regions.Add(new ProgrammableRegion { FileName = partitionTable, Offset = 0x8000, Size = GetFileSize(partitionTable) }); string fn = pathBase + "-esp32.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)appOffset, Size = (int)fs.Length }); } } return(regions); }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary <string, string> bspDict, Dictionary <string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { List <CustomStartStep> cmds = new List <CustomStartStep>(); cmds.Add(new CustomStartStep("mon esp108 chip_reset")); string bspPath = bspDict["SYS:BSP_ROOT"]; string val; if (bspDict.TryGetValue("com.sysprogs.esp32.load_flash", out val) && val == "1") { //Not a FLASHless project, FLASH loading required if (debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.program_flash", out val) && val != "0") { string loader = bspPath + @"\sysprogs\flashprog\ESP32FlashProg.bin"; if (!File.Exists(loader)) { throw new Exception("FLASH loader not found: " + loader); } var parsedLoader = new ParsedFLASHLoader(loader); //List<ProgrammableRegion> regions = new List<ProgrammableRegion>(); //regions.Add(new ProgrammableRegion { FileName = @"E:\temp\esp\build\bootloader\bootloader.bin", Offset = 0x1000, Size = 4224 }); //regions.Add(new ProgrammableRegion { FileName = @"E:\temp\esp\build\blink.bin", Offset = 0x10000, Size = 245328 }); //regions.Add(new ProgrammableRegion { FileName = @"E:\temp\esp\build\partitions_singleapp.bin", Offset = 0x4000, Size = 96 }); var regions = BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); int eraseBlockSize = int.Parse(debugMethodConfig["com.sysprogs.esp8266.xt-ocd.erase_sector_size"]); cmds.Add(parsedLoader.QueueInvocation(0, "$$com.sysprogs.esp8266.xt-ocd.prog_sector_size$$", "0", null, 0, 0, true)); for (int pass = 0; pass < 2; pass++) { foreach (var region in regions) { parsedLoader.QueueRegionProgramming(cmds, region, eraseBlockSize, pass == 0); } } } cmds.Add(new CustomStartStep("mon esp108 chip_reset")); } else { cmds.Add(new CustomStartStep("load")); } return(new CustomStartupSequence { Steps = cmds }); }
public static List<ProgrammableRegion> BuildFLASHImages(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { string bspPath = bspDict["SYS:BSP_ROOT"]; string toolchainPath = bspDict["SYS:TOOLCHAIN_ROOT"]; Regex rgBinFile = new Regex("^" + Path.GetFileName(targetPath) + "-0x([0-9a-fA-F]+)\\.bin$", RegexOptions.IgnoreCase); foreach (var fn in Directory.GetFiles(Path.GetDirectoryName(targetPath))) if (rgBinFile.IsMatch(Path.GetFileName(fn))) File.Delete(fn); string freq, mode, size; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_freq", out freq); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_mode", out mode); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_size", out size); List<ProgrammableRegion> regions = new List<ProgrammableRegion>(); using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (status != null && lineHandler != null) lineHandler(status, true); if (appMode == 0) { var img = ESP8266BinaryImage.MakeNonBootloaderImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size)); string fn = pathBase + "-0x00000.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = (int)fs.Length }); } foreach (var sec in ESP8266BinaryImage.GetFLASHSections(elfFile)) { fn = string.Format("{0}-0x{1:x5}.bin", pathBase, sec.OffsetInFLASH); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.Write(sec.Data, 0, sec.Data.Length); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)sec.OffsetInFLASH, Size = sec.Data.Length }); } } } else { var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size), appMode); string bspRoot, bootloader; if (!bspDict.TryGetValue("SYS:BSP_ROOT", out bspRoot) || !bspDict.TryGetValue("com.sysprogs.esp8266.bootloader", out bootloader)) throw new Exception("Cannot determine bootloader image path. Please check your BSP consistency."); string fn = Path.Combine(bspRoot, bootloader); if (!File.Exists(fn)) throw new Exception(fn + " not found. Cannot program OTA images."); byte[] data = File.ReadAllBytes(fn); data[2] = (byte)img.Header.Mode; data[3] = (byte)(((byte)img.Header.Size << 4) | (byte)img.Header.Frequency); fn = string.Format("{0}-0x00000.bin", pathBase); File.WriteAllBytes(fn, data); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = File.ReadAllBytes(fn).Length }); fn = string.Format("{0}-0x{1:x5}.bin", pathBase, img.BootloaderImageOffset); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)img.BootloaderImageOffset, Size = (int)fs.Length }); } } } return regions; }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { bool isOpenOCD = debugMethodConfig.ContainsKey("com.sysprogs.esp8266.openocd.iface_script"); List<CustomStartStep> cmds = new List<CustomStartStep>(); cmds.Add(new CustomStartStep(isOpenOCD ? "mon reset halt" : "maint packet R", "-exec-next-instruction", "set $com_sysprogs_esp8266_wdcfg=0", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $ccompare=0", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); var result = new CustomStartupSequence { Steps = cmds }; string val; if (bspDict.TryGetValue("com.sysprogs.esp8266.load_flash", out val) && val == "1") //Not a FLASHless project { if (debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.program_flash", out val) && val != "0") { string bspPath = bspDict["SYS:BSP_ROOT"]; List<ProgrammableRegion> regions = BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); string loader = bspPath + @"\sysprogs\flashprog\ESP8266FlashProg.bin"; if (!File.Exists(loader)) throw new Exception("FLASH loader not found: " + loader); var parsedLoader = new ParsedFLASHLoader(loader); cmds.Add(new CustomStartStep("print *((int *)0x60000900)", "set *((int *)0x60000900)=0")); cmds.Add(parsedLoader.QueueInvocation(0, "$$com.sysprogs.esp8266.xt-ocd.prog_sector_size$$", "$$com.sysprogs.esp8266.xt-ocd.erase_sector_size$$", null, 0, 0, true)); foreach (var region in regions) parsedLoader.QueueRegionProgramming(cmds, region); } if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_start_mode", out val)) val = "soft_reset"; if (val == "soft_reset") { try { using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (appMode != 0) { if (System.Windows.Forms.MessageBox.Show("The soft reset mechanism is not compatible with the OTA images. Use the jump-to-entry reset instead?", "VisualGDB", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.Yes) val = "entry_point"; } } } catch { } } if (val == "soft_reset" || val == "entry_point") { string entry = "0x40000080"; if (val == "entry_point") { using (ELFFile elf = new ELFFile(targetPath)) { foreach (var sec in elf.AllSections) { if (!sec.PresentInMemory || !sec.HasData || sec.Type != ELFFile.SectionType.SHT_PROGBITS) continue; bool isInRAM = false; if (sec.VirtualAddress >= 0x3FFE8000 && sec.VirtualAddress < (0x3FFE8000 + 81920)) isInRAM = true; else if (sec.VirtualAddress >= 0x40100000 && sec.VirtualAddress <= (0x40100000 + 32768)) isInRAM = true; if (isInRAM) { cmds.Add(new CustomStartStep(string.Format("restore {0} binary 0x{1:x} 0x{2:x} 0x{3:x}", targetPath.Replace('\\', '/'), sec.VirtualAddress - sec.OffsetInFile, sec.OffsetInFile, sec.OffsetInFile + sec.Size)) { CheckResult = true, ErrorMessage = "Failed to program the " + sec.SectionName + " section" }); } } } entry = "$$DEBUG:ENTRY_POINT$$"; } cmds.Add(new CustomStartStep("set $ps=0x20", "set $epc2=" + entry, "set $sp=$$DEBUG:INITIAL_STACK_POINTER$$", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); result.InitialHardBreakpointExpression = "*$$DEBUG:ENTRY_POINT$$"; } else cmds.Add(new CustomStartStep(isOpenOCD ? "mon reset halt" : "maint packet R")); } else { cmds.Add(new CustomStartStep("load", "set $ps=0x20", "set $epc2=$$DEBUG:ENTRY_POINT$$", "set $sp=$$DEBUG:INITIAL_STACK_POINTER$$", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $ccompare=0", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); } return result; }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary<string, string> bspDict, Dictionary<string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { if (!File.Exists(targetPath)) throw new Exception(targetPath + " not found. Debugging will not be possible."); bool stubFound = false; using (var elf = new ELFFile(targetPath)) { foreach (var sym in elf.LoadAllSymbols()) { if (sym.Name == "gdbstub_init") { stubFound = true; break; } } } if (!stubFound) { var wrp = new ResultWrapper(); _SyncContext.Send(o => ((ResultWrapper)o).Result = MessageBox.Show("The programmed image does not contain the GDB stub. Do you want to open instructions on debugging with ESP8266 GDB stub?", "VisualGDB", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information), wrp); switch(wrp.Result) { case DialogResult.Yes: Process.Start("http://visualgdb.com/KB/esp8266gdbstub"); goto case DialogResult.Cancel; case DialogResult.No: break; case DialogResult.Cancel: throw new OperationCanceledException(); } } string val; if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.program_flash", out val) || val != "0") { var wrp = new ResultWrapper(); _SyncContext.Send(o => ((ResultWrapper)o).Result = MessageBox.Show("Please reboot your ESP8266 into the bootloader mode and press OK.", "VisualGDB", MessageBoxButtons.OKCancel, MessageBoxIcon.Information), wrp); if (wrp.Result != DialogResult.OK) throw new OperationCanceledException(); using (var serialPort = new SerialPortStream(debugMethodConfig["com.sysprogs.esp8266.gdbstub.com_port"], int.Parse(debugMethodConfig["com.sysprogs.esp8266.gdbstub.bl_baud"]), System.IO.Ports.Handshake.None)) { serialPort.AllowTimingOutWithZeroBytes = true; int resetDelay; if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.reset_delay", out val) || !int.TryParse(val, out resetDelay)) resetDelay = 25; string seq; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.gdbstub.reset_sequence", out seq); ESP8266BootloaderClient client = new ESP8266BootloaderClient(serialPort, resetDelay, seq); client.Sync(); var regions = ESP8266StartupSequence.BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); ProgramProgressForm frm = null; _SyncContext.Post(o => { frm = new ProgramProgressForm(); frm.ShowDialog(); }, null); int totalSize = 0; foreach (var r in regions) totalSize += r.Size; ESP8266BootloaderClient.BlockWrittenHandler handler = (s, a, len) => frm.UpdateProgressAndThrowIfCanceled(a, len, totalSize); bool useDIO = false; try { client.BlockWritten += handler; foreach (var r in regions) { var data = File.ReadAllBytes(r.FileName); if (r.Offset == 0 && data.Length >= 4) useDIO = (data[2] == 2); client.ProgramFLASH((uint)r.Offset, data); } } finally { client.BlockWritten -= handler; _SyncContext.Post(o => { frm.Close(); frm.Dispose(); }, null); } client.RunProgram(useDIO, false); } } string tmp = null; if (debugMethodConfig?.TryGetValue("SYS:PROGRAM_WITHOUT_DEBUGGING", out tmp) == true && tmp == "1") return null; //Suppress connecting to gdb return new CustomStartupSequence { Steps = new List<CustomStartStep> { new CustomStartStep("set serial baud $$com.sysprogs.esp8266.gdbstub.baud$$"), new CustomStartStep(@"target remote \\.\$$com.sysprogs.esp8266.gdbstub.com_port$$"), } }; }
public static List <ProgrammableRegion> BuildFLASHImages(string targetPath, Dictionary <string, string> bspDict, Dictionary <string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { string bspPath = bspDict["SYS:BSP_ROOT"]; string toolchainPath = bspDict["SYS:TOOLCHAIN_ROOT"]; Regex rgBinFile = new Regex("^" + Path.GetFileName(targetPath) + "-0x([0-9a-fA-F]+)\\.bin$", RegexOptions.IgnoreCase); foreach (var fn in Directory.GetFiles(Path.GetDirectoryName(targetPath))) { if (rgBinFile.IsMatch(Path.GetFileName(fn))) { File.Delete(fn); } } string freq, mode, size; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_freq", out freq); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_mode", out mode); debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_size", out size); List <ProgrammableRegion> regions = new List <ProgrammableRegion>(); using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (status != null && lineHandler != null) { lineHandler(status, true); } if (appMode == 0) { var img = ESP8266BinaryImage.MakeNonBootloaderImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size)); string fn = pathBase + "-0x00000.bin"; using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = (int)fs.Length }); } foreach (var sec in ESP8266BinaryImage.GetFLASHSections(elfFile)) { fn = string.Format("{0}-0x{1:x5}.bin", pathBase, sec.OffsetInFLASH); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.Write(sec.Data, 0, sec.Data.Length); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)sec.OffsetInFLASH, Size = sec.Data.Length }); } } } else { var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, new ESP8266BinaryImage.ParsedHeader(freq, mode, size), appMode); string bspRoot, bootloader; if (!bspDict.TryGetValue("SYS:BSP_ROOT", out bspRoot) || !bspDict.TryGetValue("com.sysprogs.esp8266.bootloader", out bootloader)) { throw new Exception("Cannot determine bootloader image path. Please check your BSP consistency."); } string fn = Path.Combine(bspRoot, bootloader); if (!File.Exists(fn)) { throw new Exception(fn + " not found. Cannot program OTA images."); } byte[] data = File.ReadAllBytes(fn); data[2] = (byte)img.Header.Mode; data[3] = (byte)(((byte)img.Header.Size << 4) | (byte)img.Header.Frequency); fn = string.Format("{0}-0x00000.bin", pathBase); File.WriteAllBytes(fn, data); regions.Add(new ProgrammableRegion { FileName = fn, Offset = 0, Size = File.ReadAllBytes(fn).Length }); fn = string.Format("{0}-0x{1:x5}.bin", pathBase, img.BootloaderImageOffset); using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { img.Save(fs); regions.Add(new ProgrammableRegion { FileName = fn, Offset = (int)img.BootloaderImageOffset, Size = (int)fs.Length }); } } } return(regions); }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary <string, string> bspDict, Dictionary <string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { bool isOpenOCD = debugMethodConfig.ContainsKey("com.sysprogs.esp8266.openocd.iface_script"); List <CustomStartStep> cmds = new List <CustomStartStep>(); cmds.Add(new CustomStartStep(isOpenOCD ? "mon reset halt" : "maint packet R", "-exec-next-instruction", "set $com_sysprogs_esp8266_wdcfg=0", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $ccompare=0", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); var result = new CustomStartupSequence { Steps = cmds }; string val; if (bspDict.TryGetValue("com.sysprogs.esp8266.load_flash", out val) && val == "1") //Not a FLASHless project { if (debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.program_flash", out val) && val != "0") { string bspPath = bspDict["SYS:BSP_ROOT"]; List <ProgrammableRegion> regions = BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); string loader = bspPath + @"\sysprogs\flashprog\ESP8266FlashProg.bin"; if (!File.Exists(loader)) { throw new Exception("FLASH loader not found: " + loader); } var parsedLoader = new ParsedFLASHLoader(loader); cmds.Add(new CustomStartStep("print *((int *)0x60000900)", "set *((int *)0x60000900)=0")); cmds.Add(parsedLoader.QueueInvocation(0, "$$com.sysprogs.esp8266.xt-ocd.prog_sector_size$$", "$$com.sysprogs.esp8266.xt-ocd.erase_sector_size$$", null, 0, 0, true)); foreach (var region in regions) { parsedLoader.QueueRegionProgramming(cmds, region); } } if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.xt-ocd.flash_start_mode", out val)) { val = "soft_reset"; } if (val == "soft_reset") { try { using (var elfFile = new ELFFile(targetPath)) { string pathBase = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetFileName(targetPath)); string status; int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status); if (appMode != 0) { if (System.Windows.Forms.MessageBox.Show("The soft reset mechanism is not compatible with the OTA images. Use the jump-to-entry reset instead?", "VisualGDB", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.Yes) { val = "entry_point"; } } } } catch { } } if (val == "soft_reset" || val == "entry_point") { string entry = "0x40000080"; if (val == "entry_point") { using (ELFFile elf = new ELFFile(targetPath)) { foreach (var sec in elf.AllSections) { if (!sec.PresentInMemory || !sec.HasData || sec.Type != ELFFile.SectionType.SHT_PROGBITS) { continue; } bool isInRAM = false; if (sec.VirtualAddress >= 0x3FFE8000 && sec.VirtualAddress < (0x3FFE8000 + 81920)) { isInRAM = true; } else if (sec.VirtualAddress >= 0x40100000 && sec.VirtualAddress <= (0x40100000 + 32768)) { isInRAM = true; } if (isInRAM) { cmds.Add(new CustomStartStep(string.Format("restore {0} binary 0x{1:x} 0x{2:x} 0x{3:x}", targetPath.Replace('\\', '/'), sec.VirtualAddress - sec.OffsetInFile, sec.OffsetInFile, sec.OffsetInFile + sec.Size)) { CheckResult = true, ErrorMessage = "Failed to program the " + sec.SectionName + " section" }); } } } entry = "$$DEBUG:ENTRY_POINT$$"; } cmds.Add(new CustomStartStep("set $ps=0x20", "set $epc2=" + entry, "set $sp=$$DEBUG:INITIAL_STACK_POINTER$$", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); result.InitialHardBreakpointExpression = "*$$DEBUG:ENTRY_POINT$$"; } else { cmds.Add(new CustomStartStep(isOpenOCD ? "mon reset halt" : "maint packet R")); } } else { cmds.Add(new CustomStartStep("load", "set $ps=0x20", "set $epc2=$$DEBUG:ENTRY_POINT$$", "set $sp=$$DEBUG:INITIAL_STACK_POINTER$$", "set $vecbase=0x40000000", "$$com.sysprogs.esp8266.interrupt_disable_command$$", "set $ccompare=0", "set $intclear=-1", "set $intenable=0", "set $eps2=0x20", "set $icountlevel=0")); } return(result); }
public CustomStartupSequence BuildSequence(string targetPath, Dictionary <string, string> bspDict, Dictionary <string, string> debugMethodConfig, LiveMemoryLineHandler lineHandler) { if (!File.Exists(targetPath)) { throw new Exception(targetPath + " not found. Debugging will not be possible."); } bool stubFound = false; using (var elf = new ELFFile(targetPath)) { foreach (var sym in elf.LoadAllSymbols()) { if (sym.Name == "gdbstub_init") { stubFound = true; break; } } } if (!stubFound) { var wrp = new ResultWrapper(); _SyncContext.Send(o => ((ResultWrapper)o).Result = MessageBox.Show("The programmed image does not contain the GDB stub. Do you want to open instructions on debugging with ESP8266 GDB stub?", "VisualGDB", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information), wrp); switch (wrp.Result) { case DialogResult.Yes: Process.Start("http://visualgdb.com/KB/esp8266gdbstub"); goto case DialogResult.Cancel; case DialogResult.No: break; case DialogResult.Cancel: throw new OperationCanceledException(); } } string val; if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.program_flash", out val) || val != "0") { var wrp = new ResultWrapper(); _SyncContext.Send(o => ((ResultWrapper)o).Result = MessageBox.Show("Please reboot your ESP8266 into the bootloader mode and press OK.", "VisualGDB", MessageBoxButtons.OKCancel, MessageBoxIcon.Information), wrp); if (wrp.Result != DialogResult.OK) { throw new OperationCanceledException(); } using (var serialPort = new SerialPortStream(debugMethodConfig["com.sysprogs.esp8266.gdbstub.com_port"], int.Parse(debugMethodConfig["com.sysprogs.esp8266.gdbstub.bl_baud"]), System.IO.Ports.Handshake.None)) { serialPort.AllowTimingOutWithZeroBytes = true; int resetDelay; if (!debugMethodConfig.TryGetValue("com.sysprogs.esp8266.reset_delay", out val) || !int.TryParse(val, out resetDelay)) { resetDelay = 25; } string seq; debugMethodConfig.TryGetValue("com.sysprogs.esp8266.gdbstub.reset_sequence", out seq); ESP8266BootloaderClient client = new ESP8266BootloaderClient(serialPort, resetDelay, seq); client.Sync(); var regions = ESP8266StartupSequence.BuildFLASHImages(targetPath, bspDict, debugMethodConfig, lineHandler); ProgramProgressForm frm = null; _SyncContext.Post(o => { frm = new ProgramProgressForm(); frm.ShowDialog(); }, null); int totalSize = 0; foreach (var r in regions) { totalSize += r.Size; } ESP8266BootloaderClient.BlockWrittenHandler handler = (s, a, len) => frm.UpdateProgressAndThrowIfCanceled(a, len, totalSize); bool useDIO = false; try { client.BlockWritten += handler; foreach (var r in regions) { var data = File.ReadAllBytes(r.FileName); if (r.Offset == 0 && data.Length >= 4) { useDIO = (data[2] == 2); } client.ProgramFLASH((uint)r.Offset, data); } } finally { client.BlockWritten -= handler; _SyncContext.Post(o => { frm.Close(); frm.Dispose(); }, null); } client.RunProgram(useDIO, false); } } string tmp = null; if (debugMethodConfig?.TryGetValue("SYS:PROGRAM_WITHOUT_DEBUGGING", out tmp) == true && tmp == "1") { return(null); //Suppress connecting to gdb } return(new CustomStartupSequence { Steps = new List <CustomStartStep> { new CustomStartStep("set serial baud $$com.sysprogs.esp8266.gdbstub.baud$$"), new CustomStartStep(@"target remote \\.\$$com.sysprogs.esp8266.gdbstub.com_port$$"), } }); }