コード例 #1
0
            public override void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                bool programNow;

                if (_Settings.ProgramFLASHUsingExternalTool)
                {
                    programNow = false;
                }
                else
                {
                    switch (_Settings.ProgramMode)
                    {
                    case ProgramMode.Disabled:
                        programNow = false;
                        break;

                    case ProgramMode.Auto:
                        programNow = !service.IsCurrentFirmwareAlreadyProgrammed();
                        break;

                    default:
                        programNow = true;
                        break;
                    }
                }

                foreach (var cmd in _Settings.StartupCommands)
                {
                    bool isLoad = cmd.Trim() == "load";

                    if (isLoad)
                    {
                        if (service.Mode == EmbeddedDebugMode.Attach)
                        {
                            session.RunGDBCommand("mon halt");
                        }
                        else
                        {
                            var sequence = ESP8266StartupSequence.BuildSequence(service, (ESP8266OpenOCDSettings)_Settings, (l, i) => session.SendInformationalOutput(l), programNow, _Context.Method?.Directory);
                            using (var ctx = session.CreateScopedProgressReporter("Programming FLASH", new string[] { "Programming FLASH..." }))
                            {
                                if (RunSequence(ctx, service, session, sequence))
                                {
                                    service.OnFirmwareProgrammedSuccessfully();
                                }
                            }
                        }
                    }
                    else
                    {
                        session.RunGDBCommand(cmd);
                    }
                }
            }
コード例 #2
0
            public void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                using (var r = session.CreateScopedProgressReporter("Programming FLASH memory", new string[] { "Loading FLASH memory" }))
                {
                    Regex rgPercentage = new Regex(@"(.*)\( *([0-9]+) *% *\)");

                    EventHandler <LineReceivedEventArgs> handler = (s, e) =>
                    {
                        session.SendInformationalOutput(e.Line);
                        r.AppendLogLine(e.Line);
                        var m = rgPercentage.Match(e.Line);
                        if (m.Success)
                        {
                            int value = int.Parse(m.Groups[2].Value);
                            r.ReportTaskProgress(value, 100, m.Groups[1].ToString());
                        }
                    };

                    try
                    {
                        Tool.LineReceived += handler;
                        while (Tool.IsRunning && !r.IsAborted)
                        {
                            Thread.Sleep(100);
                        }

                        if (r.IsAborted)
                        {
                            Tool.TerminateProgram();
                            throw new OperationCanceledException();
                        }
                    }
                    finally
                    {
                        Tool.LineReceived -= handler;
                    }
                }

                string text       = Tool.AllText;
                int    validLines = text.Split('\n').Count(l => l.Trim() == "Hash of data verified.");

                if (validLines >= _RegionCount.Count)
                {
                    service.GUIService.Report("The FLASH memory has been programmed, however the ESP32 GDB stub does not support live debugging yet. Please use JTAG if you want to debug your program or reset your board to run the program without debugging.");
                }
                else
                {
                    throw new Exception("Warning: some of the FLASH regions could not be programmed. Please examine the stub output for details.");
                }

                throw new OperationCanceledException();
            }
コード例 #3
0
            public void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                ReportFLASHProgrammingProgress(Tool, service, session);
                string text       = Tool.AllText;
                int    validLines = text.Split('\n').Count(l => l.Trim() == "Hash of data verified.");

                if (validLines >= _RegionCount.Count)
                {
                    service.GUIService.Report("The FLASH memory has been programmed, however the ESP32 GDB stub does not support live debugging yet. Please use JTAG if you want to debug your program or reset your board to run the program without debugging.");
                }
                else
                {
                    throw new Exception("Warning: some of the FLASH regions could not be programmed. Please examine the stub output for details.");
                }

                throw new OperationCanceledException();
            }
コード例 #4
0
            public void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                //We may need to wait for the AVaRICE to complete programming the FLASH memory.
                int timeout = _Settings.GDBTimeout;

                if (timeout != 0)
                {
                    session.RunGDBCommand($"set remotetimeout {timeout}");
                    session.RunGDBCommand($"set tcp connect-timeout {timeout}");
                    session.RunGDBCommand($"set tcp auto-retry on");
                }

                var result = session.RunGDBCommand($"target remote :{_GDBPort}");

                if (!result.IsDone)
                {
                    throw new Exception("Failed to connect to AVaRICE");
                }
            }
