news 2026/7/18 13:27:30

J-Link+Ozone调试教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
J-Link+Ozone调试教程

一、调试前的准备

使用J-Link将PC和单片机连接

以STM32入门教程中的“读写内部FLASH”实验为例,使用Keil打开该工程

按照下图所示的步骤进行操作,如果使用J-Link仿真器,则在第三步选择ST-Link Debugger

按照下图所示的步骤进行操作,输出选项卡需要勾选调试信息

按照下图所示的步骤进行操作,代码生成的优化选项中,优化等级需要选为0,否则Keil在编译程序的过程中可能会过度优化,导致编译得到的二进制机器码和C语言代码不是等价的,在调试过程中会引起代码执行顺序错乱

完成以上步骤后,编译程序,然后将其下载到单片机中

二、Ozone调试工程快速创建

1、新建工程

(1)打开Ozone,在菜单栏选择“File”→“New”→“Project”,新建一个工程。(如果是初次使用,那么打开Ozone后会自动弹出向导,引导用户新建工程)

(2)在Device选择MCU型号(本教程使用STM32F103C8T6),并在Peripherals导入对应的.svd文件(芯片厂商提供,可生成外设寄存器树,直接在上位机查看和修改外设寄存器)。

(3)主机接口选择USB;目标接口视情况选择,对于ARM芯片,通过查看数据手册关于调试的章节,可以确认是否支持SWD,支持即可选择,而非ARM芯片仅支持JTAG;目标接口速率可以选择2MHz,若硬件稳定,则可以提速。

(4)选择编译输出的.elf文件,如果是使用Keil编译,则选择编译输出的.axf文件(.axf文件是ARM扩展版.elf文件),路径尽量不包含中文和全角字符。

(5)创建完成后,在菜单栏选择“File”→“Save Project as...”,即可保存调试工程。

2、三种调试启动模式

(1)Download & Reset Program:擦除Flash,将固件烧录到Flash中,然后复位MCU,释放复位后程序从头全速运行。

(2)Attach to Running Program:连接后程序保持运行,可观察设备实时的动态变量,不会破坏RAM堆栈、寄存器。

(3)Attach & Halt Program:连接后停止正在运行的程序,直接冻结现场,立刻捕获当前寄存器、堆栈、内存快照,不会破坏RAM堆栈、寄存器。

三、Ozone基础调试功能

1、断点系统与变量访问

(1)使用Ozone调试,Flash区不限制硬件断点数量(Cortex-M只有4~8个硬件断点,Keil调试受限于硬件数量),因为Ozone自动在Flash写入BKPT断点指令,缓存原始指令,断点取消后自动恢复代码。

(2)源码断点(程序断点):

①在代码浏览区的左侧有一些灰色的区域,鼠标左键点击,即可在区域对应的代码打上源码断点,当单片机运行到这些代码的时候,会触发停止运行的条件;如果需要取消源码断点,鼠标左键点击它对应的红色圆圈,即可取消断点。

②鼠标右键点击源码断点对应的红色圆圈,选择“Edit Breakpoint”,在弹出的窗口中可以设置断点触发的前置条件。

[1]Condition填入条件表达式,如cnt>100。如果选择“Trigger when true”,那么断点命中时,需要满足条件表达式才会真正停机;如果选择“Trigger on change”,那么断点命中时,表达式数值发生过变化,才会真正停机。

[2]Skpi填入断点命中次数,假如设置为499,那么断点命中500次才会真正停机。

(3)数据断点(访问断点):

①数据断点,它是针对变量(或者说内存地址)而言的,如果一个变量被设置了数据断点,那么当程序对该变量进行访问时,会触发停止条件。

②数据断点的设置方式:

[1]在菜单栏选择“View”→“Watched Data”,打开数据监测窗口。

[2]直接编辑表达式,输入变量名或变量地址,即可监测变量的值,编辑Value属性还可以直接在线修改变量的值,但是需要注意,对于非静态局部变量,仅程序运行到该函数栈帧内时有效,函数退出后栈内存失效。

[3]鼠标右键上一步添加的变量,选择“Set Data Breakpoint”,即可为该变量添加数据断点。

[4]数据断点有三个参数,设置完成后,点击“OK”即可,能看到变量被打上黄色圆圈标记。

Expression:数据断点的表达式,也就是变量名或变量地址

Access Condition:数据断点的触发条件,可选择仅读访问触发(Write)、仅写访问触发(Read)、读写访问均可触发(Read/Write)

Access Size:数据断点对应的变量字节长度,可选择1/2/4 Bytes或自动识别(Automatic)

(4)向量捕获断点:

