JLink未开放软件开发接口(SDK),无法进行二次开发,但通过一些大佬的发现,JLink在烧录时,实际上都是通过调用JLinkARM.dll动态库提供的接口来进行操作的。这样我们就可以对其进行二次开发,该库有两个版本,一个32位,一个64位,具体位置如下图所示:
该工程实例代码已给出,需要的自行下载:https://download.csdn.net/download/carrymen/88463100
以下是库中导出函数的原型的一部分,基本够用了:
//JLINK TIF
#define JLINKARM_TIF_JTAG 0
#define JLINKARM_TIF_SWD 1
#define JLINKARM_TIF_DBM3 2
#define JLINKARM_TIF_FINE 3
#define JLINKARM_TIF_2wire_JTAG_PIC32 4
//RESET TYPE
#define JLINKARM_RESET_TYPE_NORMAL 0
#define JLINKARM_RESET_TYPE_CORE 1
#define JLINKARM_RESET_TYPE_PIN 2
//REGISTER INDEX
/*
0 - 15 R0 - R15(SP=R13, PC=R15)
16 XPSR
17 MSP
18 PSP
19 RAZ
20 CFBP
21 APSR
22 EPSR
23 IPSR
24 PRIMASK
25 BASEPRI
26 FAULTMASK
27 CONTROL
28 BASEPRI_MAX
29 IAPSR
30 EAPSR
31 IEPSR
*/
typedef BOOL (*JLINKARM_Open_Func_Ptr)(void); // 定义导出函数类型
typedef void (*JLINKARM_Close_Func_Ptr)(void);
typedef DWORD (*JLINKARM_TIF_Select_Func_Ptr)(int);
typedef void (*JLINKARM_SetSpeed_Func_Ptr)(int);
typedef void (*JLINKARM_Reset_Func_Ptr)(void);
typedef void (*JLINKARM_Go_Func_Ptr)(void);
typedef BOOL (*JLINKARM_IsOpen_Func_Ptr)(void);
typedef void (*JLINKARM_SetLogFile_Func_Ptr)(char *file);
typedef DWORD (*JLINKARM_GetDLLVersion_Func_Ptr)(void);
typedef DWORD (*JLINKARM_GetHardwareVersion_Func_Ptr)(void);
typedef DWORD (*JLINKARM_GetFirmwareString_Func_Ptr)(char *buff, int count);
typedef DWORD (*JLINKARM_GetSN_Func_Ptr)(void);
typedef BOOL (*JLINKARM_ExecCommand_Func_Ptr)(char* cmd, int a, int b);
typedef DWORD (*JLINKARM_TIF_Select_Func_Ptr)(int type);
typedef void (*JLINKARM_SetSpeed_Func_Ptr)(int speed);
typedef DWORD (*JLINKARM_GetSpeed_Func_Ptr)(void);
typedef DWORD (*JLINKARM_GetId_Func_Ptr)(void);
typedef DWORD (*JLINKARM_GetDeviceFamily_Func_Ptr)(void);
typedef BOOL (*JLINKARM_Open_Func_Ptr)(void);
typedef void (*JLINKARM_Close_Func_Ptr)(void);
typedef BOOL (*JLINKARM_IsOpen_Func_Ptr)(void);
typedef BOOL (*JLINKARM_Connect_Func_Ptr)(void);
typedef BOOL (*JLINKARM_IsConnected_Func_Ptr)(void);
typedef int (*JLINKARM_Halt_Func_Ptr)(void);
typedef BOOL (*JLINKARM_IsHalted_Func_Ptr)(void);
typedef void (*JLINKARM_SetResetType_Func_Ptr)(int type);
typedef void (*JLINKARM_Reset_Func_Ptr)(void);
typedef void (*JLINKARM_Go_Func_Ptr)(void);
typedef void (*JLINKARM_GoIntDis_Func_Ptr)(void);
typedef DWORD (*JLINKARM_ReadReg_Func_Ptr)(int index);
typedef int (*JLINKARM_WriteReg_Func_Ptr)(int index, DWORD data);
typedef int (*JLINKARM_ReadMem_Func_Ptr)(DWORD addr, int len, void *buf);
typedef int (*JLINKARM_WriteMem_Func_Ptr)(DWORD addr, int len, void *buf);
typedef int (*JLINKARM_WriteU8_Func_Ptr)(DWORD addr, BYTE data);
typedef int (*JLINKARM_WriteU16_Func_Ptr)(DWORD addr, WORD data);
typedef int (*JLINKARM_WriteU32_Func_Ptr)(DWORD addr, DWORD data);
typedef int (*JLINK_EraseChip_Func_Ptr)(void);
typedef int (*JLINKARM_DownloadFile_Func_Ptr)(LPCSTR file, DWORD addr);
typedef void (*JLINKARM_BeginDownload_Func_Ptr)(int index);
typedef void (*JLINKARM_EndDownload_Func_Ptr)(void);
qt通过resolve对动态库进行解析获取对应函数指针:
jlink_lib= new QLibrary("JLink_x64.dll");
if(jlink_lib->load()){
qDebug()<<"加载JLink_x64.dll成功, 开始解析函数";
JLINKARM_Open_Entry = (JLINKARM_Open_Func_Ptr)jlink_lib->resolve("JLINKARM_Open");
JLINKARM_IsOpen_Entry = (JLINKARM_IsOpen_Func_Ptr)jlink_lib->resolve("JLINKARM_IsOpen");
JLINKARM_Close_Entry = (JLINKARM_Close_Func_Ptr)jlink_lib->resolve("JLINKARM_Close");
JLINKARM_ExecCommand_Entry = (JLINKARM_ExecCommand_Func_Ptr)jlink_lib->resolve("JLINKARM_ExecCommand");
JLINKARM_GetDLLVersion_Entry = (JLINKARM_GetDLLVersion_Func_Ptr)jlink_lib->resolve("JLINKARM_GetDLLVersion");
JLINKARM_TIF_Select_Entry = (JLINKARM_TIF_Select_Func_Ptr)jlink_lib->resolve("JLINKARM_TIF_Select");
JLINKARM_SetSpeed_Entry = (JLINKARM_SetSpeed_Func_Ptr)jlink_lib->resolve("JLINKARM_SetSpeed");
JLINKARM_GetSpeed_Entry = (JLINKARM_GetSpeed_Func_Ptr)jlink_lib->resolve("JLINKARM_GetSpeed");
JLINKARM_Connect_Entry = (JLINKARM_Connect_Func_Ptr)jlink_lib->resolve("JLINKARM_Connect");
JLINKARM_IsConnected_Entry = (JLINKARM_IsConnected_Func_Ptr)jlink_lib->resolve("JLINKARM_IsConnected");
JLINKARM_GetId_Entry = (JLINKARM_GetId_Func_Ptr)jlink_lib->resolve("JLINKARM_GetId");
JLINKARM_GetSN_Entry = (JLINKARM_GetSN_Func_Ptr)jlink_lib->resolve("JLINKARM_GetSN");
JLINKARM_Reset_Entry = (JLINKARM_Reset_Func_Ptr)jlink_lib->resolve("JLINKARM_Reset");
JLINKARM_Halt_Entry = (JLINKARM_Halt_Func_Ptr)jlink_lib->resolve("JLINKARM_Halt");
JLINKARM_WriteMem_Entry = (JLINKARM_WriteMem_Func_Ptr)jlink_lib->resolve("JLINKARM_WriteMem");
JLINKARM_ReadMem_Entry = (JLINKARM_ReadMem_Func_Ptr)jlink_lib->resolve("JLINKARM_ReadMem");
JLINK_EraseChip_Entry = (JLINK_EraseChip_Func_Ptr)jlink_lib->resolve("JLINK_EraseChip");
qDebug()<<"解析函数完成";
}
else
{
qDebug()<<"加载JLink_x64.dll失败!!";
}
例程运行后可能会遇到库的路径找不到,而导致无法解析该库,有两种可能:一种是路径没找到,还有就是动态库的位数和qt编译工具位数对不上,他有一个32位库一个64位库,自行选择。而路径问题的话只需要将库放进编译后的工程中即可,也可以修改库路径。
运行成功后会打印一下信息:
qt工程运行成功界面如下图所示:
如果需要适配不同STM32型号芯片的烧录需要对工程进行几个位置的修改:
①:修改芯片型号和下载模式,还有下载速率
②:修改ID读取地址,根据型号来定,一下给出了STM32和GD32的UID存放地址,参照修改:
做以上修改就可以了,我使用了STM32F429IG和STM32F103ZET6两块型号不同的芯片做了测试,结果是都能进行烧录,也可以更改成GD32型号,具体就没测试了,大家可以自己试一下。