コード例 #5
0
ファイル: XDSDebugController.cs プロジェクト: whinis/BSPTools
            public LoadedProgrammingStub(string path, ISimpleGDBSession session, TiXDSDebugSettings settings)
            {
                byte[] data = File.ReadAllBytes(path);
                _Path = path.Replace('\\', '/');
                var offsets = Enumerable.Range(0, data.Length - 3).Where(d => BitConverter.ToInt32(data, d) == Signature).ToArray();

                if (offsets.Length != 1)
                {
                    throw new Exception("Unable to uniquely locate the address table block in " + path);
                }

                int off = offsets[0];

                LoadAddress       = BitConverter.ToUInt32(data, off += 4);
                EndOfStack        = BitConverter.ToUInt32(data, off += 4);
                ProgramBuffer     = BitConverter.ToUInt32(data, off += 4);
                ProgramBufferSize = BitConverter.ToUInt32(data, off += 4);

                EntryPoint = BitConverter.ToUInt32(data, off += 4);
                Result     = BitConverter.ToUInt32(data, off += 4);
                _Session   = session;
                _Settings  = settings;
            }
コード例 #6
0
            public void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                bool programFLASH = false;

                if (service.Mode != EmbeddedDebugMode.Attach && service.Mode != EmbeddedDebugMode.ConnectionTest)
                {
                    switch (_Settings.ProgramMode)
                    {
                    case ProgramMode.Auto:
                        programFLASH = !service.IsCurrentFirmwareAlreadyProgrammed();
                        break;

                    case ProgramMode.Enabled:
                        programFLASH = true;
                        break;
                    }
                }

                DoConnect(service, session, _Settings, _COMPort, programFLASH);
                if (_Settings.ProgramMode == ProgramMode.Auto)
                {
                    service.OnFirmwareProgrammedSuccessfully();
                }
            }
コード例 #7
0
            public static void ReportFLASHProgrammingProgress(IExternalToolInstance tool, IDebugStartService service, ISimpleGDBSession session)
            {
                using (var r = session.CreateScopedProgressReporter("Programming FLASH memory", new string[] { "Loading FLASH memory" }))
                {
                    Regex rgPercentage = new Regex(@"(.*)\( *([0-9]+) *% *\)");

                    EventHandler <LineReceivedEventArgs> handler = (s, e) =>
                    {
                        session.SendInformationalOutput(e.Line);
                        r.AppendLogLine(e.Line);
                        var m = rgPercentage.Match(e.Line);
                        if (m.Success)
                        {
                            int value = int.Parse(m.Groups[2].Value);
                            r.ReportTaskProgress(value, 100, m.Groups[1].ToString());
                        }
                    };

                    try
                    {
                        tool.LineReceived += handler;
                        while (tool.IsRunning && !r.IsAborted)
                        {
                            Thread.Sleep(100);
                        }

                        if (r.IsAborted)
                        {
                            tool.TerminateProgram();
                            throw new OperationCanceledException();
                        }
                    }
                    finally
                    {
                        tool.LineReceived -= handler;
                    }
                }
            }
コード例 #8
0
        public static bool RunSequence(ILoadProgressReporter reporter, IDebugStartService service, ISimpleGDBSession session, CustomStartupSequence sequence)
        {
            var espCmds = sequence.Steps;

            if (espCmds != null)
            {
                DateTime startTime = DateTime.Now;

                int total = 0, done = 0;
                foreach (var s in espCmds)
                {
                    total += s.ProgressWeight;
                }

                for (int retry = 0; ; retry++)
                {
                    try
                    {
                        foreach (var s in espCmds)
                        {
                            SimpleGDBCommandResult r = default(SimpleGDBCommandResult);

                            foreach (var scmd in s.Commands)
                            {
                                r = session.RunGDBCommand(scmd);
                            }

                            bool failed = false;
                            if (s.ResultVariable != null)
                            {
                                string val = session.EvaluateExpression(s.ResultVariable);
                                if (val != "0")
                                {
                                    failed = true;
                                }
                            }
                            if (s.CheckResult && !failed)
                            {
                                failed = r.MainStatus != "^done";
                            }

                            if (failed)
                            {
                                string msg = s.ErrorMessage ?? "Custom FLASH programming step failed";
                                if (s.CanRetry)
                                {
                                    throw new RetriableException(msg);
                                }
                                else
                                {
                                    throw new Exception(msg);
                                }
                            }

                            done += s.ProgressWeight;
                            reporter.ReportTaskProgress(done, total);
                        }
                        break;
                    }
                    catch (RetriableException)
                    {
                        if (retry < 2)
                        {
                            continue;
                        }
                        throw;
                    }
                }

                reporter.ReportTaskCompletion(true);
                session.SendInformationalOutput("Loaded image in " + (int)(DateTime.Now - startTime).TotalMilliseconds + " ms");
            }

            if (!string.IsNullOrEmpty(sequence.InitialHardBreakpointExpression))
            {
                session.RequestInitialBreakpoint(service.ExpandProjectVariables(sequence.InitialHardBreakpointExpression, true, false));
            }

            return(true);
        }
コード例 #9
0
 protected override bool RunLoadCommand(IDebugStartService service, ISimpleGDBSession session, string cmd) => throw new NotSupportedException();
