From ba95366f61de343e71915e8beb1edbf00bbf68c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=B0=E5=8D=9A=E6=96=87?= Date: Tue, 27 Sep 2022 15:55:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 173 +++++++++++++++++++++++++-------- imgs/process-block-diagram.png | Bin 0 -> 38831 bytes lower/log/README.md | 16 ++- lower/serial/README.md | 26 +++-- 4 files changed, 162 insertions(+), 53 deletions(-) create mode 100644 imgs/process-block-diagram.png diff --git a/README.md b/README.md index 64d2af0..cc134f9 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,37 @@ ## 项目简介 -本程序使用QT编写,用于硬件设备的调试,可直接驱动串口或各种调试器(基于OpenOCD支持),有以下几个主要特性 +本程序使用QT编写,用于硬件设备的调试,可直接驱动串口或各种调试器(基于OpenOCD支持) -* 主要功能 +**主要功能** - * **实时查看**和**修改**变量值 +* 实时查看和修改变量值 - * 变量值**波形实时绘制** +* 实时绘制变量值波形 - * **采样数据导出**到CSV表格 +* 导出采样数据 - * 格式化**日志**输出 +* 格式化日志输出 -* 调试器模式理论上支持OpenOCD允许GDB连接的各种调试器及硬件芯片,如STLink、JLink、CMSIS-DAP等以及STM32全系列等 +**连接方式** -* 调试器模式下采样最高约100Hz,串口模式约80Hz +* 调试器模式:软件直接驱动调试器读取目标芯片数据 -* 图形化变量选择器 + * 无需修改目标芯片程序 -> 目前进行了以下设备的测试 -> 调试器:STLink、CMSIS-DAP -> 目标芯片:STM32F103RCT6、STM32F103C8T6 + * 理论上支持OpenOCD所支持的各种调试器及硬件芯片,如STLink、JLink、CMSIS-DAP等以及STM32全系列等 + + > 附OpenOCD官方文档: [支持的调试器](https://openocd.org/doc/html/Debug-Adapter-Hardware.html)、[支持的芯片](https://openocd.org/doc/html/CPU-Configuration.html#Target-CPU-Types) + + * 最高采样速度约100Hz + +* 串口模式:软件和目标芯片间通过串口连接 + + * 需将一段程序移植至目标芯片中 + + * 可支持几乎所有带串口的芯片 + + * 最高采样速度约80Hz ![运行演示](imgs/run-demo.png) @@ -32,23 +42,31 @@ ## 使用方法 -1. 若使用串口连接,需先将串口下位机程序移植到目标芯片中 [串口移植说明](lower/serial/README.md) +1. 若使用串口连接,或需使用日志功能,需先将对应下位机程序移植到目标芯片中 -2. 若使用日志功能,需先将日志下位机程序移植到目标芯片中[日志移植说明](lower/log/README.md) + > 请查看[串口移植说明](lower/serial/README.md)、[日志移植说明](lower/log/README.md) + + > 注:串口与日志功能不冲突,可以同时使用 -> 注:串口与日志功能不冲突,可以同时使用 +2. 下载最新发行版,解压后双击`LinkScope.exe`运行程序 -3. 点击设置符号文件,添加变量 +3. 点击设置符号文件,然后设置要查看的变量 - * 加载符号文件后即可在变量选择窗口添加需要查看的变量,可以直接添加到列表或添加到编辑框后进行手动编辑 + * 添加变量 - * 在主窗口表格最后一行变量名(编辑框)处手动填写也可以添加变量 + * 在变量选择窗口添加(须先设置符号文件) - * 在变量名上右键可删除变量,或在选中变量名后按Del键 + * 在主窗口表格最后一行的变量名处手动填写 - * 变量名不仅可以填入单个变量名,还可以填入合法的C语言表达式(GDB支持即可);复合类型不能修改和绘图,只能实时查看 + * 删除变量 -4. 选择连接模式,连接芯片,连接后程序开始循环采样 + * 在变量名上单击右键 + + * 单击选中变量名后按Del键 + + > 注:添加的变量名可以是任何合法的C语言表达式,可参考[进阶使用说明](#进阶使用说明);结构体等复合类型只能查看,不能修改和绘图 + +4. 选择连接模式,连接芯片,连接成功后程序开始采样 * 调试器模式下,在下拉框中选择调试器和芯片类型,点击连接目标 @@ -58,7 +76,7 @@ 6. 单击`变量名`列选中对应的变量,绘图窗口会加粗绘制波形,左下角会显示当前值和查看值(拖动鼠标进行查看) -7. 绘图界面说明可以在绘图窗口点击操作说明查看,滚轮配合`Ctrl`、`Shift`、`Alt`可以实现画面的缩放和移动 +7. 绘图界面中滚轮配合`Ctrl`、`Shift`、`Alt`可以实现画面的缩放和移动 ![操作演示](imgs/oper-sample.gif) @@ -68,7 +86,7 @@ ## 主要菜单项说明 -* `刷新连接配置`:连接配置文件位于`openocd/share/openocd/scripts`下的`target`和`interface`中,用户可按照OpenOCD语法编写配置脚本,放入对应目录下,然后点击该菜单项将配置文件加载到下拉选框中 +* `刷新连接配置`:若自行编写了配置文件,可以通过该菜单项将配置文件加载到下拉选框中,可参考[进阶使用说明](#进阶使用说明) * `保存配置`:软件中所配置的连接模式、调试器型号、芯片型号、符号文件路径和各变量的配置都可以通过该菜单项保存到一个配置文件中 @@ -78,6 +96,44 @@ --- +## 进阶使用说明 + +* 在变量名处可以填写任意GDB支持的C语言表达式 + + 假设目标程序的`main.c`中含有如下全局变量 + + ```c + static int g_int = 0; //静态全局变量 + int g_arr[10] = {0}; //全局数组 + struct Pack { + int var1,var2; + } g_pack = {0}; //全局结构体变量 + ``` + + 则可以通过变量名实现下列查看 + + ```c + g_int //查看变量g_int的值 + &g_int //查看g_int的地址 + g_pack.var1 //查看g_pack中var1成员变量的值 + g_pack.var1+g_pack.var2 //对两个变量求和 + p_arr[0] 或 *g_arr //查看g_arr数组的第一个元素 + g_pack //查看整个结构体(不能绘图) + g_arr[2]@3 //查看g_arr[2]至g_arr[4](不能绘图) + 'main.c'::g_int //指定查看main.c文件中的g_int + *(int*)0x20005c5c //查看0x20005c5c地址上的一个int数据(此方式无需设置符号文件也能用) + ``` + +* 可以通过修改OpenOCD配置文件自定义调试器模式下的连接 + + * 配置文件位于`openocd/share/openocd/scripts`下的`target`和`interface`文件夹中,可以在其中进行修改或添加 + + * 配置语法可以参考[OpenOCD官方文档](https://openocd.org/doc/html/Config-File-Guidelines.html) + + * 若新增了配置文件,可以通过`刷新连接配置`菜单项将其载入到软件下拉选框中 + +--- + ## 使用注意事项 * 若不指定符号文件,无法使用变量名,只能通过绝对地址进行查看 @@ -100,29 +156,44 @@ ## 其他说明 -* 关于采样速度 +**关于采样速度** - * 采样速度与CPU占用率、添加的变量数量、日志输出频率等因素相关,程序会以尽可能高的速度进行采样 +* 采样速度与CPU占用率、添加的变量数量、日志输出频率等因素相关,程序会以尽可能高的速度进行采样 - * 简介中介绍的采样速度是在`i5-8265U`CPU接近空载时,添加单个变量并关闭日志的情况下测试得到的 +* 简介中介绍的采样速度是在`i5-8265U`CPU接近空载时,添加单个变量并关闭日志的情况下测试得到的 + +* 调试器模式下获取单条日志用时约50ms,串口模式约90ms,获取过程中无法进行采样,若日志数量较多则会对采样速度造成较大影响 + +**关于实际支持的设备** + +* 虽然理论上支持OpenOCD所支持的所有设备,但受各种因素影响,实际使用时仍可能在部分设备上无法工作 + +* 目前已测试过的设备如下: + + * 调试器:STLINK-V2、CMSIS-DAP + + * 目标芯片:STM32F103RCT6、STM32F103C8T6、STM32F407ZGT6、STM32F407IGH6 - * 调试器模式下获取单条日志用时约50ms,串口模式约90ms,获取过程中无法进行采样,若日志数量较多则会对采样速度造成较大影响 --- -## TODO +## 开发说明 -* 提升采样频率 +> 注:若您希望参与贡献,可以阅读本段说明,若仅需使用软件则无需阅读 -* 增加对本地程序的支持 +**开发环境** ---- +* IDE:Qt Creator -## 运行过程简介 +* QT版本:5.9.9 -* 调试器模式下,连接目标时,程序会在后台启动OpenOCD进程进行连接,并命令GDB进程连接到OpenOCD;串口模式下,OpenOCD被替换为一个Tcp服务器用于解析GDB指令并收发串口数据 +**运行过程简介** -* 运行过程中程序会不断模拟与GDB进程进行命令行交互,在用户添加变量时使用`display expr`指令将变量添加到GDB的查看表中,同时定时10ms发送`display`指令并进行正则解析,更新用户界面 +* 调试器模式下,连接目标时,程序会在后台启动OpenOCD进程进行连接,并命令GDB进程连接到OpenOCD;串口模式下,OpenOCD被替换为一个Tcp服务器用于解析GDB的RSP指令并收发串口数据 + + ![程序结构框图](imgs/process-block-diagram.png) + +* 运行过程中主进程会通过标准输入输出与GDB进程进行交互,在用户添加变量时使用`display expr`指令将变量添加到GDB的查看表中,同时定时10ms发送`display`指令并进行正则解析,更新用户界面 * 程序开有一个微秒级定时器,每收到一个变量采样数据时,会从该定时器获取当前的时间戳并与数据一起记录下来,同时绘图窗口会不断对历史数据进行更新绘图 @@ -132,10 +203,36 @@ * 日志下位机程序会创建一个缓冲区队列,下位机会将日志输出到缓冲区中,程序会定时使用GDB的print指令将日志出队并解析显示出来 ---- +**仓库文件说明** -## 仓库文件说明 +* `mainwindow.cpp/h`:主窗口 -* `lower`目录下为下位机程序 +* `graphwindow.cpp/h`:绘图窗口 -* 编译QT程序后需要将`gdb`和`openocd`目录复制到可执行文件同级目录下 +* `listwindow.cpp/h`:变量选择窗口 + +* `logwindow.cpp/h`:日志窗口 + +* `aboutwindow.cpp/h`:关于窗口 + +* `helpwindow.cpp/h`:帮助窗口 + +* `openocd.cpp/h`:openocd进程控制 + +* `serialocd.cpp/h`:串口服务器相关逻辑,负责接收GDB的TCP连接并通过串口与下位机连接 + +* `gdbprocess.cpp/h`:gdb进程控制和输出解析 + +* `vartype.h`:变量相关数据类型定义 + +* `qss`:QSS样式文件 + +* `gdb`/`openocd`:gdb和openocd的执行和配置文件,不参与编译,需在编译后手动置于可执行文件同一目录下 + +* `lower/log`/`lower/serial`:下位机代码 + +**TODO** + +* 提升采样频率 + +* 增加对本地程序的支持 diff --git a/imgs/process-block-diagram.png b/imgs/process-block-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..31b041a28f75095710dee489a4018b869f16f1f0 GIT binary patch literal 38831 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 N44$rjF6*2UngE|>6 例:`LOG_INFO("sys","code=%d",123);//输出的日志标签为"sys",日志内容为"code=123"` + > 例:`LOG_INFO("sys","code=%d",123); //输出的日志标签为"sys",日志内容为"code=123"` * `#define LOG_DEBUG(tag,msg,...)`:输出调试日志,用法与信息日志相同 @@ -52,13 +58,13 @@ > 注:若不想新增`log.c`文件或编译器不支持多个源文件,可以将其中的内容放入任何一个源文件中 -2. 根据平台修改配置项 +2. 根据所用平台修改配置项 - * 一般情况下只需修改时间戳配置即可,其余参数可以保持默认 + * **一般情况下只需修改时间戳配置`LOG_GET_MS`即可**,其余参数可以保持默认 - * 若下位机内存不够,或希望输出更长的日志,或希望一次性写入更多条日志,可修改日志缓冲区大小配置 + * 若下位机内存不够,或希望输出更长的日志,或希望一次性写入更多条日志,可修改缓冲区大小配置`LOG_MAX_QUEUE_SIZE`、`LOG_MAX_LEN` - * 若编译器不支持`__FUNCTION__`宏,需要将函数名宏定义替换为空字符串 + * 若编译器不支持`__FUNCTION__`宏,需要将`LOG_GET_FUNC_NAME`替换为空字符串 * 若编译器不支持标准库函数,需要自行实现各函数并替换到对应宏定义中 diff --git a/lower/serial/README.md b/lower/serial/README.md index 6bf9339..df8a06b 100644 --- a/lower/serial/README.md +++ b/lower/serial/README.md @@ -2,9 +2,15 @@ --- -# 配置项 +## 相关文件 -* **`#define DEBUG_SEND(buf,len)`**:需配置为所用平台的串口发送语句,将buf所指向的len个字节通过串口发出 +本下位机程序仅包含单个文件`debug.c`,位于仓库`lower/serial`目录下,也可以下载发行版中的下位机程序压缩包后在`serial`文件夹中找到 + +--- + +## 配置项 + +* **`#define DEBUG_SEND(buf,len)`:需配置为所用平台的串口发送语句,将buf所指向的len个字节通过串口发出 * `#define DEBUG_RESET()`:需配置为所用平台的复位语句,上位机中点击复位并运行时会调用该语句 @@ -12,23 +18,23 @@ * `#define DEBUG_WRITE_ADDR_RANGE(addr)`:写地址限制条件,若请求的地址addr不符合条件则不会写入 -> 注:加粗项为必需配置,其余项若不需要对应功能可不定义 +> 注:带**的项为必需配置,其余项若不需要对应功能可不定义 --- -# 函数接口 +## 函数接口 * `void Debug_SerialRecv(uint8_t *buf,uint16_t len);`:外部程序需要在收到串口数据时调用该函数进行解析,buf为数据首地址,len为字节数 -> 注:程序使用循环队列作为接收数据缓存,调用该函数时无需保证一次性传入完整数据帧,但应保证一个数据帧接收结束时及时调用该函数 + > 注:程序使用循环队列作为接收数据缓存,调用该函数时无需保证一次性传入完整数据帧,但应保证一个数据帧接收结束时及时调用该函数 --- -# 移植说明 +## 移植说明 1. 开启一个串口,将下位机程序添加到项目工程中 -> 注:串口需配置为波特率115200、8位数据位,无校验位、1位停止位 + > 注:串口需配置为波特率115200、8位数据位,无校验位、1位停止位 2. 修改配置项 @@ -36,9 +42,9 @@ --- -# 移植示例 +## 移植示例 -## STM32 & HAL & 中断收发 +### STM32 & HAL & 中断收发 ```c @@ -81,7 +87,7 @@ void USART1_IRQHandler(void) //串口中断服务函数 ``` -## Arduino 串口轮询方式 +### Arduino 串口轮询方式 ```c++