①如果设置了向量捕获断点,那么程序一旦进入异常处理函数,将会立刻停机,自动弹出异常窗口,直接显示故障原因,不用手动进HardFault函数挖栈。

②向量捕获断点的设置方式:

[1]在菜单栏选择“View”→“Break & Tracepoints”,打开断点管理窗口(断点管理窗口会管理所有类型的断点,可以在其中配置断点是否使能)。

[2]鼠标右键窗口的空白区域,选择“Vector Catch”。

[3]将所有错误类型全部勾选。

(5)任务断点:

①如果程序使用了FreeRTOS/μC-OS,则可以设置断点仅在执行指定任务时可以触发,用于排查多任务干扰bug。

②任务断点的设置方式:

[1]按照源码断点的方式在对应代码处设置断点。

[2]鼠标右键断点,选择“Edit Breakpoint...”,打开断点编辑窗口。

[3]如果程序使用了FreeRTOS并且有任务定义,则可在Task选项的下拉框选择相应的任务,这样,只有当前执行任务匹配所选任务时,断点才会触发。

2、实时变量波形绘图

(1)在菜单栏选择“View”→“Data Sampling”,打开数据采样窗口。

(2)切换Data Sampling窗口的选项卡为Setup,将想要观察动态变化的变量从Watched Data窗口拖到Data Sampling窗口,或者手动添加表达式(全局/静态变量名)。

(3)切换Data Sampling窗口的选项卡为Samples,可以看到每隔一定的采样时间(采样频率Sampling Freq可配置),Ozone都会对变量值进行采样,生成若干数据点,鼠标右键窗口,选择“Export...”,即可导出.csv格式文件,然后使用其它工具(如MATLAB)绘图。

3、其它调试窗口

(1)Call Stack:

①打开方式:在菜单栏选择“View”→“Call Stack”。

②函数调用栈可显示函数的调用链路,在出现Hardfault时,还可直接定位bug函数。

(2)Registers(Peripherals):

①打开方式:在菜单栏选择“View”→“Registers”。

②寄存器窗口显示了单片机的所有寄存器存储情况,如果导入了相应的.svd文件,还可直接查看外设寄存器的存储情况。

(3)Memory:

①打开方式:在菜单栏选择“View”→“Memory”。

②Memory支持整片内存的查看,对于可写区域可以直接在线修改。

(4)Disassembly:

①打开方式:在菜单栏选择“View”→“Disassembly”。

②Disassembly窗口展示汇编语言(与C语言混排,展示对应关系),支持单步汇编级调试,可定位异常指令。

(5)Source Files:

①打开方式:在菜单栏选择“View”→“Source Files”。

②Source Files窗口展示程序中的代码文件(不一定包含工程的所有文件,在编译过程中未使用的代码文件不会显示),双击对应的代码文件可在代码浏览窗口打开它,按下Ctrl+F可以查找想要搜索的字段,在菜单栏也提供了若干Find工具搜索变量和函数。

4、程序运行控制键

(1)Halt program execution:控制单片机停止运行程序,代码浏览页面会跳转到停止点。

(2)Resumes program execution:控制单片机继续运行程序,直到触发停止运行的条件,或手动停止运行。

(3)Reset & Break At Symbol:控制单片机复位,运行到程序入口符号(main函数/Reset_Handler)后立刻暂停CPU。

(4)Reset & Halt:控制单片机复位,在复位向量地址处停机。

(5)Reset & Run:控制单片机复位,复位后全速运行程序,直到触发停止运行的条件,或手动停止运行。

(6)Steps into the current subroutine:控制单片机从当前停止点对应的C代码开始运行程序,并停止在下一条C代码,也即只运行一条C代码,如果遇到函数调用,会转入函数中,停在函数开头。

(7)Steps over the current subroutine:控制单片机从当前停止点对应的C代码开始运行程序,并停止在下一条C代码,也即只运行一条C代码,如果遇到函数调用,会一步跳过,不会转入函数(即使在执行函数的时候触发了断点)。

(8)Steps out the current subroutine:控制单片机从当前停止点对应的C代码开始运行程序,直到从当前运行的函数中转出,或触发停止运行的条件,单片机停止运行程序。

5、RTT日志打印

(1)SEGGER_RTT不占用USART硬件串口、不占用定时器,仅靠J-Link调试通道传输,可实现零开销实时打印日志。

(2)单片机工程的工作:

①在J-Link完整安装包中找到RTT源码(如果没有则从SEGGER官网下载即可,截至2026年依然可行),取出如下文件,添加到Keil工程中。(如果后续编译报错,可选择移除SEGGER_RTT_ASM_ARMv7M.s)