コード例 #10
0
        bool LoadFLASH(DebugStartContext context, IDebugStartService service, ISimpleGDBSession session, ESP32OpenOCDSettings settings, ESP32GDBStub stub)
        {
            string val;

            if (!service.SystemDictionary.TryGetValue("com.sysprogs.esp32.load_flash", out val) || val != "1")
            {
                //This is a RAM-only configuration
                return(session.RunGDBCommand("load").IsDone);
            }
            else
            {
                if (settings.ProgramFLASHUsingExternalTool)
                {
                    var svc = service.AdvancedDebugService as IExternallyProgrammedProjectDebugService ?? throw new Exception("This project type does not support external FLASH memory programming");
                    svc.ProgramFLASHMemoryUsingExternalTool(settings.ProgramMode);
                }
                else
                {
                    List <ProgrammableRegion> blocks = BuildProgrammableBlocksFromSettings(service, settings);

                    Regex rgFLASHSize = new Regex("Auto-detected flash size ([0-9]+) KB");
                    if (settings.CheckFLASHSize)
                    {
                        var match = stub.Tool.AllText.Split('\n').Select(s => rgFLASHSize.Match(s)).FirstOrDefault(m => m.Success);
                        if (match != null)
                        {
                            int detectedSizeKB  = int.Parse(match.Groups[1].Value);
                            int specifiedSizeMB = 0;
                            switch (settings.FLASHSettings.Size)
                            {
                            case ESP8266BinaryImage.ESP32FLASHSize.size1MB:
                                specifiedSizeMB = 1;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size2MB:
                                specifiedSizeMB = 2;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size4MB:
                                specifiedSizeMB = 4;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size8MB:
                                specifiedSizeMB = 8;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size16MB:
                                specifiedSizeMB = 16;
                                break;
                            }

                            if (detectedSizeKB < (specifiedSizeMB * 1024) && detectedSizeKB >= 1024)
                            {
                                if (service.GUIService.Prompt($"The FLASH size specified via Project Properties is greater than the actual SPI FLASH size on your device. Please switch FLASH size to {detectedSizeKB / 1024}MB or less.\nDo you want to cancel FLASH programming?", System.Windows.Forms.MessageBoxIcon.Warning))
                                {
                                    throw new OperationCanceledException();
                                }
                            }
                        }
                    }

                    using (var ctx = session.CreateScopedProgressReporter("Programming FLASH...", new[] { "Programming FLASH memory" }))
                    {
                        int   blkNum        = 0;
                        Regex rgWriteXBytes = new Regex("wrote ([0-9]+) bytes from file");
                        foreach (var blk in blocks)
                        {
                            ctx.ReportTaskProgress(blkNum++, blocks.Count);
                            string path = blk.FileName.Replace('\\', '/');
                            if (path.Contains(" "))
                            {
                                throw new Exception($"ESP32 OpenOCD does not support spaces in paths. Please relocate {path} to a location without spaces");
                            }
                            var  result    = session.RunGDBCommand($"mon program_esp32 \"{path}\" 0x{blk.Offset:x}");
                            bool succeeded = result.StubOutput?.FirstOrDefault(l => l.Contains("** Programming Finished **")) != null;
                            if (!succeeded)
                            {
                                throw new Exception("FLASH programming failed. Please review the gdb/OpenOCD logs for details.");
                            }
                            var m = result.StubOutput.Select(l => rgWriteXBytes.Match(l)).FirstOrDefault(m2 => m2.Success);
                            if (m == null)
                            {
                                throw new Exception("FLASH programming did not report the amount of written bytes. Please review the gdb/OpenOCD logs for details.");
                            }
                            int bytesWritten = int.Parse(m.Groups[1].Value);
                            if (bytesWritten == 0 && blk.Size > 0)
                            {
                                throw new Exception("FLASH programming did not write any data. This is a known bug of ESP32 OpenOCD. Please restart your device and JTAG programmer and try again.");
                            }
                        }
                    }
                }
            }

            if (!session.RunGDBCommand("mon reset halt").IsDone)
            {
                throw new Exception("Failed to reset target after programming");
            }

            return(true);
        }
コード例 #11
0
 protected override bool RunLoadCommand(IDebugStartService service, ISimpleGDBSession session, string cmd) => _Controller.LoadFLASH(_Context, service, session, (ESP32OpenOCDSettings)_Settings, this);
コード例 #12
0
ファイル: XDSDebugController.cs プロジェクト: whinis/BSPTools
            public void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                var info = service.TargetFileInfo;

                var result = session.RunGDBCommand($"-target-select remote :{LocalGDBEndpoint}");

                if (result.MainStatus != "^connected")
                {
                    throw new Exception("Failed to connect to gdb stub");
                }

                result = session.RunGDBCommand("mon reset");
                if (!result.IsDone)
                {
                    throw new Exception("Failed to reset target");
                }

                if (_Settings.FLASHDriver == TiXDSFLASHDriver.CC3220)
                {
                    var sections = info.GetLoadableSections()
                                   .Where(section => section.LoadAddress.HasValue && section.LoadAddress.Value >= FLASHBase && section.LoadAddress.Value < (FLASHBase + MaximumFLASHSize))
                                   .ToArray();

                    if (sections.Length == 0)
                    {
                        if (service.Mode != EmbeddedDebugMode.ConnectionTest)
                        {
                            session.SendInformationalOutput("No FLASH sections found in " + info.Path);

                            result = session.RunGDBCommand("load");
                            if (!result.IsDone)
                            {
                                throw new Exception("Failed to reset target");
                            }
                        }
                    }
                    else
                    {
                        bool skipLoad = false;

                        switch (_Settings.ProgramMode)
                        {
                        case ProgramMode.Disabled:
                            skipLoad = true;
                            break;

                        case ProgramMode.Auto:
                            if (service.IsCurrentFirmwareAlreadyProgrammed())
                            {
                                skipLoad = true;
                            }
                            break;
                        }

                        if (service.Mode == EmbeddedDebugMode.Attach || service.Mode == EmbeddedDebugMode.ConnectionTest)
                        {
                            skipLoad = true;
                        }

                        if (!skipLoad)
                        {
                            var resources = _Settings.FLASHResources ?? new FLASHResource[0];

                            using (var progr = session.CreateScopedProgressReporter("Programming FLASH...", new[] { "Erasing FLASH", "Programing FLASH" }))
                            {
                                var  stub      = new LoadedProgrammingStub(service.GetPathWithoutSpaces(Path.Combine(_BaseDir, "CC3220SF.bin")), session, _Settings);
                                uint totalSize = 0;

                                int totalItems = sections.Length + resources.Length;
                                int itemsDone  = 0;

                                foreach (var sec in sections)
                                {
                                    stub.EraseMemory((uint)sec.LoadAddress.Value, (uint)sec.Size);
                                    totalSize += (uint)sec.Size;
                                    progr.ReportTaskProgress(itemsDone, totalItems, $"Erasing {sec.Name}...");
                                }

                                foreach (var r in resources)
                                {
                                    r.ExpandedPath = service.ExpandProjectVariables(r.Path, true, true);
                                    r.Data         = File.ReadAllBytes(r.ExpandedPath);

                                    stub.EraseMemory(FLASHBase + (uint)r.ParsedOffset, (uint)r.Data.Length);
                                    totalSize += (uint)r.Data.Length;
                                    progr.ReportTaskProgress(itemsDone, totalItems, $"Erasing area for {Path.GetFileName(r.ExpandedPath)}...");
                                }

                                progr.ReportTaskCompletion(true);

                                var path = service.GetPathWithoutSpaces(info.Path);

                                uint doneTotal = 0;
                                foreach (var sec in sections)
                                {
                                    for (uint done = 0; done < (uint)sec.Size; done++)
                                    {
                                        uint todo = Math.Min(stub.ProgramBufferSize, (uint)sec.Size - done);
                                        progr.ReportTaskProgress(doneTotal, totalSize, $"Programming {sec.Name}...");
                                        stub.ProgramMemory((uint)sec.LoadAddress.Value + done, path, (uint)sec.OffsetInFile + done, todo, sec.Name);

                                        doneTotal += todo;
                                        done      += todo;
                                    }
                                }

                                foreach (var r in resources)
                                {
                                    var imgName = Path.GetFileName(r.ExpandedPath);
                                    for (uint done = 0; done < (uint)r.Data.Length; done++)
                                    {
                                        uint todo = Math.Min(stub.ProgramBufferSize, (uint)r.Data.Length - done);
                                        progr.ReportTaskProgress(doneTotal, totalSize, $"Programming {imgName}...");
                                        stub.ProgramMemory((uint)FLASHBase + (uint)r.ParsedOffset + done, path, done, todo, imgName);

                                        doneTotal += todo;
                                        done      += todo;
                                    }
                                }
                            }
                        }

                        service.OnFirmwareProgrammedSuccessfully();
                        session.RunGDBCommand("set $pc=resetISR", false);
                    }
                }
            }
