cancel
Showing results for 
Search instead for 
Did you mean: 

C# API to create custom ST-LINK utility software

jprinster
Associate II

I have a custom C# application for production testing of one of our boards that has an STM32 processor on it. To program the bootloader into the flash I use the ST-LINK utility software. I would like to integrate the program and verify functionality into my production test software so the user doesn't have to leave my software to run the ST-LINK utility. Is there an API available that would give me access to the ST-LINK to program a processor?

Thank you.

5 REPLIES 5

Don't know about C#, but STM32CubeProgrammer provides a C++ API:

In addition to the graphical user interface and to the command line interfaceSTM32CubeProgrammer offers a C++ API that can be used to develop your application...

...For more information about the C++ API, read the help file provided within theSTM32CubeProgrammer package under API\doc folder.

https://www.st.com/en/development-tools/stm32cubeprog.html

stanley.setiawan
Associate II

Hello! I happen to have a similar case like you @jprinster​ . Do you manage to get those APIs? I do know that SEGGER (link) have those APIs but they need us to purchase the license before downloading it.

I ended up just creating a system process (basically the same as a command window) and then called the ST-LINK Utility command line interface. It means the target PC has to have ST-LINK Utility installed, but that's not a big deal since the application I wrote is only used within our building. Here's the code I created from some other example.

using System; 
using System.Diagnostics; 
using System.IO; 
 
namespace Application.STLink { 
  public class STLinkAdapter { 
 
    //==================================================== 
    #region Data Properties 
    private const string CmdListDevices = "-List"; 
    private const string CmdConnectToTarget = "-c ID=0 SWD"; 
    private const string CmdProgramFromFile = "-P"; 
    private const string CmdFlashErase = "-ME"; 
    private const string CmdVerifyProgramming = "-V"; 
    private const string CmdRunFirmware = "-Run"; 
    private const string CmdNoPrompt = "-NoPrompt"; 
    private const string STLinkCLIDefaultPath = @"C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe "; 
    public string STLinkCLIAppPath { get; set; } 
    #endregion
 
    //======================================================= 
    #region Constructor 
    public STLinkAdapter(string a_STLinkCLIAppPath) { 
      if (string.IsNullOrEmpty(a_STLinkCLIAppPath)) { 
        STLinkCLIAppPath = STLinkCLIDefaultPath; 
      } 
    } 
    #endregion
 
    //======================================================= 
    #region Procedures 
    public STLinkReturnCodes FindSTLink(out string a_ResultOut) { 
      STLinkReturnCodes l_STLinkReturnCode = STLinkReturnCodes.Success; 
      l_STLinkReturnCode = ExecuteCommandSync(STLinkCLIAppPath, CmdListDevices, out a_ResultOut); 
      if (l_STLinkReturnCode == STLinkReturnCodes.Success) { 
        if (a_ResultOut.Contains("No ST-LINK detected")) { 
          a_ResultOut = "No ST-Link found"; 
          l_STLinkReturnCode = STLinkReturnCodes.Failure; 
        } 
        else { 
          a_ResultOut = "ST-Link detected"; 
        } 
      } 
      return l_STLinkReturnCode; 
    }
 
    //----------------------------------- 
    public STLinkReturnCodes ConnectToTarget(string a_TargetProcessor, out string a_ResultOut) { 
      STLinkReturnCodes l_STLinkReturnCode = STLinkReturnCodes.Success;
 
      l_STLinkReturnCode = ExecuteCommandSync(STLinkCLIAppPath, CmdConnectToTarget, out a_ResultOut);
 
      if (l_STLinkReturnCode == STLinkReturnCodes.Success) { 
        if (a_ResultOut.Contains(a_TargetProcessor)) { 
          a_ResultOut = "Target processor found: " + a_TargetProcessor; 
          l_STLinkReturnCode = STLinkReturnCodes.Success; 
        } 
        else { 
          a_ResultOut = "Target processor not found."; 
          l_STLinkReturnCode = STLinkReturnCodes.Failure; 
        } 
      } 
      return l_STLinkReturnCode; 
    }
 
 
 