②包含头文件SEGGER_RTT.h,并在使用前调用SEGGER_RTT_Init函数,初始化RTT模块(一般在初始化其它模块时一同对其进行初始化)。

SEGGER_RTT_Init();

③RTT支持多通道分离日志,一共16个通道(编号0~15),调用SEGGER_RTT_printf函数可打印日志,函数的使用方式和printf类似,只是多了一个函数参数——通道编号。

SEGGER_RTT_printf(<number>, "<打印的日志字符串及格式控制>", <输出表列>);

④举例:修改main.c,在主函数中打印日志。

#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "Store.h" #include "Key.h" #include "SEGGER_RTT.h" uint8_t KeyNum; //定义用于接收按键键码的变量 int main(void) { /*模块初始化*/ OLED_Init(); //OLED初始化 Key_Init(); //按键初始化 Store_Init(); //参数存储模块初始化,在上电的时候将闪存的数据加载回Store_Data,实现掉电不丢失 /*显示静态字符串*/ OLED_ShowString(1, 1, "Flag:"); OLED_ShowString(2, 1, "Data:"); while (1) { KeyNum = Key_GetNum(); //获取按键键码 if (KeyNum == 1) //按键1按下 { Store_Data[1] ++; //变换测试数据 Store_Data[2] += 2; Store_Data[3] += 3; Store_Data[4] += 4; Store_Save(); //将Store_Data的数据备份保存到闪存,实现掉电不丢失 SEGGER_RTT_printf(0, "Key value = %d\r\n", KeyNum); } if (KeyNum == 2) //按键2按下 { Store_Clear(); //将Store_Data的数据全部清0 SEGGER_RTT_printf(0, "Key value = %d\r\n", KeyNum); } OLED_ShowHexNum(1, 6, Store_Data[0], 4); //显示Store_Data的第一位标志位 OLED_ShowHexNum(3, 1, Store_Data[1], 4); //显示Store_Data的有效存储数据 OLED_ShowHexNum(3, 6, Store_Data[2], 4); OLED_ShowHexNum(4, 1, Store_Data[3], 4); OLED_ShowHexNum(4, 6, Store_Data[4], 4); } }

(3)在Ozone菜单栏选择“View”→“Terminal”,即可打开RTT终端窗口,窗口中能够显示日志信息。

四、RTOS系统级调试

1、RTOS内核感知调试

(1)本节使用FreeRTOS教程中计数型信号量实验的工程进行演示,同样地,该工程也需要做调试前的准备(回看第一节)。

(2)在FreeRTOSConfig.h中添加如下宏定义(注意不要重复定义,如果原本已有定义,则修改已有定义),然后编译工程。

#define configUSE_TRACE_FACILITY 1 #define configUSE_STATS_FORMATTING_FUNCTIONS 1 #define configRECORD_STACK_HIGH_WATER_MARK 1

(3)Ozone加载RTOS解析插件:

①按照之前的步骤新建工程。

②如果弹出如下警告窗口,点击左下角“Apply selected fix-ups”,修复完成后点“Reload Project”重新加载工程。

③在Console窗口输入命令“Project.SetOSPlugin ("C:\Program Files\SEGGER\Ozone\Plugins\OS\FreeRTOSPlugin_CM4.js");”。(导入的.js文件取决于单片机的架构,本例使用的是Cotex-M4架构,所以导入FreeRTOSPlugin_CM4.js)

④在Ozone菜单栏选择“View”→“FreeRTOS”,即可打开任务视图窗口。

(4)开始调试,当程序停止时,任务视图窗口才会更新显示。

2、SystemView系统时序追踪

(1)SystemView是SEGGER配套J-Link的免费(非商业用途)RTOS全时序追踪工具(可从SEGGER官网获取),底层依靠RTT传输内核事件,实时抓取MCU运行全过程,生成可视化时间轴图谱,专门解决嵌入式实时系统卡顿、调度异常、功耗高、中断风暴等疑难问题,兼容FreeRTOS、RT-Thread、uC/OS等主流RTOS。

(2)SystemView工作原理简介:

①目标系统中的应用程序调用SystemView APls,对需要记录的信息进行采集,例如任务切换、中断进出、数据采样等。

②SystemView模块调用RTT APIs,将数据写入位于目标系统RAM里的RTT bufer。

③在不影响目标程序运行的情况下,J-Link通过调试接口读取RTT buffer的内容。

④SystemView主机软件通过J-Link DLL实时获取RTT数据,并进行图形化显示。

(3)使用SystemView前,需要将RTT代码和SystemView代码整合在嵌入式应用程序中:

①RTT源码整合在上一节中有说明,本节不再赘述。

②在SystemView完整安装包中找到SystemView源码(如果没有则从SEGGER官网下载即可,截至2026年依然可行),取出如下文件,添加到Keil工程中。

③在FreeRTOSConfig.h中添加如下宏定义(注意不要重复定义,如果原本已有定义,则修改已有定义),并包含SEGGER_SYSVIEW_FreeRTOS.h文件。

#include "SEGGER_SYSVIEW_FreeRTOS.h" #define configUSE_TRACE_FACILITY 1 #define configRECORD_STACK_HIGH_WATER_MARK 1 #define configGENERATE_RUN_TIME_STATS 0 #define configUSE_STATS_FORMATTING_FUNCTIONS 1

④在main.c文件中包含SEGGER_SYSVIEW.h文件,并初始化SystemView。

#include "stm32f10x.h" // Device header #include "OLED.h" #include "FreeRTOS.h" #include "task.h" #include "FreeRTOS_experiment.h" #include "Key.h" #include "LED.h" #include "SEGGER_SYSVIEW.h" int main(void) { /*模块初始化*/ OLED_Init(); //OLED初始化 Key_Init(); //Key初始化 LED_Init(); //LED初始化 /* SystemView 核心初始化 */ SEGGER_SYSVIEW_Conf(); /* 开始录制 */ SEGGER_SYSVIEW_Start(); FreeRTOS_Test(); while (1) { } }

⑤如果编译报了RAM空间不足的错误,则尝试减小分配给FreeRTOS的堆,修改以下宏定义。

#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )

(4)只要目标芯片的SWD/JTAG带宽足够,SEGGER J-Link支持多应用同时访问同一调试器,首先使用Ozone运行程序,然后单独打开SystemView连接同一个J-Link,即可进行录制。关于SystemView的使用,可参考另外的教程,此处不过多赘述。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 13:26:06

终极指南:3步完成B站缓存视频合并,安卓用户的离线观影救星

终极指南&#xff1a;3步完成B站缓存视频合并&#xff0c;安卓用户的离线观影救星 【免费下载链接】BilibiliCacheVideoMerge &#x1f525;&#x1f525;Android上将bilibili缓存视频合并导出为mp4&#xff0c;支持安卓5.0 ~ 13&#xff0c;视频挂载弹幕播放(Android consolid…

作者头像 李华
网站建设 2026/7/18 13:24:39

告别歌词不同步烦恼:用LRC Maker打造你的专属音乐时光机

告别歌词不同步烦恼&#xff1a;用LRC Maker打造你的专属音乐时光机 【免费下载链接】lrc-maker 歌词滚动姬&#xff5c;可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 你是否曾为心爱的歌曲配上歌词时&#xff0c;发…

作者头像 李华
网站建设 2026/7/18 13:23:05

别踩2026年做培训视频总结的常见成本误区,过来人分享实操经验

先说明白核心判断 2026年做培训视频总结的常见成本误区&#xff0c;本质是要么贪免费选了转写不准的工具&#xff0c;花几小时返工反而亏了时间成本&#xff1b;要么冲动买了高价年卡&#xff0c;一年用不了几次亏了金钱成本。作为测了3年AI效率工具的产品视角博主&#xff0c…

作者头像 李华
网站建设 2026/7/18 13:22:25

暗黑3自动化助手终极指南:D3KeyHelper如何彻底解放你的双手

暗黑3自动化助手终极指南&#xff1a;D3KeyHelper如何彻底解放你的双手 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面&#xff0c;可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 还在为暗黑破坏神3中重复的技…

作者头像 李华
网站建设 2026/7/18 13:22:09

智联招聘和前程无忧哪个好?HR实测对比,主流招聘平台深度测评

大家好&#xff0c;我是深耕人力资源行业多年的持证人力资源管理师。从事招聘、人事统筹工作多年&#xff0c;几乎用过国内主流、小众的各类招聘平台。在日常工作中&#xff0c;被同行、企业管理者问得最多的问题就是&#xff1a;智联招聘和前程无忧哪个更适合企业招聘&#xf…

作者头像 李华
网站建设 2026/7/18 13:19:36

如何高效管理海量Excel数据:批量查询工具使用指南

如何高效管理海量Excel数据&#xff1a;批量查询工具使用指南 【免费下载链接】QueryExcel 多Excel文件内容查询工具。 项目地址: https://gitcode.com/gh_mirrors/qu/QueryExcel 你是否曾经面对数十甚至上百个Excel文件&#xff0c;需要从中查找特定信息却无从下手&…

作者头像 李华