コード例 #13
0
            public virtual void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                string[] regularStartupCommands = new[]
                {
                    "-gdb-set breakpoint pending on",
                    "-gdb-set detach-on-fork on",
                    "-gdb-set python print-stack none",
                    "-gdb-set print object on",
                    "-gdb-set print sevenbit-strings on",
                    "-gdb-set host-charset UTF-8",
                    "-gdb-set target-charset WINDOWS-1252",
                    "-gdb-set target-wide-charset UTF-16",
                    "-gdb-set pagination off",
                    "-gdb-set auto-solib-add on",
                    "inferior 1",
                    "set remotetimeout 10",
                    "set tcp connect-timeout 30",
                };

                SimpleGDBCommandResult result;

                foreach (var cmd in regularStartupCommands)
                {
                    result = session.RunGDBCommand(cmd);
                    if (!result.IsDone)
                    {
                        throw new Exception("GDB command failed: " + cmd);
                    }
                }

                session.EnableAsyncMode(GDBAsyncMode.AsyncWithTemporaryBreaks, true, true);
                session.ConnectToExtendedRemote(null, _GDBPort, true);

                result = session.RunGDBCommand("mon is_target_connected");
                if (!result.IsDone)
                {
                    throw new Exception("The target did not report connection state");
                }

                if (result.StubOutput?.FirstOrDefault(l => l.Trim() == "Connection status=connected.") == null)
                {
                    throw new Exception("The Renesas gdb stub is not connected to the target.");
                }

                result = ParseAndApplyIOAccessWidths(service, session, result);

                result = session.RunGDBCommand("monitor get_no_hw_bkpts_available");
                if (result.IsDone && result.StubOutput != null)
                {
                    foreach (var line in result.StubOutput)
                    {
                        if (int.TryParse(line.Trim(), out var tmp))
                        {
                            session.RunGDBCommand($"set remote hardware-breakpoint-limit " + tmp);
                            break;
                        }
                    }
                }

                result = session.RunGDBCommand("monitor get_target_max_address");
                if (result.IsDone && result.StubOutput != null)
                {
                    foreach (var line in result.StubOutput)
                    {
                        string trimmedLine = line.Trim();
                        if (trimmedLine.StartsWith("0x") && int.TryParse(trimmedLine.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out var tmp))
                        {
                            session.RunGDBCommand($"mem 0x0 0x{tmp + 1:x} rw 8 nocache");
                            break;
                        }
                    }
                }

                result = session.RunGDBCommand("monitor configuration_complete");

                if (_LoadFLASH)
                {
                    result = session.RunGDBCommand("monitor prg_download_start_on_connect");

                    result = session.RunGDBCommand("load");
                    if (!result.IsDone)
                    {
                        throw new Exception("Failed to program FLASH memory");
                    }

                    service.OnFirmwareProgrammedSuccessfully();

                    result = session.RunGDBCommand("monitor prg_download_end");
                }

                string[] finalCommands = new[]
                {
                    "monitor reset",
                    "monitor enable_stopped_notify_on_connect",
                    "monitor enable_execute_on_connect",
                };

                using (var awaiter = session.InterceptFirstStoppedEvent())
                {
                    foreach (var cmd in finalCommands)
                    {
                        result = session.RunGDBCommand(cmd);
                        if (!result.IsDone)
                        {
                            throw new Exception("GDB command failed: " + cmd);
                        }
                    }

                    while (!awaiter.WaitForStop(100))
                    {
                        session.RunGDBCommand("monitor do_nothing");
                    }
                }
            }
コード例 #14
0
 protected virtual bool RunLoadCommand(IDebugStartService service, ISimpleGDBSession session, string cmd)
 {
     return(session.RunGDBCommand(cmd).IsDone);
 }
