当前位置: 首页 > news >正文

Qt--通过JLinkARM.dll实现Jlink自动烧写

一、调用的动态库

在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          XPSR17          MSP18          PSP19          RAZ20          CFBP21          APSR22          EPSR23          IPSR24          PRIMASK25          BASEPRI26          FAULTMASK27          CONTROL28          BASEPRI_MAX29          IAPSR30          EAPSR31          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 5QTimer *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;
}

参考文章:

QT写J-link上位机实现烧录功能

JLinkARM.dll部分导出函数定义

自制J-Flash烧录工具——Qt调用jlinkARM.dll方式

http://www.dtcms.com/a/613772.html

相关文章:

  • gitlab cicd 模块解释
  • 如何实现带历史记录功能的控制台2048游戏
  • gitlab cicd首次操作
  • 建设学院网站意义比价 wordpress 插件下载
  • 电子毕业设计代做网站上海雷蒙威手表网站
  • LangChain Memory
  • 【ZeroRange WebRTC】NACK(Negative Acknowledgment)技术深度分析
  • 物联网架构
  • 网站推广公司兴田德润在哪儿wordpress 手机支付
  • 如何在 VSCode 中创建 Vue 项目
  • 【ZeroRange WebRTC】PLI(Picture Loss Indication)技术深度分析
  • 神马影视 8.8 源码 2025 版,HDR + 杜比音效 + 零卡顿
  • MFC编程实战:全面掌握Combo Box(组合框)控件的高级应用
  • 归并排序 (BM20 数组中的逆序对)
  • Spring @Around 注解
  • 建设企业网站需要考虑的因素有哪些店铺logo设计免费
  • 50019_基于微信小程序的校园互助系统
  • (120页PPT)ChatGPT与数字化转型的业财融合(附下载方式)
  • Java面试中等测试题
  • 爱站库全栈网站开发工程师
  • docker避免每次sudo方法
  • 计算机图形学·15 计算机视图(Computer Viewing)
  • 使用rufus制作系统盘及Ubantu24.04.3LTS镜像文件下载
  • opencart做视频网站做网站盈利方式
  • Polar MISC(下)
  • DNS基础介绍
  • Spring Boot 3.4 正式发布,结构化日志!
  • Docker安装和使用kkfileview
  • 做超市dm的网站淘宝联盟网站建设不完整
  • 手机终端传输模式深入介绍