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 0000000..31b041a Binary files /dev/null and b/imgs/process-block-diagram.png differ diff --git a/lower/log/README.md b/lower/log/README.md index 0706db8..e0460fc 100644 --- a/lower/log/README.md +++ b/lower/log/README.md @@ -2,6 +2,12 @@ --- +## 相关文件 + +本下位机程序包含`log.c`、`log.h`两个文件,位于仓库`lower/log`目录下,也可以下载发行版中的下位机程序压缩包后在`log`文件夹中找到 + +--- + ## 配置项 * **标准库函数配置项** @@ -36,7 +42,7 @@ * `#define LOG_INFO(tag,msg,...)`:输出信息日志,`tag`为日志标签,`msg`为日志内容,日志内容中可包含格式化占位符,与后面的可变参数一起进行格式化输出 - > 例:`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++