调试单片机程序时,光盯着变量值看,往往只能弄清楚一部分问题;一旦遇到中断响应不对、外设状态报错、任务切换出现混乱,或者程序干脆跑飞了,还得去翻看CPU内部的寄存器和外设那边的寄存器。要弄明白在IAR C-SPY里怎么查看寄存器发生的变化,以及寄存器窗口的数值一直不刷新可能是什么原因,重点是把普通的一次性查看和程序跑起来以后的持续观察区分开。C-SPY既能查看CPU寄存器、外设寄存器,也能打开内存窗口,并且可以把寄存器分组和调试窗口的布局保存下来,下次再用就方便了许多。
一、IAR C-SPY怎么查看寄存器变化
观察寄存器变化,不能只靠程序全速跑的时候拿眼睛盯着窗子看;更稳当的做法,是让程序在几个关键点停下来,再比较执行前和执行后的数值有什么不同。
1、进入调试会话
完成编译以后,点一下【Project】→【Download and Debug】,让IAR进到C-SPY的调试环境。当程序停在入口位置时,再从【View】菜单里把【Register】窗口打开。不同芯片版本下,菜单名称可能有一点点差别,但调试窗口里都会把CPU寄存器和外设寄存器分好组列出来。
2、选择需要查看的寄存器组
看CPU运行状态,可以先关注PC、SP、状态寄存器还有几个通用寄存器;等到排查GPIO、UART、SPI、定时器或中断问题时,再对应展开外设寄存器。不要一口气展开太多外设分组,否则每次单步执行,工具都要从硬件那里重新读取更多状态,调试速度会明显变慢。C-SPY的资料也提过,寄存器窗口打开以后,在单步期间是需要从硬件重新读一次寄存器的。
3、在关键代码前后设置断点
往寄存器里写数据的语句前面设一个断点,执行完这条语句之后再设一个断点;点一下【Go】跑到断点,把当时的原始数值记下来,接着用【Step Over】单步跨过,看看寄存器有没有照着预想的情况变化。排查中断时,不光要看通用寄存器,还要同时去瞧状态寄存器、中断使能位和挂起标志这些地方。
4、需要记录变化时缩小观察范围
只留下跟当前问题直接相关的那几个寄存器组就好;寄存器数量太多时,可以自己建一个自定义分组,把需要反复查看的那些寄存器放在一起。C-SPY会在多次调试会话之间帮着保留住寄存器组的设置,下回再进到调试界面时,不用重新再去整理一遍。
二、IAR C-SPY寄存器窗口不刷新的原因有哪些
寄存器窗口里的数值一直不变化,未必是程序没有在跑,很多时候是目标还在全速运行、调试驱动不支持实时读取,或者当前查看的那几个寄存器本身有访问上的限制。
1、程序没有停下来
一般的Register窗口更合适在暂停、断点命中或者刚做完单步之后去瞧。当程序持续运行的时候,部分调试驱动不会一直不停地去读全部寄存器;这时可以点一下【Break】叫程序先停住,再看数值有没有更新。想要连续观察普通变量,可以试试Live Watch,但它刷新得是否稳定,还是得看驱动和目标硬件本身。C-SPY对变量和表达式,既支持连续监控,也可以按需要去读取。
2、芯片型号或调试驱动选错
进到【Project】→【Options】,先检查【General Options】里选的目标器件,再看【Debugger】→【Setup】中的驱动类型是不是配对了。C-SPY会根据所选的驱动给出不同的设置项,I-jet、J-Link、ST-LINK、CMSIS-DAP这些驱动的可用能力并不完全一样。
3、外设寄存器读取受到限制
有些外设寄存器,必须先把外设的时钟打开才能正常读到;还有些寄存器属于只写、读一次就会自动清零,或者是受保护的。如果窗口显示一直不变,或者直接出现问号,再或者读取之后状态自己变了,就要去翻一翻芯片手册,把访问规则弄清楚,不要上来就断定是C-SPY不正常。
4、调试链路不稳定
目标板反复自行复位、跑进了低功耗模式,又或者调试器跟目标板的连接不太稳固,都会让寄存器窗口停在旧的数值上。这时可以先暂停程序,把目标板的连接重新插拔,再查一下供电情况、下载配置和调试接口的通信速率。
三、IAR C-SPY寄存器变化怎样稳定复核
寄存器问题排查完以后,还要按一套固定的步骤去做一次复核,不要只凭一次单步的结果就急着下结论。
1、固定断点位置
每次都在相同的代码位置把程序停下来,把当时的输入条件、寄存器初始值和执行完的结果放在一起对比。如果是中断方面的问题,就要把进入中断前、刚进入中断后,还有退出中断后的状态,分别记下来好好对照。
2、减少同时打开的窗口
寄存器窗口、Memory窗口、Watch、Live Watch和Locals这些窗口,每多开一个都会增加调试读取的负担;发现单步开始出现卡顿的时候,先把跟当前问题没关系的窗口关掉,只保留必要的寄存器组。
3、用数据断点辅助定位
如果芯片和调试驱动都支持数据断点,可以针对某个内存地址设一个专门监视写入动作的断点;C-SPY的数据日志断点能够按照Read、Write或Read/Write类型记录对该地址的访问,用来追查某个变量或者映射过去的寄存器到底是被哪段代码改动了,效果会很好。
总结
在IAR C-SPY里查看寄存器变化,基本顺序是先进入调试会话,打开Register窗口,选择要看的是CPU还是外设寄存器组,接着用断点和单步比较执行前后的数值。寄存器窗口不刷新时,重点检查程序是不是真的停住了、芯片型号和调试驱动有没有选对、外设时钟是否打开、寄存器本身的访问属性,以及调试链路的稳定性。把观察范围收窄之后,再用固定的断点和数据断点复核一遍,定位就会更有把握。