最近需要写一个烧录软件,让工厂可以实现一键烧录。
1.命令行烧录
这里实现了运行一个bat文件进行一键烧录,不想看这部分的可以直接跳到第二部分,不受影响。
由于jlink的自带烧录软件JFlash.exe操作十分繁杂,需要自己开发一个简洁的烧录方法,一番操作发现,可以使用J-Link Commander 的命令行进行烧录,操作流程如下:
既然可以用这个命令行,那就可以用bat文件来执行,此间需要生成一个.jlink文件供命令行执行,总共需要两个文件,我这里是burn_hex.bat 和 burn_script.jlink,具体内容如下:
burn_hex.bat:
@echo off
set JLINK_PATH="C:\Program Files (x86)\SEGGER\JLink\JLink.exe"
set HEX_FILE_PATH="Programmer.hex"
set CHIP_MODEL=NRF52832
%JLINK_PATH% -device %CHIP_MODEL% -if SWD -speed 4000 -CommanderScript burn_script.jlink
burn_script.jlink:
connect
device NRF52832_XXAA
speed 4000
TIF SWD
loadfile D:\Programmer.hex
r
g
q
两个 文件放在同一目录下,将hex路径设置正确,点击bat文件即可进行烧录。
命令行衍生上位机
既然可以按如上的方式烧录,那用上位机生成*.jlink文件再执行bat即可实现上位机烧录,但是这种方式不够灵活。
2.C#调用JLinkARM.dll烧录
通过调查发现,jlink的烧录都有调用JLinkARM.dll里面的接口,那开发者也可以调用,但是SEGGER并未开源,需要花钱购买全部的接口。好在有大佬成功逆向了部分接口,原帖:c#的 JLINK API,自己用的 (amobbs.com 阿莫电子技术论坛)
稍全的接口如下(C++):
//arm.h,裡面的API list 如下
/*********************************************************************
*
* API functions
*/
void JLINKARM_Close(void);
void JLINKARM_ClrBP(unsigned BPIndex);
void JLINKARM_ClrError(void);
void JLINKARM_EnableLog2File(void);
const char * JLINKARM_GetCompileDateTime(void);
U16 JLINKARM_GetEmbeddedFWVersion(void);
void JLINKARM_GetHWStatus(JTAG_HW_STATUS * pStat);
U32 JLINKARM_GetId(void);
void JLINKARM_GetIdData(JTAG_ID_DATA * pIdData);
U16 JLINKARM_GetSelDevice(void);
int JLINKARM_GetVoltage(void);
U16 JLINKARM_GetSpeed(void);
void JLINKARM_Go(void);
void JLINKARM_GoIntDis(void);
char JLINKARM_Halt(void);
char JLINKARM_HaltNoSave(void);
char JLINKARM_IsConnected(void);
char JLINKARM_IsHalted(void);
const char * JLINKARM_Open(void);
int JLINKARM_ReadDCC(U32 * pData, U32 NumItems, int TimeOut);
void JLINKARM_ReadDCCFast(U32 * pData, U32 NumItems);
U32 JLINKARM_ReadICEReg(int RegIndex);
int JLINKARM_ReadMem (U32 addr, U32 count, void * p);
void JLINKARM_ReadMemU8 (U32 Addr, U32 NumItems, U8 * pData, U8* pStatus);
void JLINKARM_ReadMemU16(U32 Addr, U32 NumItems, U16* pData, U8* pStatus);
void JLINKARM_ReadMemU32(U32 Addr, U32 NumItems, U32* pData, U8* pStatus);
U32 JLINKARM_ReadReg (ARM_REG RegIndex);
void JLINKARM_Reset(void);
void JLINKARM_ResetPullsTRST (U8 OnOff);
void JLINKARM_ResetPullsRESET(U8 OnOff);
void JLINKARM_SelDevice(U16 DeviceIndex);
void JLINKARM_SetBP(unsigned BPIndex, U32 Addr);
int JLINKARM_SetEndian(int v);
int JLINKARM_SetInitRegsOnReset(int v);
void JLINKARM_SetMaxSpeed(void);
void JLINKARM_SetResetDelay(int ms);
int JLINKARM_SetResetPara(int Value);
void JLINKARM_SetSpeed(int Speed);
char JLINKARM_Step(void);
int JLINKARM_Test(void);
U16 JLINKARM_UpdateFirmware(void);
U32 JLINKARM_UpdateFirmwareIfNewer(void);
int JLINKARM_WaitDCCRead(int TimeOut);
int JLINKARM_WriteDCC(const U32 * pData, U32 NumItems, int TimeOut);
void JLINKARM_WriteDCCFast(const U32 * pData, U32 NumItems);
void JLINKARM_WriteICEReg(int RegIndex, U32 Value, int AllowDelay);
char JLINKARM_WriteReg(ARM_REG RegIndex, U32 Data);
void JLINKARM_WriteMem(U32 addr, U32 count, const void * p);
void JLINKARM_WriteMemDelayed(U32 Addr, U32 Count, const void * p);
void JLINKARM_WriteU8 (U32 addr, U8 Data);
void JLINKARM_WriteU16(U32 addr, U16 Data);
void JLINKARM_WriteU32(U32 addr, U32 Data);
void JLINKARM_EnableLogCom(void (*DebugFunc)(const char *));
C#接口如下:
/// <summary>
/// 打开JLINK设备
/// </summary>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_Open();
/// <summary>
/// 关闭JLINK设备
/// </summary>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_Close();
/// <summary>
/// 连接设备
/// </summary>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_Connect();
/// <summary>
/// 开启RTT
/// </summary>
/// <param name="terminal"></param>
/// <param name="size"></param>
[DllImport("JLinkARM.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINK_RTTERMINAL_Control(UInt32 CMD, UInt32 size);
/// <summary>
/// 从RTT回读数据
/// </summary>
/// <param name="terminal"></param>
/// <param name="rxBuffer"></param>
/// <param name="len"></param>
[DllImport("JLinkARM.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern void JLINK_RTTERMINAL_Read(int terminal, [Out(), MarshalAs(UnmanagedType.LPArray)] byte[] rxBuffer, UInt32 size);
static string gbk_ansi(string str)
{
string keyword;
byte[] buffer = Encoding.GetEncoding("GB2312").GetBytes(str);
keyword = Encoding.UTF8.GetString(buffer);
return keyword;
}
public static string JLINKARM_ReadRTT_String()
{
try
{
byte[] aa = new byte[1000];
JLINK_RTTERMINAL_Read(0, aa,1000);
ASCIIEncoding kk = new ASCIIEncoding();
//使用UTF-8编码
UTF8Encoding uu = new UTF8Encoding();
string ss = uu.GetString(aa);
if(ss.Length>1)
{
Console.Write(ss);
}
return ss;
}
catch(Exception ex)
{
}
return String.Empty;
}
/// <summary>
/// 写数据到RTT
/// </summary>
/// <param name="terminal"></param>
/// <param name="txBuffer"></param>
/// <param name="len"></param>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINK_RTTERMINAL_Write(int terminal, [In(), MarshalAs(UnmanagedType.LPArray)] byte[] txBuffer, UInt32 size);
/// <summary>
/// 系统复位
/// </summary>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_Reset();
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_GoAllowSim();
/// <summary>
/// 执行程序
/// </summary>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_Go();
/// <summary>
/// 中断程序执行
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern bool JLINKARM_Halt();
/// <summary>
/// 单步执行
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern bool JLINKARM_Step();
/// <summary>
/// 清除错误信息
/// </summary>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ClrError();
/// <summary>
/// 设置JLINK接口速度
/// </summary>
/// <param name="speed"></param>
/// <remarks>0为自动调整</remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_SetSpeed(int speed);
/// <summary>
/// 设置JTAG为最高速度
/// </summary>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_SetMaxSpeed()
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt16 JLINKARM_GetSpeed()
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_GetVoltage()
;
/// <summary>
/// 当前MCU是否处于停止状态
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern bool JLINKARM_IsHalted()
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern bool JLINKARM_IsConnected()
;
/// <summary>
/// JLINK是否已经可以操作了
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern bool JLINKARM_IsOpen()
;
/// <summary>
/// 取消程序断点
/// </summary>
/// <param name="index">断点序号</param>
/// <remarks>配合JLINKARM_SetBP()使用</remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ClrBP(UInt32 index)
;
/// <summary>
/// 设置程序断点
/// </summary>
/// <param name="index">断点序号</param>
/// <param name="addr">目标地址</param>
/// <remarks>建议使用JLINKARM_SetBPEx()替代</remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_SetBP(UInt32 index, UInt32 addr)
;
/// <summary>
/// 设置程序断点
/// </summary>
/// <param name="addr">目标地址</param>
/// <param name="mode">断点类型</param>
/// <returns>Handle,提供给JLINKARM_ClrBPEx()使用</returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int JLINKARM_SetBPEx(UInt32 addr, BP_MODE mode)
;
/// <summary>
/// 取消程序断点
/// </summary>
/// <param name="handle"></param>
/// <remarks>配合JLINKARM_SetBPEx()使用</remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ClrBPEx(int handle)
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int JLINKARM_SetWP(UInt32 addr, UInt32 addrmark, UInt32 dat, UInt32 datmark, byte ctrl, byte ctrlmark)
;
/// <summary>
/// 取消数据断点
/// </summary>
/// <param name="handle"></param>
/// <remarks>配合JLINKARM_SetWP()使用</remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ClrWP(int handle)
;
/// <summary>
/// 设置寄存器
/// </summary>
/// <param name="index"></param>
/// <param name="dat"></param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_WriteReg(ARM_REG index, UInt32 dat)
;
/// <summary>
/// 读取寄存器
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_ReadReg(ARM_REG index)
;
/// <summary>
/// 写入一段数据
/// </summary>
/// <param name="addr"></param>
/// <param name="size"></param>
/// <param name="buf"></param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_WriteMem(UInt32 addr, UInt32 size, byte[] buf)
;
/// <summary>
/// 读取一段数据
/// </summary>
/// <param name="addr"></param>
/// <param name="size"></param>
/// <param name="buf"></param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ReadMem(UInt32 addr, UInt32 size, [Out(), MarshalAs(UnmanagedType.LPArray)] byte[] buf)
;
/// <summary>
/// 从调试通道获取一串数据
/// </summary>
/// <param name="buf"></param>
/// <param name="size">需要获取的数据长度</param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ReadDCCFast([Out(), MarshalAs(UnmanagedType.LPArray)] UInt32[] buf, UInt32 size)
;
/// <summary>
/// 从调试通道获取一串数据
/// </summary>
/// <param name="buf"></param>
/// <param name="size">希望获取的数据长度</param>
/// <param name="timeout"></param>
/// <returns>实际获取的数据长度</returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_ReadDCC([Out(), MarshalAs(UnmanagedType.LPArray)] UInt32[] buf, UInt32 size, int timeout)
;
/// <summary>
/// 向调试通道写入一串数据
/// </summary>
/// <param name="buf"></param>
/// <param name="size">需要写入的数据长度</param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_WriteDCCFast(UInt32[] buf, UInt32 size)
;
/// <summary>
/// 向调试通道写入一串数据
/// </summary>
/// <param name="buf"></param>
/// <param name="size">希望写入的数据长度</param>
/// <param name="timeout"></param>
/// <returns>实际写入的数据长度</returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_WriteDCC(UInt32[] buf, UInt32 size, int timeout)
;
/// <summary>
/// 获取JLINK的DLL版本号
/// </summary>
/// <returns></returns>
/// <remarks>使用10进制数表示</remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_GetDLLVersion()
;
/// <summary>
/// 执行命令
/// </summary>
/// <param name="oBuffer"></param>
/// <param name="a"></param>
/// <param name="b"></param>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_ExecCommand([In(), MarshalAs(UnmanagedType.LPArray)] byte[] oBuffer,int a,int b);
/// <summary>
/// 选择接口,0是JTAG 1是SWD
/// </summary>
/// <param name="type"></param>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_TIF_Select(int type);
/// <summary>
/// 获取JLINK的固件版本号
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_GetHardwareVersion()
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern void JLINKARM_GetFeatureString([Out(), MarshalAs(UnmanagedType.LPArray)] byte[] oBuffer)
;
[DllImport("JLinkARM.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern void JLINKARM_GetOEMString([Out(), MarshalAs(UnmanagedType.LPArray)] byte[] oBuffer)
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_SetLogFile([In(), MarshalAs(UnmanagedType.LPArray)] byte[] oBuffer)
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern StringBuilder JLINKARM_GetCompileDateTime()
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_GetSN()
;
/// <summary>
/// 获取当前MCU的ID号
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern UInt32 JLINKARM_GetId()
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern void JLINKARM_ReadMemU32(UInt32 addr, UInt32 leng, ref UInt32 buf, ref byte status)
;
/// <summary>
/// 写入32位的数据
/// </summary>
/// <param name="addr"></param>
/// <param name="dat"></param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_WriteU32(UInt32 addr, UInt32 dat)
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern void JLINKARM_ReadMemU16(UInt32 addr, UInt32 leng, ref UInt16 buf, ref byte status)
;
/// <summary>
/// 写入16位的数据
/// </summary>
/// <param name="addr"></param>
/// <param name="dat"></param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_WriteU16(UInt32 addr, UInt16 dat)
;
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern void JLINKARM_ReadMemU8(UInt32 addr, UInt32 leng, ref byte buf, ref byte status)
;
/// <summary>
/// 写入8位的数据
/// </summary>
/// <param name="addr"></param>
/// <param name="dat"></param>
/// <remarks></remarks>
[DllImport("JLinkARM.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void JLINKARM_WriteU8(UInt32 addr, byte dat)
;
有了这个接口便可以调用连接jlink了,例如:
Console.WriteLine("Jlink操作演示");
JLinkHandler.JLINKARM_SetLogFile(System.Text.Encoding.UTF8.GetBytes("this_log.txt"));
JLinkHandler.JLINKARM_Open();
var ver = JLinkHandler.JLINKARM_GetDLLVersion();
Console.WriteLine("DLL 版本: "+ver);
Console.WriteLine("SN:" + JLinkHandler.JLINKARM_GetSN());
Console.WriteLine("硬件版本: " + JLinkHandler.JLINKARM_GetHardwareVersion());
JLinkHandler.JLINKARM_ExecCommand(System.Text.Encoding.UTF8.GetBytes("device = STM32H743VI"), 0, 0);
JLinkHandler.JLINKARM_TIF_Select(1);
JLinkHandler.JLINKARM_SetSpeed(4000);
Console.WriteLine("CPU ID: "+JLinkHandler.JLINKARM_GetId());
可惜的是,并没有直接下载hex文件的接口,这就需要先了解hex文件的结构,进行进一步解析,再调用接口写到对应的地址下。这里有参考文章:
STM32的烧录和Hex/bin烧录文件解析、烧录文件是被如何存储到MCU中的?_stm32 bin文件解析-CSDN博客文章来源:https://www.toymoban.com/news/detail-848068.html
hex文件内含有地址和数据,软件解析地址并烧录数据,烧录完毕之后,调用:JLINKARM_Go();,程序成功执行,搞了好几天终于成功了,记录一下。文章来源地址https://www.toymoban.com/news/detail-848068.html
到了这里,关于自己开发jlink烧录软件,烧录上位机, C#调用JLinkARM.dll实现软件烧录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!