static async Task RunOptionsAndReturnExitCodeAsync(Options o) { #region parse verbosity option switch (o.Verbosity) { // quiet case "q": case "quiet": verbosityLevel = VerbosityLevel.Quiet; break; // minimal case "m": case "minimal": verbosityLevel = VerbosityLevel.Minimal; break; // normal case "n": case "normal": verbosityLevel = VerbosityLevel.Normal; break; // detailed case "d": case "detailed": verbosityLevel = VerbosityLevel.Detailed; break; // diagnostic case "diag": case "diagnostic": verbosityLevel = VerbosityLevel.Diagnostic; break; default: throw new ArgumentException("Invalid option for Verbosity"); } #endregion Console.WriteLine(headerInfo); Console.WriteLine(copyrightInfo); Console.WriteLine(); #region target processing // if a target name was specified, try to be smart and set the platform accordingly (in case it wasn't specified) if (string.IsNullOrEmpty(o.Platform) && !string.IsNullOrEmpty(o.TargetName)) { // easiest one: ESP32 if (o.TargetName.Contains("ESP32")) { o.Platform = "esp32"; } else if ( o.TargetName.Contains("ST") || o.TargetName.Contains("MBN_QUAIL") || o.TargetName.Contains("NETDUINO3") || o.TargetName.Contains("GHI FEZ") || o.TargetName.Contains("IngenuityMicro") || o.TargetName.Contains("ORGPAL") ) { // candidates for STM32 o.Platform = "stm32"; } else if ( o.TargetName.Contains("TI_CC1352") ) { // candidates for TI CC13x2 o.Platform = "cc13x2"; } else { // other supported platforms will go here // in case a wacky target is entered by the user, the package name will be checked against Bintray repo } } #endregion #region platform specific options // if an option was specified and has an obvious platform, try to be smart and set the platform accordingly (in case it wasn't specified) if (string.IsNullOrEmpty(o.Platform)) { // JTAG related if ( o.ListJtagDevices || !string.IsNullOrEmpty(o.JtagDeviceId) || o.HexFile.Any() || o.BinFile.Any()) { o.Platform = "stm32"; } // DFU related else if ( o.ListDevicesInDfuMode || !string.IsNullOrEmpty(o.DfuDeviceId) || !string.IsNullOrEmpty(o.DfuFile)) { o.Platform = "stm32"; } // ESP32 related else if ( !string.IsNullOrEmpty(o.SerialPort) || (o.BaudRate != 921600) || (o.Esp32FlashMode != "dio") || (o.Esp32FlashFrequency != 40)) { o.Platform = "esp32"; } } #endregion #region ESP32 platform options if (o.Platform == "esp32") { // COM port is mandatory for ESP32 if (string.IsNullOrEmpty(o.SerialPort)) { _exitCode = ExitCodes.E6001; return; } EspTool espTool; try { espTool = new EspTool( o.SerialPort, o.BaudRate, o.Esp32FlashMode, o.Esp32FlashFrequency); } catch (Exception) { _exitCode = ExitCodes.E4005; return; } EspTool.DeviceInfo esp32Device; if (espTool.ComPortAvailable) { try { esp32Device = espTool.TestChip(); } catch (EspToolExecutionException ex) { _exitCode = ExitCodes.E4000; _extraMessage = ex.Message; return; } } else { // couldn't open COM port // done here, this command has no further processing _exitCode = ExitCodes.E6000; return; } if (verbosityLevel >= VerbosityLevel.Normal) { Console.WriteLine($"Connected to ESP32 { esp32Device.ChipName } with MAC address { esp32Device.MacAddress }"); Console.WriteLine($"features { esp32Device.Features }"); string flashSize = esp32Device.FlashSize >= 0x10000 ? $"{ esp32Device.FlashSize / 0x100000 }MB" : $"{ esp32Device.FlashSize / 0x400 }kB"; Console.WriteLine($"Flash information: manufacturer 0x{ esp32Device.FlashManufacturerId } device 0x{ esp32Device.FlashDeviceModelId } size { flashSize }"); } // set verbosity espTool.Verbosity = verbosityLevel; // backup requested if (!string.IsNullOrEmpty(o.BackupPath) || !string.IsNullOrEmpty(o.BackupFile)) { try { // backup path specified, backup deployment _exitCode = Esp32Operations.BackupFlash(espTool, esp32Device, o.BackupPath, o.BackupFile, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } catch (ReadEsp32FlashException ex) { _exitCode = ExitCodes.E4004; _extraMessage = ex.Message; // done here return; } } // update operation requested? if (o.Update) { try { // write flash _exitCode = await Esp32Operations.UpdateFirmwareAsync( espTool, esp32Device, o.TargetName, true, o.FwVersion, o.Stable, o.DeploymentImage, null, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } // done here _exitCode = ExitCodes.OK; return; } catch (ReadEsp32FlashException ex) { _exitCode = ExitCodes.E4004; _extraMessage = ex.Message; } catch (WriteEsp32FlashException ex) { _exitCode = ExitCodes.E4003; _extraMessage = ex.Message; } catch (EspToolExecutionException ex) { _exitCode = ExitCodes.E4000; _extraMessage = ex.Message; } } // it's OK to deploy after update if (o.Deploy) { // need to take care of flash address string appFlashAddress = null; if (o.FlashAddress.Any()) { // take the first address, it should be the only one valid appFlashAddress = o.FlashAddress.ElementAt(0); } else { _exitCode = ExitCodes.E9009; return; } // this to flash a deployment image without updating the firmware try { // write flash _exitCode = await Esp32Operations.UpdateFirmwareAsync( espTool, esp32Device, null, false, null, false, o.DeploymentImage, appFlashAddress, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } // done here _exitCode = ExitCodes.OK; return; } catch (ReadEsp32FlashException ex) { _exitCode = ExitCodes.E4004; _extraMessage = ex.Message; } catch (WriteEsp32FlashException ex) { _exitCode = ExitCodes.E4003; _extraMessage = ex.Message; } catch (EspToolExecutionException ex) { _exitCode = ExitCodes.E4000; _extraMessage = ex.Message; } } // done here return; } #endregion #region STM32 platform options if (o.Platform == "stm32") { if (o.ListDevicesInDfuMode) { var connecteDevices = StmDfuDevice.ListDfuDevices(); if (connecteDevices.Count == 0) { Console.WriteLine("No DFU devices found"); } else { Console.WriteLine("-- Connected DFU devices --"); foreach (string deviceId in connecteDevices) { Console.WriteLine(deviceId); } Console.WriteLine("---------------------------"); } // done here, this command has no further processing _exitCode = ExitCodes.OK; return; } if (o.ListJtagDevices) { try { var connecteDevices = StmJtagDevice.ListDevices(); if (connecteDevices.Count == 0) { Console.WriteLine("No JTAG devices found"); } else { Console.WriteLine("-- Connected JTAG devices --"); foreach (string deviceId in connecteDevices) { Console.WriteLine(deviceId); } Console.WriteLine("---------------------------"); } // done here, this command has no further processing _exitCode = ExitCodes.OK; } catch (Exception ex) { // exception with _exitCode = ExitCodes.E5000; _extraMessage = ex.Message; } return; } if (!string.IsNullOrEmpty(o.DfuFile)) { // there is a DFU file argument, so follow DFU path var dfuDevice = new StmDfuDevice(o.DfuDeviceId); if (!dfuDevice.DevicePresent) { // no DFU device found // done here, this command has no further processing _exitCode = ExitCodes.E1000; return; } if (verbosityLevel >= VerbosityLevel.Normal) { Console.WriteLine($"Connected to DFU device with ID { dfuDevice.DeviceId }"); } // set verbosity dfuDevice.Verbosity = verbosityLevel; // get mass erase option dfuDevice.DoMassErase = o.MassErase; try { dfuDevice.FlashDfuFile(o.DfuFile); // done here, this command has no further processing _exitCode = ExitCodes.OK; return; } catch (DfuFileDoesNotExistException) { // DFU file doesn't exist _exitCode = ExitCodes.E1002; } catch (Exception ex) { // exception with DFU operation _exitCode = ExitCodes.E1003; _extraMessage = ex.Message; } } else if ( o.BinFile.Any() && o.HexFile.Any()) { // this has to be a JTAG connected device #region STM32 JTAG options try { var jtagDevice = new StmJtagDevice(o.JtagDeviceId); if (!jtagDevice.DevicePresent) { // no JTAG device found // done here, this command has no further processing _exitCode = ExitCodes.E5001; return; } if (verbosityLevel >= VerbosityLevel.Normal) { Console.WriteLine($"Connected to JTAG device with ID { jtagDevice.DeviceId }"); } // set verbosity jtagDevice.Verbosity = verbosityLevel; // get mass erase option jtagDevice.DoMassErase = o.MassErase; if (o.HexFile.Any()) { _exitCode = jtagDevice.FlashHexFiles(o.HexFile); // done here return; } if (o.BinFile.Any()) { _exitCode = jtagDevice.FlashBinFiles(o.BinFile, o.FlashAddress); // done here return; } } catch (CantConnectToJtagDeviceException) { // done here, this command has no further processing _exitCode = ExitCodes.E5002; } #endregion } else if (!string.IsNullOrEmpty(o.TargetName)) { // update operation requested? if (o.Update) { // this to update the device with fw from Bintray // need to take care of flash address string appFlashAddress = null; if (o.FlashAddress.Any()) { // take the first address, it should be the only one valid appFlashAddress = o.FlashAddress.ElementAt(0); } _exitCode = await Stm32Operations.UpdateFirmwareAsync( o.TargetName, o.FwVersion, o.Stable, true, o.DeploymentImage, appFlashAddress, o.DfuDeviceId, o.JtagDeviceId, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } // it's OK to deploy after update if (o.Deploy) { // this to flash a deployment image without updating the firmware // need to take care of flash address string appFlashAddress = null; if (o.FlashAddress.Any()) { // take the first address, it should be the only one valid appFlashAddress = o.FlashAddress.ElementAt(0); } else { _exitCode = ExitCodes.E9009; return; } _exitCode = await Stm32Operations.UpdateFirmwareAsync( o.TargetName, null, false, false, o.DeploymentImage, appFlashAddress, o.DfuDeviceId, o.JtagDeviceId, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } // reset MCU requested? if (o.ResetMcu) { _exitCode = Stm32Operations.ResetMcu( o.JtagDeviceId, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } } } #endregion #region TI CC13x2 platform options if (o.Platform == "cc13x2") { if (!string.IsNullOrEmpty(o.TargetName)) { // update operation requested? if (o.Update) { // this to update the device with fw from Bintray // need to take care of flash address string appFlashAddress = null; if (o.FlashAddress.Any()) { // take the first address, it should be the only one valid appFlashAddress = o.FlashAddress.ElementAt(0); } _exitCode = await CC13x26x2Operations.UpdateFirmwareAsync( o.TargetName, o.FwVersion, o.Stable, true, o.DeploymentImage, appFlashAddress, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } // it's OK to deploy after update if (o.Deploy) { // this to flash a deployment image without updating the firmware // need to take care of flash address string appFlashAddress = null; if (o.FlashAddress.Any()) { // take the first address, it should be the only one valid appFlashAddress = o.FlashAddress.ElementAt(0); } else { _exitCode = ExitCodes.E9009; return; } _exitCode = await CC13x26x2Operations.UpdateFirmwareAsync( o.TargetName, null, false, false, o.DeploymentImage, appFlashAddress, verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } // reset MCU requested? if (o.ResetMcu) { // can't reset CC13x2 device without configuration file // would require to specify the exact target name and then had to try parsing that _exitCode = ExitCodes.E9000; // done here return; } } if (o.TIInstallXdsDrivers) { _exitCode = CC13x26x2Operations.InstallXds110Drivers(verbosityLevel); if (_exitCode != ExitCodes.OK) { // done here return; } } } #endregion }
internal static async System.Threading.Tasks.Task <ExitCodes> UpdateFirmwareAsync( string targetName, string fwVersion, bool stable, bool updateFw, string applicationPath, string deploymentAddress, string dfuDeviceId, string jtagId, VerbosityLevel verbosity) { bool isApplicationBinFile = false; StmDfuDevice dfuDevice; StmJtagDevice jtagDevice; // if a target name wasn't specified use the default (and only available) ESP32 target if (string.IsNullOrEmpty(targetName)) { return(ExitCodes.E1000); } Stm32Firmware firmware = new Stm32Firmware( targetName, fwVersion, stable) { Verbosity = verbosity }; // need to download update package? if (updateFw) { var operationResult = await firmware.DownloadAndExtractAsync(); if (operationResult != ExitCodes.OK) { return(operationResult); } // download successful } // setup files to flash var filesToFlash = new List <string>(); if (updateFw) { filesToFlash.Add(firmware.nanoBooterFile); filesToFlash.Add(firmware.nanoCLRFile); } // need to include application file? if (!string.IsNullOrEmpty(applicationPath)) { // check application file if (File.Exists(applicationPath)) { // check if application is BIN or HEX file if (Path.GetExtension(applicationPath) == "hex") { // HEX we are good with adding it to the flash package filesToFlash.Add(new FileInfo(applicationPath).FullName); } else { // BIN app, set flag isApplicationBinFile = true; } } else { return(ExitCodes.E9008); } } // need DFU or JTAG device if (firmware.HasDfuPackage) { // DFU package dfuDevice = new StmDfuDevice(dfuDeviceId); if (!dfuDevice.DevicePresent) { // no DFU device found // done here, this command has no further processing return(ExitCodes.E1000); } if (verbosity >= VerbosityLevel.Normal) { Console.WriteLine($"Connected to DFU device with ID { dfuDevice.DeviceId }"); } // set verbosity dfuDevice.Verbosity = verbosity; try { dfuDevice.FlashDfuFile(firmware.DfuPackage); // done here, this command has no further processing return(ExitCodes.OK); } catch (Exception) { // exception return(ExitCodes.E1003); } } else { // JATG device jtagDevice = new StmJtagDevice(jtagId); if (!jtagDevice.DevicePresent) { // no JTAG device found // done here, this command has no further processing return(ExitCodes.E5001); } if (verbosity >= VerbosityLevel.Normal) { Console.WriteLine($"Connected to JTAG device with ID { jtagDevice.DeviceId }"); } // set verbosity jtagDevice.Verbosity = verbosity; ExitCodes programResult = ExitCodes.OK; // write HEX files to flash if (filesToFlash.Any(f => f.EndsWith(".hex"))) { programResult = jtagDevice.FlashHexFiles(filesToFlash); } if (programResult == ExitCodes.OK && isApplicationBinFile) { // now program the application file programResult = jtagDevice.FlashBinFiles(new List <string>() { applicationPath }, new List <string>() { deploymentAddress }); } if (updateFw) { // reset MCU jtagDevice.ResetMcu(); } return(programResult); } }