コード例 #15
0
            public virtual void ConnectGDBToStub(IDebugStartService service, ISimpleGDBSession session)
            {
                foreach (var cmd in _Settings.StartupCommands)
                {
                    if (service.Mode == EmbeddedDebugMode.Attach)
                    {
                        if (SkipCommandOnAttach(cmd))
                        {
                            continue;
                        }
                    }

                    bool isLoad = cmd.Trim() == "load";
                    if (isLoad)
                    {
                        switch (_Settings.ProgramMode)
                        {
                        case ProgramMode.Disabled:
                            continue;

                        case ProgramMode.Auto:
                            if (service.IsCurrentFirmwareAlreadyProgrammed())
                            {
                                continue;
                            }
                            break;
                        }
                    }

                    if (isLoad)
                    {
                        if (isLoad && RunLoadCommand(service, session, cmd))
                        {
                            service.OnFirmwareProgrammedSuccessfully();
                        }
                    }
                    else
                    {
                        session.RunGDBCommand(cmd);
                    }
                }

                if (service.Mode != EmbeddedDebugMode.Attach && RISCVOpenOCDSettingsEditor.IsE300CPU(service.MCU))
                {
                    bool autoReset = _Settings.ResetMode == RISCVResetMode.nSRST;
                    if (autoReset)
                    {
                        //Issuing the reset signal will only trigger the 'software reset' interrupt that causes a halt by default.
                        //Resetting it and then setting $pc to _start does the trick, but results in strange chip resets later.
                        //Resetting the target via nSRST and reconnecting afterwards seems to do the trick
                        session.RunGDBCommand("mon hifive_reset");

                        //Manually manipulating nSRST with a gdb session active wreaks havoc in the internal gdb/gdbserver state machine,
                        //so we simply reconnect gdb to OpenOCD.
                        session.RunGDBCommand("-target-disconnect");
                    }
                    else
                    {
                        service.GUIService.Report("Please reset the board by pressing the 'reset' button and wait 1-2 seconds for the reset to complete. Then press 'OK'.", System.Windows.Forms.MessageBoxIcon.Information);
                        session.RunGDBCommand("mon halt");
                        session.RunGDBCommand("-target-disconnect");
                    }

                    session.RunGDBCommand("-target-select remote :$$SYS:GDB_PORT$$");

                    var expr = session.EvaluateExpression("(void *)$pc == _start");
                    if (expr?.TrimStart('0', 'x') != "1")
                    {
                        session.SendInformationalOutput("Warning: unexpected value of $pc after a reset");
                        session.RunGDBCommand("set $pc = _start");
                    }

                    //After resetting the CPU seems to be stuck in some state where resuming it will effectively keep it stalled, but
                    //resuming, halting and then finally resuming again does the job. The line below does the first resume-halt pair.
                    try
                    {
                        session.ResumeAndWaitForStop(200);
                    }
                    catch
                    {
                        //VisualGDB will throw a 'timed out' exception.
                    }

                    //If this step is skipped, subsequent break-in requests will fail
                    using (var r = session.CreateScopedProgressReporter("Waiting for the board to initialize", new[] { "Waiting for board..." }))
                    {
                        int delayInTenthsOfSecond = 10;
                        for (int i = 0; i < delayInTenthsOfSecond; i++)
                        {
                            Thread.Sleep(100);
                            r.ReportTaskProgress(i, delayInTenthsOfSecond);
                        }
                    }
                }
            }
コード例 #16
0
            static void DoConnect(IDebugStartService service, ISimpleGDBSession session, ESP8266GDBStubSettings settings, string comPort, bool programFLASH)
            {
                var targetPath = service.TargetPath;

                if (targetPath != null) //When doing connection test without an active project, the targetPath will be NULL
                {
                    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)
                    {
                        if (service.GUIService.Prompt("The programmed image does not contain the GDB stub. Do you want to open instructions on debugging with ESP8266 GDB stub?", MessageBoxIcon.Warning))
                        {
                            Process.Start("http://visualgdb.com/KB/esp8266gdbstub");
                            throw new OperationCanceledException();
                        }
                    }
                }

                List <string> steps = new List <string>();

                if (programFLASH)
                {
                    steps.Add("Connecting to bootloader");
                    steps.Add("Programming FLASH memory");
                }
                if (service.Mode != EmbeddedDebugMode.ProgramWithoutDebugging)
                {
                    steps.Add("Connecting to GDB stub");
                }

                using (var ctx = session.CreateScopedProgressReporter("Connecting to target device", steps.ToArray()))
                {
                    if (programFLASH)
                    {
                        if (!settings.SuppressResetConfirmation)
                        {
                            service.GUIService.Report("Please reboot your ESP8266 into the bootloader mode and press OK.");
                        }

                        using (var serialPort = new SerialPortStream(comPort, settings.BootloaderBaudRate, System.IO.Ports.Handshake.None))
                        {
                            serialPort.AllowTimingOutWithZeroBytes = true;

                            ESP8266BootloaderClient client = new ESP8266BootloaderClient(serialPort, settings.BootloaderResetDelay, settings.BootloaderActivationSequence);
                            client.Sync();
                            var regions = ESP8266StartupSequence.BuildFLASHImages(service, settings, (l, t) => session.SendInformationalOutput(l));

                            ctx.ReportTaskCompletion(true);

                            int totalSize = 0, writtenSize = 0;
                            foreach (var r in regions)
                            {
                                totalSize += r.Size;
                            }

                            ESP8266BootloaderClient.BlockWrittenHandler handler = (s, addr, len) => ctx.ReportTaskProgress(writtenSize += len, totalSize, $"Writing FLASH at 0x{addr:x8}...");
                            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;
                            }

                            client.RunProgram(useDIO, false);
                        }
                    }

                    ctx.ReportTaskCompletion(true);

                    if (service.Mode != EmbeddedDebugMode.ProgramWithoutDebugging)
                    {
                        ctx.ReportTaskCompletion(true);
                        session.RunGDBCommand("set serial baud " + settings.StubBaudRate);
                        var result = session.RunGDBCommand(@"target remote \\.\" + comPort);
                        if (!result.IsDone)
                        {
                            throw new Exception("Failed to connect to the gdb stub. Please check your settings.");
                        }
                    }
                }
            }
コード例 #17
0
        bool LoadFLASH(DebugStartContext context, IDebugStartService service, ISimpleGDBSession session, ESP32OpenOCDSettings settings, ESP32GDBStub stub)
        {
            string val;

            if (!service.SystemDictionary.TryGetValue("com.sysprogs.esp32.load_flash", out val) || val != "1")
            {
                //This is a RAM-only configuration
                return(session.RunGDBCommand("load").IsDone);
            }
            else
            {
                if (settings.ProgramUsingIDF)
                {
                    string bash, bashArgs;
                    if (!service.SystemDictionary.TryGetValue("com.sysprogs.esp32.esptool.bash", out bash) || !service.SystemDictionary.TryGetValue("com.sysprogs.esp32.esptool.bash_args", out bashArgs))
                    {
                        throw new Exception("ESP-IDF did not report esptool arguments");
                    }

                    if (service.SystemDictionary.TryGetValue("com.sysprogs.esp32.esptool.script", out var script) && File.Exists(script))
                    {
                        var lines = File.ReadAllLines(script).ToList();
                        int idx   = Enumerable.Range(0, lines.Count).FirstOrDefault(i => lines[i].Contains("def hard_reset(self):"));
                        if (idx > 0 && idx < (lines.Count - 1))
                        {
                            if (!lines[idx + 1].Contains("self._port.setDTR(False)"))
                            {
                                if (service.GUIService.Prompt("The esptool.py binary used in the current ESP-IDF contains known compatibility issue with Cygwin. Do you want to patch it automatically?"))
                                {
                                    Regex rgIndent = new Regex("^([ \t]*)[^ \t]");
                                    var   m        = rgIndent.Match(lines[idx + 1]);
                                    lines.Insert(idx + 1, m.Groups[1].Value + "self._port.setDTR(False)  # IO0=HIGH");
                                    File.WriteAllLines(script, lines.ToArray());
                                }
                            }
                        }
                    }

                    var tool = service.LaunchCommandLineTool(new CommandLineToolLaunchInfo
                    {
                        Command   = bash,
                        Arguments = bashArgs
                    });

                    ESP32StubDebugController.GDBStubInstance.ReportFLASHProgrammingProgress(tool, service, session);

                    string text       = tool.AllText;
                    int    validLines = text.Split('\n').Count(l => l.Trim() == "Hash of data verified.");
                    int    binCount   = 0;
                    if (service.MCU.Configuration.TryGetValue("com.sysprogs.esp32.esptool.binaries.count", out var tmp))
                    {
                        int.TryParse(tmp, out binCount);
                    }
                    binCount = 0;

                    if (validLines < binCount)
                    {
                        service.GUIService.Report("Warning: some of the FLASH regions could not be programmed. Please examine the stub output for details.", System.Windows.Forms.MessageBoxIcon.Warning);
                    }
                }
                else
                {
                    List <ProgrammableRegion> blocks;
                    if (service.MCU.Configuration.TryGetValue("com.sysprogs.esp32.esptool.binaries.count", out var tmp) && int.TryParse(tmp, out var binaryCount) && binaryCount > 0)
                    {
                        blocks = new List <ProgrammableRegion>();
                        for (int i = 0; i < binaryCount; i++)
                        {
                            string fn = service.MCU.Configuration[$"com.sysprogs.esp32.esptool.binaries[{i}].path"];

                            blocks.Add(new ProgrammableRegion
                            {
                                FileName = fn,
                                Size     = File.ReadAllBytes(fn).Length,
                                Offset   = int.Parse(service.MCU.Configuration[$"com.sysprogs.esp32.esptool.binaries[{i}].address"])
                            });
                        }
                    }
                    else
                    {
                        bool patchBootloader = (settings as IESP32Settings)?.PatchBootloader ?? false;
                        blocks = ESP32StartupSequence.BuildFLASHImages(service.TargetPath, service.SystemDictionary, settings.FLASHSettings, patchBootloader);
                    }

                    if (settings.FLASHResources != null)
                    {
                        foreach (var r in settings.FLASHResources)
                        {
                            if (r.Valid)
                            {
                                blocks.Add(r.ToProgrammableRegion(service));
                            }
                        }
                    }

                    Regex rgFLASHSize = new Regex("Auto-detected flash size ([0-9]+) KB");
                    if (settings.CheckFLASHSize)
                    {
                        var match = stub.Tool.AllText.Split('\n').Select(s => rgFLASHSize.Match(s)).FirstOrDefault(m => m.Success);
                        if (match != null)
                        {
                            int detectedSizeKB  = int.Parse(match.Groups[1].Value);
                            int specifiedSizeMB = 0;
                            switch (settings.FLASHSettings.Size)
                            {
                            case ESP8266BinaryImage.ESP32FLASHSize.size1MB:
                                specifiedSizeMB = 1;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size2MB:
                                specifiedSizeMB = 2;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size4MB:
                                specifiedSizeMB = 4;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size8MB:
                                specifiedSizeMB = 8;
                                break;

                            case ESP8266BinaryImage.ESP32FLASHSize.size16MB:
                                specifiedSizeMB = 16;
                                break;
                            }

                            if (detectedSizeKB < (specifiedSizeMB * 1024) && detectedSizeKB >= 1024)
                            {
                                if (service.GUIService.Prompt($"The FLASH size specified via Project Properties is greater than the actual SPI FLASH size on your device. Please switch FLASH size to {detectedSizeKB / 1024}MB or less.\nDo you want to cancel FLASH programming?", System.Windows.Forms.MessageBoxIcon.Warning))
                                {
                                    throw new OperationCanceledException();
                                }
                            }
                        }
                    }

                    using (var ctx = session.CreateScopedProgressReporter("Programming FLASH...", new[] { "Programming FLASH memory" }))
                    {
                        int   blkNum        = 0;
                        Regex rgWriteXBytes = new Regex("wrote ([0-9]+) bytes from file");
                        foreach (var blk in blocks)
                        {
                            ctx.ReportTaskProgress(blkNum++, blocks.Count);
                            string path      = blk.FileName.Replace('\\', '/');
                            var    result    = session.RunGDBCommand($"mon program_esp32 \"{path}\" 0x{blk.Offset:x}");
                            bool   succeeded = result.StubOutput?.FirstOrDefault(l => l.Contains("** Programming Finished **")) != null;
                            if (!succeeded)
                            {
                                throw new Exception("FLASH programming failed. Please review the gdb/OpenOCD logs for details.");
                            }
                            var m = result.StubOutput.Select(l => rgWriteXBytes.Match(l)).FirstOrDefault(m2 => m2.Success);
                            if (m == null)
                            {
                                throw new Exception("FLASH programming did not report the amount of written bytes. Please review the gdb/OpenOCD logs for details.");
                            }
                            int bytesWritten = int.Parse(m.Groups[1].Value);
                            if (bytesWritten == 0 && blk.Size > 0)
                            {
                                throw new Exception("FLASH programming did not write any data. This is a known bug of ESP32 OpenOCD. Please restart your device and JTAG programmer and try again.");
                            }
                        }
                    }
                }
            }

            if (!session.RunGDBCommand("mon reset halt").IsDone)
            {
                throw new Exception("Failed to reset target after programming");
            }

            return(true);
        }