    //----------------------------------- 
    public STLinkReturnCodes ProgramTarget(string a_BinFilePath, UInt32 a_FlashAddress, out string a_ResultOut) { 
      STLinkReturnCodes l_STLinkReturnCode = STLinkReturnCodes.Success; 
      a_ResultOut = string.Empty;
      if (File.Exists(a_BinFilePath) == false) { 
        l_STLinkReturnCode = STLinkReturnCodes.Failure; 
        a_ResultOut = "Bin file doesn't exist."; 
      }
 
      if (l_STLinkReturnCode == STLinkReturnCodes.Success) { 
        string l_CommandArguments = string.Format("{0} {1} {2} \"{3}\" 0x{4:X8} {5} {6} {7}", CmdConnectToTarget, CmdFlashErase, CmdProgramFromFile, a_BinFilePath, a_FlashAddress, CmdVerifyProgramming, CmdNoPrompt, CmdRunFirmware);
 
        l_STLinkReturnCode = ExecuteCommandSync(STLinkCLIAppPath, l_CommandArguments, out a_ResultOut); 
        if (l_STLinkReturnCode == STLinkReturnCodes.Success) { 
          if (a_ResultOut.Contains("Verification...OK")) { 
            a_ResultOut = "Target successfully programmed."; 
            l_STLinkReturnCode = STLinkReturnCodes.Success; 
          } 
          else { 
            a_ResultOut += "Programming failed!"; 
            l_STLinkReturnCode = STLinkReturnCodes.Failure; 
          } 
        } 
      } 
      return l_STLinkReturnCode; 
    }
 
    //----------------------------------- 
    /// <summary> 
    /// Executes a shell command synchronously. 
    /// </summary> 
    /// <param name="command">string command</param> 
    /// <returns>string, as output of the command.</returns> 
    private STLinkReturnCodes ExecuteCommandSync(string a_AppPath, string a_CommandParameters, out string a_ResultOut) { 
      STLinkReturnCodes l_STLinkReturnCode = STLinkReturnCodes.Success;       
       a_ResultOut = string.Empty;
 
      try { 
        // create the ProcessStartInfo using "cmd" as the program to be run, and "/c " as the parameters. 
        // Incidentally, /c tells cmd that we want it to execute the command that follows, and then exit. 
        System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(); 
        procStartInfo.FileName = a_AppPath; 
        procStartInfo.Arguments = a_CommandParameters;
        // The following commands are needed to redirect the standard output.  
        //This means that it will be redirected to the Process.StandardOutput StreamReader. 
        procStartInfo.RedirectStandardOutput = true;
        procStartInfo.UseShellExecute = false;
 
        // Do not create the black window.
        procStartInfo.CreateNoWindow = true;
 
        // Now we create a process, assign its ProcessStartInfo and start it
        using (Process l_process = Process.Start(procStartInfo)) {
          l_process.WaitForExit();
 
          // Get the output into a string
          using (StreamReader reader = l_process.StandardOutput) {
            a_ResultOut = reader.ReadToEnd();
          }
        }
        l_STLinkReturnCode = STLinkReturnCodes.Success;
      }
      catch (Exception objException) {
        l_STLinkReturnCode = STLinkReturnCodes.Failure;
        a_ResultOut = "Failure";
      }
      return l_STLinkReturnCode; 
    }
    //-----------------------------------
    #endregion
  }
}

The other half of the code....

namespace Application.STLink {
    public enum STLinkReturnCodes {
        Success = 0,
        Failure = 1
    }
}

The calls to actually use it.....

            // Connecting to the ST-LINK/V2.
            if (l_STLinkReturnCode == STLinkReturnCodes.Success) {
                l_STLinkReturnCode = await Task.Run(() => l_STLinkAdapter.FindSTLink(out l_STLinkResponse));
            }
 
            // Connecting to the processor target.  The target process or is a string like "STM32F05".
            if (l_STLinkReturnCode == STLinkReturnCodes.Success) {
                l_STLinkReturnCode = await Task.Run(() => l_STLinkAdapter.ConnectToTarget(l_FirmwareInfo.TargetProcessor, out l_STLinkResponse));
            }
 
            // Programming flashloader
            if (l_STLinkReturnCode == STLinkReturnCodes.Success) {
                l_STLinkReturnCode = await Task.Run(() => l_STLinkAdapter.ProgramTarget(l_BinFilePath, l_FirmwareInfo.FlashloaderFlashAddress, out l_STLinkResponse));
            }

wow thank you very much for your kind help! I will try out this code.. Thanks again!!