public IGDBStubInstance StartGDBStub(IDebugStartService startService, DebugStartContext context) { var settings = (RedLinkDebugSettings)context.Configuration ?? new RedLinkDebugSettings(); var cmdLine = new RedLinkServerCommandLine(settings.CommandLineArguments); int gdbPort; using (var allocator = startService.BeginAllocatingTCPPorts()) { gdbPort = allocator.AllocateUnusedTCPPort("SYS:GDB_PORT"); } var ideRoot = RegistrySettings.MCUXpressoPath ?? throw new Exception("Please specify the MCUXpresso directory via Debug Settings"); bool programNow; switch (settings.ProgramMode) { case ProgramMode.Disabled: programNow = false; break; case ProgramMode.Auto: programNow = !startService.IsCurrentFirmwareAlreadyProgrammed(); break; default: programNow = true; break; } var gdbServer = Path.Combine(ideRoot, @"binaries\crt_emu_cm_redlink.exe"); if (!File.Exists(gdbServer)) { throw new Exception("Could not find " + gdbServer); } var cmdLineText = cmdLine.CommandLine; if (cmdLineText.Contains(DeviceDirectoryVariableReference)) { var db = new RedLinkDeviceDatabase(); var device = cmdLine.Device ?? throw new Exception("RedLink command line does not specify the device (-pXXX)"); var vendor = cmdLine.Vendor ?? throw new Exception("RedLink command line does not specify the vendor (-vendor)"); device = startService.ExpandProjectVariables(device, true, false); vendor = startService.ExpandProjectVariables(vendor, true, false); var dev = db.ProvideDeviceDefinition(vendor, device) ?? throw new Exception($"Unknown vendor/device: {vendor}/{device}. Please use VisualGDB Project Properties -> Debug Settings to configure."); cmdLineText = cmdLineText.Replace(DeviceDirectoryVariableReference, TranslatePath(dev.DefinitionDirectory)); } if (cmdLineText.Contains(FLASHDriverDirectoryVariableReference)) { var pluginDir = Path.Combine(ideRoot, "plugins"); if (Directory.Exists(pluginDir)) { var toolsPlugin = Directory.GetDirectories(pluginDir, "com.nxp.mcuxpresso.tools.bin.win32*").FirstOrDefault(); if (toolsPlugin != null) { cmdLineText = cmdLineText.Replace(FLASHDriverDirectoryVariableReference, TranslatePath(Path.Combine(toolsPlugin, @"binaries\Flash"))); } } } string explicitSerialNumber = null; if (context.ResolvedDevices?.BestMatch.Device.SerialNumber != null) { if ((context.ResolvedDevices.AllCompatibleDevices?.Length ?? 0) > 1 || settings.AlwaysUseProbeSerialNumber) { explicitSerialNumber = context.ResolvedDevices.BestMatch.Device.SerialNumber; cmdLineText += " --probeserial " + explicitSerialNumber; } } int coreIndex = 0; if (cmdLine.Core is string core) { core = startService.ExpandProjectVariables(core, true, false); int.TryParse(core, out coreIndex); } var tool = startService.LaunchCommandLineTool(new CommandLineToolLaunchInfo { Command = gdbServer, Arguments = cmdLineText, WorkingDirectory = Path.GetDirectoryName(gdbServer) }); return(new RedLinkGDBStub(context, settings, cmdLine, gdbPort, tool, programNow, explicitSerialNumber, coreIndex)); }
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); } } }
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); }
public ProgrammableRegion ToProgrammableRegion(IDebugStartService service) { return(new ProgrammableRegion { FileName = service.ExpandProjectVariables(Path, true, true), Offset = ParseAddress(Offset) }); }