コード例 #18
0
            private SimpleGDBCommandResult ParseAndApplyIOAccessWidths(IDebugStartService service, ISimpleGDBSession session, SimpleGDBCommandResult result)
            {
                try
                {
                    if (!File.Exists(_PeripheralFile))
                    {
                        throw new Exception("Missing " + _PeripheralFile);
                    }

                    var doc = new XmlDocument();
                    doc.Load(_PeripheralFile);

                    Dictionary <AccessKey, List <MemoryRange> > rangesByAccess = new Dictionary <AccessKey, List <MemoryRange> >();

                    foreach (var el in doc.DocumentElement.SelectNodes("moduletable/module/register").OfType <XmlElement>().OrderBy(e => TryParseAddress(e.GetAttribute("address"))))
                    {
                        int sizeinBytes;
                        switch (el.GetAttribute("size") ?? "")
                        {
                        case "B":
                            sizeinBytes = 1;
                            break;

                        case "W":
                            sizeinBytes = 2;
                            break;

                        default:
                            continue;
                        }

                        string addrString = el.GetAttribute("address");
                        int    addr       = TryParseAddress(addrString);

                        var key = new AccessKey {
                            Direction = el.GetAttribute("access"), Size = sizeinBytes
                        };
                        if (!rangesByAccess.TryGetValue(key, out var list))
                        {
                            rangesByAccess[key] = list = new List <MemoryRange>();
                        }

                        bool found = false;
                        foreach (var range in list)
                        {
                            if (range.TryAppendAddress(addr))
                            {
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            list.Add(new MemoryRange(addr, key.Size));
                        }
                    }

                    foreach (var kv in rangesByAccess)
                    {
                        foreach (var range in Slice(kv.Value, 10))
                        {
                            string cmd = $"monitor set_io_access_width,{kv.Key.Direction},{kv.Key.Size}," + string.Join(",", range.Select(r => r.ToString()));
                            result = session.RunGDBCommand(cmd);
                        }
                    }
                }
                catch (Exception ex)
                {
                    service.GUIService.LogToDiagnosticsConsole($"Failed to parse device peripheral list: " + ex.Message);
                }

                return(result);
            }