Skip to content

Instantly share code, notes, and snippets.

@visuve
Last active July 30, 2022 11:02
Show Gist options
  • Select an option

  • Save visuve/efbfa1eb8e2dc27bb66a1fbc8afd6c51 to your computer and use it in GitHub Desktop.

Select an option

Save visuve/efbfa1eb8e2dc27bb66a1fbc8afd6c51 to your computer and use it in GitHub Desktop.
Deploy .uf2 files on a Pico and open a serial port for monitoring
using System.IO.Ports;
using System.Management;
class PicoDeploy
{
private static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Usage:");
Console.WriteLine("\t <serialport> e.g. COM5");
Console.WriteLine("\t <uf2filepath> [optional]");
return;
}
if (args.Length == 2)
{
Deploy(args[1]);
}
ReadSerial(args[0]);
}
private static void Deploy(string uf2file)
{
string extension = Path.GetExtension(uf2file);
if (extension != ".uf2")
{
Console.WriteLine($"Expected .uf2 file extension, got \"{extension}\"");
return;
}
try
{
DriveInfo[] drives = DriveInfo.GetDrives();
var picoDrive = drives.SingleOrDefault(drive =>
drive.DriveFormat == "FAT" &&
drive.DriveType == DriveType.Removable &&
drive.IsReady == true &&
drive.VolumeLabel == "RPI-RP2");
if (picoDrive == null)
{
Console.WriteLine("Failed to find a Pico drive for deployment!");
return;
}
string fileName = Path.GetFileName(uf2file);
File.Copy(uf2file, Path.Combine(picoDrive.Name, fileName));
Console.WriteLine("Waiting 2s for the Pico to boot...");
Thread.Sleep(2000);
}
catch (Exception e)
{
Console.WriteLine("Failed to copy .uf2 file!");
Console.WriteLine(e.ToString());
return;
}
}
private static void ReadSerial(string portName)
{
try
{
var serialPort = new SerialPort(portName);
serialPort.BaudRate = 115200;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.Parity = Parity.None;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.DtrEnable = true;
serialPort.DataReceived += (s, e) =>
{
Console.Write(serialPort.ReadExisting());
};
serialPort.ErrorReceived += (s, e) =>
{
Console.WriteLine("An error occurred while reading the serial port!");
Console.WriteLine(e.ToString());
Environment.Exit(0x0000001E); // ERROR_READ_FAULT, "The system cannot read from the specified device."
};
// The SerialPort class does not fire any event when the whole device disappears
var query = new WqlEventQuery()
{
EventClassName = "__InstanceOperationEvent",
WithinInterval = new TimeSpan(0, 0, 5),
Condition = "TargetInstance ISA 'WIN32_SerialPort'"
};
var watcher = new ManagementEventWatcher(query);
watcher.EventArrived += (s, e) =>
{
if (e.NewEvent.ClassPath.ClassName != "__InstanceDeletionEvent")
{
return;
}
using var mbo = e.NewEvent.Properties["TargetInstance"].Value as ManagementBaseObject;
string? deviceId = mbo?.Properties["DeviceID"]?.Value.ToString();
if (deviceId == portName)
{
Console.WriteLine($"{portName} disappeared! Closing...");
Environment.Exit(0x00000014); // ERROR_NOT_READY, "The device is not ready."
}
};
serialPort.Open();
Console.WriteLine($"{portName} opened!");
Console.WriteLine("Press any key to exit");
watcher.Start();
Console.ReadKey();
}
catch (Exception e)
{
Console.WriteLine($"Failed to open/read {portName}!");
Console.WriteLine(e.ToString());
return;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment