-
Notifications
You must be signed in to change notification settings - Fork 10
BSL430.NET.Library
BSL430.NET is Cross-Platform library serving as MSP430 Toolchain, to Upload, Download and Erase MCU memory, with communication based on generic UART converters like FT232 or Serial port. It uses BSL430.NET.FirmwareTools as aux library to help manage most common firmware formats like Intel-HEX, TI-TXT, SREC and ELF, with ability to Convert, Combine, Create, Parse, Validate and Get BSL password.
Note: This library is recommended to build as x86 or x64, rather than AnyCPU!
It depends on unmanaged code, that needs to use correct pointer size.
- .NET Framework 4.6.1
- .NET Standard 2.0
Communication with MCU is handled by 4 different ways. FTDI (FT232) is Windows only approach and requires FT2XX drivers installed on target PC. Another approch is called Libftdi and this works on Windows and also Linux, because rather on FT2XX original FTDI drivers it depends on open-sourced alternative libftdfi. Both ways use unmanaged libraries for low-level communication, those libraris are provided in folder lib or just integrated into Win GUI App. Another simple approch is to use standard Serial port (COM) with RS232/UART converter, or the last one, USB with F5xx/F6xx USB enabled MCUs. These 2 ways use managed libraries so you dont need to worry about anything, plus they are also multiplatform.
Unmanaged comm libs need to be put in right location, to let CLR correctly loads them, please follow .NET P/Invoke guidelines (usually in same folder as executable).
Device is then set up by three methods, first MCU family is chosen, this will determine BSL protocol and various stuff. Next Baud Rate is selected, proportionaly equal to transfer speed. Baud Rate setting is available only for modern 5xx/6xx MCUs but in some rare cases does not work like specified in official docs. Ultimately, the Invoke Method is chosen.
Invoke Method is crucial setting of the way how bootloader is turned on. It is a voltage sequence applied to certain MCU pins. It is required to connect RST/TEST pins to DTR/RTS according to Wiring Diagram and specific MCU family. These two signals forces MCU to start execute BSL bootloader code. In most cases, when MCU has Shared JTAG pins, RST(MCU) is connected to DTR(PC) and TEST(MCU) to RTS(PC). In case of MCU has Dedicated JTAG pins, connect RST(MCU) to DTR(PC) and TCK(MCU) to RTS(PC). When USB mode is used or when you want to handle this yourself, choose MANUAL.
Warning: Old 1xx/2xx/4xx bootloader protocol handle Erase or incorrectly entered
password as complete memory wipe including Info A (with calibration data),
if LOCK A bit is not set! It is always better to use modern MCUs with
5xx/6xx BSL protocol, but if there is no oher way, be careful.
This scan is useful only when targeting single device, output is Status class with error message/number and Devices list.
public ScanResult<FTDI_Device> ScanFTDI()
{
using (var dev = new BSL430NET(Mode.UART_FTD2XX))
{
var scan = dev.Scan<FTDI_Device>();
Console.WriteLine(scan.Status);
Console.WriteLine(scan.Devices);
return scan;
}
}
public ScanResult<Libftdi_Device> ScanFTDI()
{
using (var dev = new BSL430NET(Mode.UART_libftdi))
{
var scan = dev.Scan<Libftdi_Device>();
Console.WriteLine(scan.Status);
Console.WriteLine(scan.Devices);
return scan;
}
}
public ScanResult<USB_HID_Device> ScanFTDI()
{
using (var dev = new BSL430NET(Mode.USB_HID))
{
var scan = dev.Scan<USB_HID_Device>();
Console.WriteLine(scan.Status);
Console.WriteLine(scan.Devices);
return scan;
}
}
public ScanResult<Serial_Device> ScanFTDI()
{
using (var dev = new BSL430NET(Mode.UART_Serial))
{
var scan = dev.Scan<Serial_Device>();
Console.WriteLine(scan.Status);
Console.WriteLine(scan.Devices);
return scan;
}
}
This scan is the common scenario of first called method after start or clicked Scan button. There are 4 output classes device specific, each with Status class with error message/number and Devices list.
public ScanAllResult ScanAll()
{
using (var dev = new BSL430NET())
{
var scan = dev.ScanAllEx<FTDI_Device>();
Console.WriteLine(scan.FtdiDevices.Status);
Console.WriteLine(scan.LibftdiDevices.Status);
Console.WriteLine(scan.UsbDevices.Status);
Console.WriteLine(scan.SerialDevices.Status);
Console.WriteLine(scan.FtdiDevices.Devices);
Console.WriteLine(scan.LibftdiDevices.Devices);
Console.WriteLine(scan.UsbDevices.Devices);
Console.WriteLine(scan.SerialDevices.Devices);
return scan;
}
}
Uploading code to micro is the most common way how use this library. This method needs to be called only with source FirmwarePath, in formats Intel-HEX, TI-TXT, SREC or ELF. Password, key to unlock bootloader, is here optional, because mostly you want dont know it and also doesnt care about that data, because they are being overwriten with new one. However there are two use cases, when good password matters. First, you already uploaded main firmware to your device and now you want to upload only Info A memory (user settings, constants..). In this case you dont want to Erase MCU first, so you need to supply valid BSL password. Secondly, read warning below:
Warning: Password is optional for Download, but if wrong password is entered,
MCU takes it as an attack and erase all memory, executing Mass Erase.
If modern 5xx/6xx micro is used, code is just wiped, but if old
1xx/2xx/4xx one is used and LOCK A bit is not set, also Info A mem
is wiped, with factory calibration data. So please be careful.
This example is intended as a copy-paste template for already experienced developers.
public StatusEx UploadSimple(string FirmwarePath, Bsl430NetDevice Dev)
{
using (var dev = new BSL430NET(Dev))
{
dev.ProgressChanged += new Bsl430NetEventHandler(delegate
(object s, Bsl430NetEventArgs args) {
Console.WriteLine($"{args.Progress} {args.Report}");
});
dev.SetBaudRate(BaudRate.BAUD_115200);
dev.SetMCU(MCU.MSP430_F5XX);
dev.SetInvokeMechanism(InvokeMechanism.SHARED_JTAG);
Console.WriteLine($"{dev.Upload(FirmwarePath)}");
}
}
In this example 1 firmware file is uploaded to 2 different MCUs at once. There are presented two approaches how to use this library, firstly with hardcoded device, and secondly with output of Scan methods. Also Event Handling, Device settings and other various things are explained.
public StatusEx UploadDetailed()
{
string FirmwarePath = @"./firmware.hex"; // firmware file path
string HardcodedDevice = "FTDI1"; // hardcoded device name
var DeviceFromScan = new Bsl430NetDevice("COM1"); // device from Scan methods
// First way with DefaultDevice - default device is entered once into
// constructor, and then doesnt need to be filled again; the usual way.
// This example shows upload to 2 different MCUs simultaneously
using (var dev1 = new BSL430NET(HardcodedDevice))
using (var dev2 = new BSL430NET(DeviceFromScan))
{
// create simple event handler, prints progress (0-100) and report
var BslEventHandler = new Bsl430NetEventHandler(delegate
(object s, Bsl430NetEventArgs args) {
Console.WriteLine($"{args.Progress} {args.Report}");
});
// assign same event handler for both devices
dev1.ProgressChanged += BslEventHandler;
dev2.ProgressChanged += BslEventHandler;
// dev1 settings, intelliSense described, MCU is the most important
Status stat1Baud = dev1.SetBaudRate(BaudRate.BAUD_115200);
Status stat1Mcu = dev1.SetMCU(MCU.MSP430_F5XX);
Status stat1Invoke = dev1.SetInvokeMechanism(InvokeMechanism.SHARED_JTAG);
// dev2 settings
Status stat2Baud = dev2.SetBaudRate(BaudRate.BAUD_9600);
Status stat2Mcu = dev2.SetMCU(MCU.MSP430_FR6xx);
Status stat2Invoke = dev2.SetInvokeMechanism(InvokeMechanism.DEDICATED_JTAG);
// Run Upload of single firmware to 2 MCUs, BSL password is not needed,
// as Mass Erase is executed first, clearing memory. Only beware when
// 1xx/2xx/4xx old MCU is used, Mass Erase could wipe also Info A with
// calibration data. This is not case of modern 5xx/6xx MCUs, however
// if you dont want to clear memory first, you must supply BSL password
var result1 = Task.FromResult<StatusEx>(dev1.Upload(FirmwarePath));
var result2 = await Task.FromResult<StatusEx>(dev2.Upload(FirmwarePath));
// use overiden ToString method to output all important result data
Console.WriteLine($Dev1: "{result1}");
Console.WriteLine($Dev2: "{result2}");
}
}
Downloading code from micro is useful only sometimes, like when solving a problem with some remote device. This method needs to be called with AddrStart, which is the address of the very first data node wanted, next DataSize is required, as this is the count of bytes downloaded counting AddrStart. Password is key to unlock bootloader. Before call you need to set up device acording to specific situation, MCU family, Invoke Method and Baud Rate (already described). After calling data can be processed, so the Firmware Output Path is the location of created firmware made from downloaded data, formated in FwFormat specified. StatusEx is returned holding complete result info data.
Warning: Password is needed for Download. If wrong password is entered, MCU
takes it as an attack and erase all memory, executing Mass Erase.
If modern 5xx/6xx micro is used, code is just wiped, but if old
1xx/2xx/4xx one is used and LOCK A bit is not set, also Info A mem
is wiped, with factory calibration data. So please be careful.
This example is intended as a copy-paste template for already experienced developers.
public StatusEx DownloadSimple(string OutputPath, FwFormat Format, Bsl430NetDevice Dev,
int FirstAddr, int ByteSize, byte[] Password)
{
using (var dev = new BSL430NET(Dev))
{
dev.ProgressChanged += new Bsl430NetEventHandler(delegate
(object s, Bsl430NetEventArgs args) {
Console.WriteLine($"{args.Progress} {args.Report}");
});
dev.SetBaudRate(BaudRate.BAUD_115200);
dev.SetMCU(MCU.MSP430_F5XX);
dev.SetInvokeMechanism(InvokeMechanism.SHARED_JTAG);
var ret = dev.Download(Password, FirstAddr, ByteSize, out List<byte> Data);
Firmware fw = FwTools.Create(Data, FirstAddr, Format);
using (StreamWriter wr = new StreamWriter(path)) {
wr.Write(fw );
Console.WriteLine($"{ret}\n{fw}");
}
}
}
In this example ...
public StatusEx DownloadDetailed()
{
}
Erasing micro is often needed and doesnt require any input data, nor it cares about set Baud Rate value. Just call this method and quickly all memory is erased.
Warning: If old 1xx/2xx/4xx MCU is used and LOCK A bit is not set dont do it!
Info A memory will be erased as well, with factory calibration data.
This will also happen when incorrect password entered, so be careful.
Or just dont use old micros and buy a new one :)
This example is intended as a copy-paste template for already experienced developers.
public StatusEx EraseSimple(string FirmwarePath, Bsl430NetDevice Dev)
{
using (var dev = new BSL430NET(Dev))
{
dev.ProgressChanged += new Bsl430NetEventHandler(delegate
(object s, Bsl430NetEventArgs args) {
Console.WriteLine($"{args.Progress} {args.Report}");
});
dev.SetBaudRate(BaudRate.BAUD_115200);
dev.SetMCU(MCU.MSP430_F5XX);
dev.SetInvokeMechanism(InvokeMechanism.SHARED_JTAG);
Console.WriteLine($"{dev.Upload(FirmwarePath)}");
}
}
In this example ...
public StatusEx EraseDetailed()
{
}