diff --git a/nanoFirmwareFlasher.Library/JLinkCli.cs b/nanoFirmwareFlasher.Library/JLinkCli.cs
index 1c2fad14..6be0ebf5 100644
--- a/nanoFirmwareFlasher.Library/JLinkCli.cs
+++ b/nanoFirmwareFlasher.Library/JLinkCli.cs
@@ -29,10 +29,15 @@ public class JLinkCli
///
private const string FlashAddressToken = "{FLASH_ADDRESS}";
+ ///
+ /// Token to replace with address to flash.
+ ///
+ private const string LoadFileListToken = "{LOAD_FILE_LIST}";
+
///
/// Template for JLink command file to flash a file.
///
- private const string FlashFileCommandTemplate = $@"
+ private const string FlashSingleFileCommandTemplate = $@"
USB
speed auto
Halt
@@ -40,6 +45,19 @@ speed auto
Reset
Go
Exit
+";
+
+ ///
+ /// Template for JLink command file to flash multiple files.
+ ///
+ private const string FlashMultipleFilesCommandTemplate = $@"
+USB
+speed auto
+Halt
+{LoadFileListToken}
+Reset
+Go
+Exit
";
///
@@ -240,7 +258,7 @@ public ExitCodes ExecuteFlashBinFiles(
}
// compose JLink command file
- var jlinkCmdContent = FlashFileCommandTemplate.Replace(FilePathToken, binFilePath).Replace(FlashAddressToken, addresses.ElementAt(index++));
+ var jlinkCmdContent = FlashSingleFileCommandTemplate.Replace(FilePathToken, binFilePath).Replace(FlashAddressToken, addresses.ElementAt(index++));
var jlinkCmdFilePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.jlink");
// create file
@@ -293,6 +311,152 @@ public ExitCodes ExecuteFlashBinFiles(
return ExitCodes.OK;
}
+ ///
+ /// Executes an operation that flashes a collection of Intel HEX format files to a connected J-Link device.
+ ///
+ /// List of files to flash to the device.
+ /// ID of the J-Link device to execute the operation into. Leave to use the default address.
+ ///
+ public ExitCodes ExecuteFlashHexFiles(
+ IList files,
+ string probeId)
+ {
+ // check file existence
+ if (files.Any(f => !File.Exists(f)))
+ {
+ return ExitCodes.E5004;
+ }
+
+ List shadowFiles = new List();
+
+ // J-Link can't handle diacritc chars
+ // developer note: reported to Segger (Case: 60276735) and can be removed if this is fixed/improved
+ foreach (string hexFile in files)
+ {
+ if (!hexFile.IsNormalized(NormalizationForm.FormD) ||
+ hexFile.Contains(' '))
+ {
+ var tempFile = Path.Combine(
+ Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.Machine),
+ Path.GetFileName(hexFile));
+
+ // copy file to shadow file
+ File.Copy(
+ hexFile,
+ tempFile,
+ true);
+
+ shadowFiles.Add(tempFile);
+ }
+ else
+ {
+ // copy file to shadow list
+ shadowFiles.Add(hexFile);
+ }
+ }
+
+ // erase flash
+ if (DoMassErase)
+ {
+ var eraseResult = ExecuteMassErase(probeId);
+
+ if (eraseResult != ExitCodes.OK)
+ {
+ return eraseResult;
+ }
+
+ // toggle mass erase so it's only performed before the first file is flashed
+ DoMassErase = false;
+ }
+
+ if (Verbosity < VerbosityLevel.Normal)
+ {
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.Write("Flashing device...");
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("Flashing device...");
+ }
+
+ // program HEX file(s)
+ StringBuilder listOfFiles = new StringBuilder();
+
+ foreach (string hexFile in shadowFiles)
+ {
+ // make sure path is absolute
+ var hexFilePath = Utilities.MakePathAbsolute(
+ Environment.CurrentDirectory,
+ hexFile);
+
+ if (Verbosity > VerbosityLevel.Normal)
+ {
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.WriteLine($"{Path.GetFileName(hexFilePath)}");
+ }
+
+ listOfFiles.AppendLine($"LoadFile {hexFilePath}");
+ }
+
+ // compose JLink command file
+ var jlinkCmdContent = FlashMultipleFilesCommandTemplate.Replace(
+ LoadFileListToken,
+ listOfFiles.ToString());
+
+ var jlinkCmdFilePath = Path.Combine(
+ Path.GetTempPath(),
+ $"{Guid.NewGuid()}.jlink");
+
+ // create file
+ var jlinkCmdFile = File.CreateText(jlinkCmdFilePath);
+ jlinkCmdFile.Write(jlinkCmdContent);
+ jlinkCmdFile.Close();
+
+ var cliOutput = RunJLinkCLI(jlinkCmdFilePath);
+
+ // OK to delete the JLink command file
+ File.Delete(jlinkCmdFilePath);
+
+ if (Verbosity >= VerbosityLevel.Normal
+ && cliOutput.Contains("Skipped. Contents already match"))
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+
+ Console.WriteLine("");
+ Console.WriteLine("******************* WARNING *********************");
+ Console.WriteLine("Skip flashing. Contents already match the update.");
+ Console.WriteLine("*************************************************");
+ Console.WriteLine("");
+
+ Console.ForegroundColor = ConsoleColor.White;
+ }
+ else if (!(cliOutput.Contains("Flash download: Program & Verify")
+ && cliOutput.Contains("O.K.")))
+ {
+ ShowCLIOutput(cliOutput);
+
+ return ExitCodes.E5006;
+ }
+
+ ShowCLIOutput(cliOutput);
+
+ if (Verbosity < VerbosityLevel.Normal)
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine(" OK");
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine("Flashing completed...");
+ }
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ return ExitCodes.OK;
+ }
+
public void ShowCLIOutput(string cliOutput)
{
// show CLI output, if verbosity is diagnostic
diff --git a/nanoFirmwareFlasher.Library/JLinkDevice.cs b/nanoFirmwareFlasher.Library/JLinkDevice.cs
index d83eaee7..76e67835 100644
--- a/nanoFirmwareFlasher.Library/JLinkDevice.cs
+++ b/nanoFirmwareFlasher.Library/JLinkDevice.cs
@@ -164,5 +164,16 @@ public ExitCodes FlashBinFiles(IList files, IList addresses)
addresses,
ProbeId);
}
+
+ ///
+ /// Flash the HEX supplied to the connected device.
+ ///
+ ///
+ public ExitCodes FlashHexFiles(IList files)
+ {
+ return ExecuteFlashHexFiles(
+ files,
+ ProbeId);
+ }
}
}
diff --git a/nanoFirmwareFlasher.Library/JLinkOperations.cs b/nanoFirmwareFlasher.Library/JLinkOperations.cs
index 1c19cc62..c71f5da5 100644
--- a/nanoFirmwareFlasher.Library/JLinkOperations.cs
+++ b/nanoFirmwareFlasher.Library/JLinkOperations.cs
@@ -103,13 +103,13 @@ public static async System.Threading.Tasks.Task UpdateFirmwareAsync(
var connectedSilabsJLinkDevices = JLinkDevice.ListDevices();
- if (connectedSilabsJLinkDevices.Any())
+ if (!connectedSilabsJLinkDevices.Any())
{
// no device was found
return ExitCodes.E9010;
}
- // JTAG device
+ // Jlink device
jlinkDevice = new JLinkDevice(probeId);
if (!jlinkDevice.DevicePresent)
@@ -152,6 +152,12 @@ public static async System.Threading.Tasks.Task UpdateFirmwareAsync(
// set verbosity
jlinkDevice.Verbosity = verbosity;
+ // write HEX files to flash
+ if (filesToFlash.Any(f => f.EndsWith(".hex")))
+ {
+ operationResult = jlinkDevice.FlashHexFiles(filesToFlash);
+ }
+
if (operationResult == ExitCodes.OK && isApplicationBinFile)
{
// now program the application file