一、调用的动态库
在Jlink的安装目录下包含 JLinkARM.dll 动态库,将其拷贝到工程中。
并将 JLinkDevices.xml 与 Devices 文件夹 拷贝到工程运行文件夹,Jlink需要调用识别芯片设备。

二、库函数原型
添加库对应函数原型的头文件,“函数名_Func_Ptr”。
//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 BOOL (*JLINKARM_IsOpen_Func_Ptr)(void); //是否打开
typedef BOOL (*JLINKARM_Connect_Func_Ptr)(void); //连接
typedef BOOL (*JLINKARM_IsConnected_Func_Ptr)(void); //是否连接
typedef void (*JLINKARM_Reset_Func_Ptr)(void); //复位系统
typedef void (*JLINKARM_Go_Func_Ptr)(void); //制行程序
typedef void (*JLINKARM_SetSpeed_Func_Ptr)(int); //设置接口速度
typedef int (*JLINKARM_Halt_Func_Ptr)(void); //中断程序,进入停止状态
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 (*JLINK_EraseChip_Func_Ptr)(void);
typedef int (*JLINK_HSS_Stop_Func_Ptr)(void);
typedef DWORD (*JLINKARM_TIF_Select_Func_Ptr)(int);
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_IsHalted_Func_Ptr)(void);
typedef void (*JLINKARM_SetResetType_Func_Ptr)(int type);
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_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 (*JLINKARM_DownloadFile_Func_Ptr)(LPCSTR file, DWORD addr);
typedef void (*JLINKARM_BeginDownload_Func_Ptr)(int index);
typedef void (*JLINKARM_EndDownload_Func_Ptr)(void);
三、动态库的调用
.h
#include <QLibrary>
//建立一个动态库
QLibrary *jlink_lib;
//根据动态库的头文件函数列表进行映射
JLINKARM_Open_Func_Ptr JLINKARM_Open_Entry = NULL;
JLINKARM_IsOpen_Func_Ptr JLINKARM_IsOpen_Entry = NULL;
//...
//新建调用函数,为了方便直接与库函数同名
bool JLINKARM_Open();
bool JLINKARM_IsOpen();
.cpp
//进行动态库函数解析
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");
//...
qDebug()<<"解析函数完成";
}
else
{
qDebug()<<"加载JLink_x64.dll失败!!";
}
//调用函数--根据函数原型进行调用函数的建立
bool JLINKARM_Open()
{
if(JLINKARM_Open_Entry)
{
return JLINKARM_Open_Entry();
}
return false;
}
//...
四、具体操作的实现
4.1 Connect 连接设备
//传入参数:芯片名称例如:STM32F429IG
bool OpenDevice(QString device)
{
if(JLINKARM_IsOpen())
{
qDebug()<<"JLINKARM was Opened!";
return true;
}
JLINKARM_Open();
if(JLINKARM_IsOpen())
{
qDebug()<<"JLINKARM open success!";
QString Str = "device = " + device;
QByteArray ba = Str.toLatin1();
char *strInc = ba.data();
JLINKARM_ExecCommand(strInc,NULL,0);
JLINKARM_TIF_Select(JLINKARM_TIF_SWD);
JLINKARM_SetSpeed(4000);
JLINKARM_Connect();
if(JLINKARM_IsConnected())
{
if(JLINKARM_IsHalted() == 0)
{
JLINKARM_Halt();
}
qDebug()<<"JlinkARM is connected!";
return true;
}
else
{
qDebug()<<"JlinkARM connect failed!";
}
}
else
{
qDebug()<<"JlinkARM open failed!";
}
return false;
}
4.2 Disconnect 断开连接
bool DisconnectDevice()
{
JLINKARM_Close();
if(!JLINKARM_IsOpen())
{
qDebug()<<"JLINKARM Close success !";
return true;
}
else
{
qDebug()<<"JLINKARM Close fail !";
}
return false;
}
4.3 Erase擦除芯片
bool EraseChip()
{
if(!JLINKARM_IsOpen())
{
return false;
}
int rHSS_Stop = JLINK_HSS_Stop();
qDebug()<<QString("JLINK_HSS_Stop: %1 ").arg(rHSS_Stop);
int rEraseChip = JLINK_EraseChip();
qDebug()<<QString("EraseChip: %1 ").arg(rEraseChip);
if(rEraseChip == 0)
{
qDebug()<<"JLINK EraseChip success!";
return true;
}
DisconnectDevice();
qDebug()<<"JLINK EraseChip failed !";
return false;
}
4.4 Production Programming 烧录文件
#define BURN_STEP_SIZE 1024
#define BURN_DELAY 5
QTimer *timer_burn;
int GetFlashPos; //Flash烧写递增地址
QByteArray burn_bin_data; //烧写bin的文件缓冲区
connect(timer_burn, SIGNAL(timeout()),this, SLOT(on_timer_burn_timeout()));
//传参为烧写的起始地址与bin文件的文件路径,只支持bin文件烧录
bool FileBurnBegin(int FlashPos, QString FlashBinFile)
{
GetFlashPos = FlashPos;
burn_bin_data.clear();
if(FlashBinFile.right(3) != "bin")
{
return false;
}
QFile burn_file;
burn_file.setFileName(FlashBinFile);
burn_file.open(QIODevice::ReadOnly); //打开文件
if(burn_file.isOpen())
{
burn_bin_data = burn_file.readAll(); //将要烧录的数据读取到内存中
burn_file.close(); //关闭文件
if(burn_bin_data.size() > 1024*1024)
{
qDebug()<<"文件大小不允许超过1MB!";
burn_bin_data.clear();
DisconnectDevice();
return;
}
qDebug()<<"开始烧录固件, 请稍后...";
timer_burn->start(BURN_DELAY);
}
else
{
qDebug()<<"打开固件失败, 请检查文件是否存在!";
DisconnectDevice();
return false;
}
}
void on_timer_burn_timeout()
{
if(timer_burn->isActive())
{
timer_burn->stop();
if(burn_bin_data.isEmpty()) //烧录完成
{
DisconnectDevice();
return;
}
else //烧录的数据非空
{
if(burn_bin_data.size() > BURN_STEP_SIZE) //大小超过1K
{
int ret = JLINKARM_WriteMem(GetFlashPos,
BURN_STEP_SIZE,
burn_bin_data.data());
GetFlashPos += BURN_STEP_SIZE;
burn_bin_data.remove(0, BURN_STEP_SIZE);
}
else //大小不到1K
{
int ret = JLINKARM_WriteMem(GetFlashPos,
burn_bin_data.size(),
burn_bin_data.data());
GetFlashPos += burn_bin_data.size();
burn_bin_data.clear();
}
timer_burn->start(BURN_DELAY);
}
}
}
4.5 Start Application 运行程序
JLINKARM_Reset();
OpenDevice();
JLINKARM_Go();
4.6 Verify 校验
//传参为 起始地址,大小与比较的bin文件内容
bool VerifyFlashContent(uint32_t startAddr, uint32_t size, const uint8_t* expectedData)
{
uint8_t* flashData = (uint8_t*)malloc(size);
if (!flashData)
{
qDebug()<<"内存分配失败...";
return false;
}
if (JLINKARM_ReadMem(startAddr, size, flashData) != 0)
{
qDebug()<<"读取Flash失败...";
free(flashData);
return false;
}
bool match = true;
for (uint32_t i = 0; i < size; i++)
{
if (flashData[i] != expectedData[i]) {
qDebug() << QString("数据不匹配在地址 0x%1: Flash=0x%2, 期望=0x%3")
.arg(startAddr + i, 8, 16, QLatin1Char('0'))
.arg(flashData[i], 2, 16, QLatin1Char('0'))
.arg(expectedData[i], 2, 16, QLatin1Char('0'));
match = false;
break;
}
}
free(flashData);
if (match)
{
qDebug() << "Flash验证成功!所有数据匹配。";
}
else
{
qDebug() << "Flash验证失败!发现数据不匹配。";
}
return match;
}
参考文章:
8277

被折叠的 条评论
为什么被折叠?



