VC Windows上位机实现J-Link RTT Viewer功能

发布时间 2023-11-09 14:17:32作者: ckrgd

1.J-Link 工具下载

Software Development Tools by SEGGER – The Embedded Experts

下载这个

 安装好后,打开JLinkRTTViewer.exe,按照嵌入式工程师给的连接方法,测试指令

 2.调用JLinkARM.dll中的函数来写对应代码

参考:【Jlink & C#】通过C#实现Jlink RTT上位机的功能-CSDN博客

JLinkARM.dll和JLinkRTTViewer.exe在同一个文件夹,直接拿来用

JLinkARM.dll部分导出函数定义-CSDN博客

静态调用,直接上代码

//JLinkARM.dll  要用的函数加载

//JLINK TIF
#define JLINKARM_TIF_JTAG    0
#define JLINKARM_TIF_SWD    1

const UINT32 LINKARM_RTTERMINAL_CMD_START = 0;
const UINT32 JLINKARM_RTTERMINAL_CMD_STOP = 1;
const UINT32 JLINKARM_RTTERMINAL_CMD_GETDESC = 2;
const UINT32 LINKARM_RTTERMINAL_CMD_GETNUMBUF = 3;

typedef char*(*JLINKARM_Open_Func)(void);
typedef char(*JLINKARM_IsOpen_Func)(void);
typedef void(*JLINKARM_Close_Func)(void);
typedef int(*JLINKARM_ExecCommand_Func)(const char* sIn, char* sError, int BufferSize);
typedef int(*JLINKARM_TIF_Select_Func)(int);
typedef void(*JLINKARM_SetSpeed_Func)(UINT32);
typedef int(*JLINKARM_Connect_Func)(void);
typedef BOOL(*JLINKARM_IsConnected_Func)(void);
typedef void(*JLINKARM_SetLogFile_Func)(const char* sFilename);

typedef int(WINAPI*JLINK_RTTERMINAL_Read_Func_Ptr)(UINT32 BufferIndex, char* sBuffer, UINT32 BufferSize);
typedef int(WINAPI*JLINK_RTTERMINAL_Write_Func_Ptr)(UINT32 BufferIndex, const char* sBuffer, UINT32 BufferSize);
typedef int(WINAPI*JLINK_RTTERMINAL_Control_Func_Ptr)(UINT32 Cmd, void* p);

JLINKARM_Open_Func JLINKARMOpen = NULL;               //打开设备
JLINKARM_IsOpen_Func JLINKARMIsOpen = NULL;           //是否已经打开
JLINKARM_Close_Func JLINKARMClose = NULL;             //关闭设备
JLINKARM_ExecCommand_Func JLINKARMExecCommand = NULL; //连接设备参数
JLINKARM_TIF_Select_Func JLINKARMTIFSelect = NULL;    //选择设备
JLINKARM_SetSpeed_Func JLINKARMSetSpeed = NULL;       //设置JLINK接口速度 0为自动调整
JLINKARM_Connect_Func JLINKARMConnect = NULL;
JLINKARM_IsConnected_Func JLINKARMIsConnected = NULL;
JLINKARM_SetLogFile_Func JLINKARMSetLogFile = NULL;

JLINK_RTTERMINAL_Read_Func_Ptr JLINKRTTErminalRead = NULL;
JLINK_RTTERMINAL_Write_Func_Ptr JLINKRTTErminalWrite = NULL;
JLINK_RTTERMINAL_Control_Func_Ptr JLINKRTTErminalControl = NULL;

