Add support for setting VCP baud rate in Silabs JLink devices (#142)
This commit is contained in:
Родитель
8b51b4f272
Коммит
181bbb4193
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -208,6 +208,12 @@ namespace nanoFramework.Tools.FirmwareFlasher
|
|||
[Display(Name = "No J-Link device found. Make sure it's connected.")]
|
||||
E8001 = 8001,
|
||||
|
||||
/// <summary>
|
||||
/// Error executing silink command.
|
||||
/// </summary>
|
||||
[Display(Name = "Error executing silink CLI command.")]
|
||||
E8002 = 8002,
|
||||
|
||||
////////////////////////////////
|
||||
// Application general Errors //
|
||||
////////////////////////////////
|
||||
|
|
|
@ -1125,6 +1125,7 @@ namespace nanoFramework.Tools.FirmwareFlasher
|
|||
|
||||
var connectedJLinkDevices = JLinkDevice.ListDevices();
|
||||
|
||||
|
||||
if (o.BinFile.Any()
|
||||
&& connectedJLinkDevices.Count != 0)
|
||||
{
|
||||
|
@ -1147,6 +1148,9 @@ namespace nanoFramework.Tools.FirmwareFlasher
|
|||
Console.WriteLine($"Connected to J-Link device with ID {jlinkDevice.ProbeId}");
|
||||
}
|
||||
|
||||
// set VCP baud rate (if needed)
|
||||
_ = SilinkCli.SetVcpBaudRate(o.JLinkDeviceId is null ? connectedJLinkDevices.First() : "");
|
||||
|
||||
// set verbosity
|
||||
jlinkDevice.Verbosity = _verbosityLevel;
|
||||
|
||||
|
@ -1196,6 +1200,9 @@ namespace nanoFramework.Tools.FirmwareFlasher
|
|||
|
||||
operationPerformed = true;
|
||||
|
||||
// set VCP baud rate (if needed)
|
||||
_ = SilinkCli.SetVcpBaudRate(o.JLinkDeviceId is null ? connectedJLinkDevices.First() : "");
|
||||
|
||||
if (_exitCode != ExitCodes.OK)
|
||||
{
|
||||
// done here
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
//
|
||||
// Copyright (c) .NET Foundation and Contributors
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace nanoFramework.Tools.FirmwareFlasher
|
||||
{
|
||||
internal class SilinkCli
|
||||
{
|
||||
private const int SilinkTelnetPort = 49000;
|
||||
private const int SilinkAdminPort = SilinkTelnetPort + 2;
|
||||
private const int TargetBaudRate = 921600;
|
||||
|
||||
/// <summary>
|
||||
/// This will set the baud rate of the VCP in a Silabs Jlink board.
|
||||
/// Before setting the value the devices is queried and the new setting is applied only if needed.
|
||||
/// </summary>
|
||||
/// <param name="probeId">Id of the JLink probe to adjust the baud rate.</param>
|
||||
/// <param name="verbosity">Verbosity level for the operation. <see cref="VerbosityLevel.Quiet"/> will be used if not specified.</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Currently this operation is only supported in Windows machines.
|
||||
/// </remarks>
|
||||
public static ExitCodes SetVcpBaudRate(
|
||||
string probeId,
|
||||
VerbosityLevel verbosity = VerbosityLevel.Quiet)
|
||||
{
|
||||
// check that we can run on this platform
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
|
||||
|| RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Console.WriteLine("");
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
|
||||
Console.WriteLine($"Setting VCP baud rate in {OSPlatform.OSX} is not supported.");
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("");
|
||||
|
||||
return ExitCodes.E8002;
|
||||
}
|
||||
|
||||
// launch silink
|
||||
var silinkCli = RunSilinkCLI(Path.Combine(probeId));
|
||||
|
||||
var silinkSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
IPEndPoint silinkEndPoint = new(IPAddress.Parse("127.0.0.1"), SilinkAdminPort);
|
||||
|
||||
try
|
||||
{
|
||||
silinkSocket.Connect(silinkEndPoint);
|
||||
|
||||
Thread.Sleep(250);
|
||||
|
||||
// query current config
|
||||
byte[] buffer = Encoding.Default.GetBytes("serial vcom\r");
|
||||
silinkSocket.Send(buffer);
|
||||
|
||||
Thread.Sleep(250);
|
||||
|
||||
buffer = new byte[1024];
|
||||
int receiveCount = silinkSocket.Receive(buffer, 0, buffer.Length, 0);
|
||||
|
||||
var currentConfig = Encoding.Default.GetString(buffer, 0, receiveCount);
|
||||
|
||||
if (!string.IsNullOrEmpty(currentConfig))
|
||||
{
|
||||
// interpret reply
|
||||
const string regexPattern = "(?:Stored port speed : )(?'baudrate'\\d+)";
|
||||
|
||||
var myRegex1 = new Regex(regexPattern, RegexOptions.Multiline);
|
||||
var currentBaud = myRegex1.Match(currentConfig);
|
||||
|
||||
if (currentBaud.Success)
|
||||
{
|
||||
// verify current setting
|
||||
if (int.TryParse(currentBaud.Groups["baudrate"].Value, out int baudRate) && baudRate == TargetBaudRate)
|
||||
{
|
||||
return ExitCodes.OK;
|
||||
}
|
||||
}
|
||||
|
||||
// need to set baud rate because it's different
|
||||
|
||||
if (verbosity >= VerbosityLevel.Normal)
|
||||
{
|
||||
Console.Write("Setting VCP baud rate...");
|
||||
}
|
||||
|
||||
Thread.Sleep(250);
|
||||
|
||||
// compose command
|
||||
buffer = Encoding.Default.GetBytes("serial vcom config speed {TargetBaudRate}\r");
|
||||
silinkSocket.Send(buffer);
|
||||
|
||||
Thread.Sleep(250);
|
||||
|
||||
buffer = new byte[1024];
|
||||
receiveCount = silinkSocket.Receive(buffer, 0, buffer.Length, 0);
|
||||
|
||||
var opResult = Encoding.Default.GetString(buffer, 0, receiveCount);
|
||||
|
||||
if (opResult.Contains("Baudrate set to 921600 bps"))
|
||||
{
|
||||
if (verbosity >= VerbosityLevel.Normal)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine(" OK");
|
||||
|
||||
Console.WriteLine("");
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
}
|
||||
|
||||
return ExitCodes.OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbosity >= VerbosityLevel.Normal)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("FAILED!");
|
||||
|
||||
Console.WriteLine("");
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
|
||||
Console.WriteLine($"{opResult.Replace("PK> ", "")}");
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("");
|
||||
}
|
||||
|
||||
return ExitCodes.E8002;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("");
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
|
||||
Console.WriteLine($"Error occurred: {ex.Message}");
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("");
|
||||
|
||||
return ExitCodes.E8002;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// close socket
|
||||
silinkSocket?.Close();
|
||||
|
||||
// kill process tree (to include JLink)
|
||||
silinkCli.Kill(true);
|
||||
}
|
||||
|
||||
return ExitCodes.E8002;
|
||||
}
|
||||
|
||||
internal static Process RunSilinkCLI(string probeId)
|
||||
{
|
||||
// prepare the process start of J-Link
|
||||
string appName = "silink.exe";
|
||||
string appDir = Path.Combine(Program.ExecutingPath, "silink");
|
||||
|
||||
|
||||
Process silinkCli = new Process();
|
||||
string parameter = $" -sn {probeId} -automap {SilinkTelnetPort}";
|
||||
|
||||
silinkCli.StartInfo = new ProcessStartInfo(Path.Combine(appDir, appName), parameter)
|
||||
{
|
||||
WorkingDirectory = appDir,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
};
|
||||
|
||||
// start siLink CLI and...
|
||||
silinkCli.Start();
|
||||
|
||||
// ... return the process
|
||||
return silinkCli;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -103,6 +103,8 @@
|
|||
</None>
|
||||
<None Include="..\lib\jlinkLinux\**" Link="jlinkLinux\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="Always">
|
||||
</None>
|
||||
<None Include="..\lib\silink\**" Link="silink\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="Always">
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\lib\uniflash\**" Link="uniflash\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="Always">
|
||||
|
|
Загрузка…
Ссылка в новой задаче