//加载JLinkARM.dll函数
void LoadJLinkARMLibrary()
{
    HMODULE    hModule;
    hModule = LoadLibrary(_T("JLinkARM.dll"));

    JLINKARMOpen = (JLINKARM_Open_Func)GetProcAddress(hModule, "JLINKARM_Open");
    JLINKARMIsOpen = (JLINKARM_IsOpen_Func)GetProcAddress(hModule, "JLINKARM_IsOpen");
    JLINKARMClose = (JLINKARM_Close_Func)GetProcAddress(hModule, "JLINKARM_Close");
    JLINKARMExecCommand = (JLINKARM_ExecCommand_Func)GetProcAddress(hModule, "JLINKARM_ExecCommand");
    JLINKARMTIFSelect = (JLINKARM_TIF_Select_Func)GetProcAddress(hModule, "JLINKARM_TIF_Select");
    JLINKARMSetSpeed = (JLINKARM_SetSpeed_Func)GetProcAddress(hModule, "JLINKARM_SetSpeed");
    JLINKARMConnect = (JLINKARM_Connect_Func)GetProcAddress(hModule, "JLINKARM_Connect");
    JLINKARMIsConnected = (JLINKARM_IsConnected_Func)GetProcAddress(hModule, "JLINKARM_IsConnected");
    JLINKARMSetLogFile = (JLINKARM_SetLogFile_Func)GetProcAddress(hModule, "JLINKARM_SetLogFile");


    JLINKRTTErminalRead = (JLINK_RTTERMINAL_Read_Func_Ptr)GetProcAddress(hModule, "JLINK_RTTERMINAL_Read");
    JLINKRTTErminalWrite = (JLINK_RTTERMINAL_Write_Func_Ptr)GetProcAddress(hModule, "JLINK_RTTERMINAL_Write");
    JLINKRTTErminalControl = (JLINK_RTTERMINAL_Control_Func_Ptr)GetProcAddress(hModule, "JLINK_RTTERMINAL_Control");
}
//打开jlink设备并连接芯片,并执行读前需要的特殊函数
BOOL JLinkConnectDevice(CString &strError)
{
    char cIsopen = JLINKARMIsOpen();
    if (cIsopen == 1)
    {
        return TRUE;
    }
    char* cpOpenRet;
    cpOpenRet = JLINKARMOpen();
    if (cpOpenRet == NULL)
    {//成功
        char cError[128];
        JLINKARMExecCommand("device = GD32F407VE", cError, 128);//第一个参数是由硬件工程师指定的
        if (cError[0] == 0)
        {//成功
            JLINKARMTIFSelect(JLINKARM_TIF_SWD);
            JLINKARMSetSpeed(4000); //设置下载速度
            int iConnectret = JLINKARMConnect();
            if (iConnectret)
            {
                strError = "JLINKARMConnect 失败";
                return FALSE;
            }
            else
            {
                JLINKARMSetLogFile("JLinkLog.log");
                //读结果前要执行特殊函数?????
                JLINKRTTErminalControl(LINKARM_RTTERMINAL_CMD_START, 0);
                return TRUE;
            }
        }
        else
        {
            strError = cpOpenRet;
            strError += ",JLINKARMExecCommand 失败";
            return FALSE;
        }

        return TRUE;
    }
    else
    {
        strError = cpOpenRet;
        strError += ",JLINKARMOpen 失败";
        return FALSE;
    }
}



//指令编号   指令字符串,  返回结果, 错误信息
BOOL JLinkExecuteEnter(int iCmdCode, CString strCmd, CString &strRet, CString &strError)
{
    CLog mLog;

    //param_set+product_key=ue6g80ksaodivatn  1   param_set+product_key success
    //param_read+product_key  2    param_read+product_key=ue6g80ksaodivat
    //param_set+device_uuid=uuid2893ffc9b6fd3c9b  3   param_set+device_uuid success
    //param_read+device_uuid  4    param_read+device_uuid=uuid2893ffc9b6fd3c9b
    //param_set+device_authkey=pd3tnj3lLZT2azTIj2yuuSy6alSJMzKF  5     param_set+device_authkey success
    //param_read+device_authkey  6    param_read+device_authkey=pd3tnj3lLZT2azTIj2yuuSy6alSJMzKF
//先发指令
    char cWrite[128] = { 0 };
    sprintf(cWrite, strCmd);
    int len = strlen(cWrite);
    mLog.WriteLog("发送指令:%s", strCmd);
    int ret = JLINKRTTErminalWrite(0, cWrite, len + 1);
    if (ret < 0)
    {
        strError = "JLINKRTTErminalWrite 失败";
        return FALSE;
    }
    //这个时间决定读到返回值的概率
    Sleep(100);

    char cRead[512] = { 0 };
    CString strRead;
    ret = JLINKRTTErminalRead(0, cRead, 512);
    if (ret > 0)
    {
        strRead = cRead;
        mLog.WriteLog("收到返回:%s", strRead);
    }
    else
    {
        strError = "JLINKRTTErminalRead 未读到结果";
        return FALSE;
    }
}
//执行完指令后关闭
JLINKRTTErminalControl(JLINKARM_RTTERMINAL_CMD_STOP, 0);
JLINKARMClose();