嵌入式中变量被意外修改的调试方法

问题描述

在移植公司的实时操作系统到一款国产 RISC-V 架构芯片时,为了测试 systick 中断是否有效,在此中断 isr 中对一个静态变量加一,打断点观察变量的变化来确定中断是否正确执行了!

中断 isr 的主要内容如下:

	isr_handler(void) 
	{
		...
		static int i = 0;
		i++;
		clear_interrupt_flag();
		...
	}

在调试的过程中发现,进入到这个函数后确实给变量加 1 了,但是下一次再进入时变量值又会变为 0,调试了下汇编没发现问题。多执行几次发现效果相同,问题能够不断【复现】。

调试方法

变量的值被意外修改这样的问题之前也已经遇到过,直接的方法就是 watch 这个变量的地址,在修改的时候程序会停下来,这样就能看到哪里进行了非法操作。

可是在此款芯片上上面的方法却不太适用。虽然可以 watch 一个变量的地址,但是 watch 之后程序执行非常非常慢,可能要等非常久才能定位到问题,而我有不能减少中间执行的过程,这是一个常识性的问题,因此这中方式只能弃之不用。

有没有更好的方式呢?

我仔细的想了想,立刻就想到了一种非常简单的方式。我可以把这个变量设置为常量,常量一般都存储在代码段,而在我使用的这个芯片上,代码段是放在 flash 上面的,要通过普通的访存指令修改 flash 上面的数据会进入异常,这样我只需要查看异常发生的位置就能够成功定位到出问题的地方。

这样的方式果然好用,我立刻就发现了问题,可是让我不解的是它指向了一个不在代码区域内的位置,这可出乎我的意料了。

进一步的分析

当我发现问题发生的地方是一段程序区域外的位置,我觉得可能在中断处理流程中栈帧被修改了,这样恢复的时候才恢复到了一个错误的地址,这样的怀疑比较合理。我再回去看了看中断处理的汇编代码,发现我在中断中切换到了系统栈,将需要保存的现场存储到了系统栈中,而我的用户程序也使用了系统栈,这样旧的栈帧就被中断处理过程破坏了,恢复之后就表现出了一个异常的行为。

其实我切换栈指针这样的设计是正确的,只是我不应该在非任务环境下测试它。当第一个任务调度运行之后,中断打断的任务与系统栈有不同的栈指针,在这种条件下切换栈指针是正确的。我按照这样的思路创建了任务,启动实时操作系统,再次测试便没有问题了!

总结

在实际的测试中,对一些必要条件的忽略可能会造成严重的问题,我们不仅要关注程序执行的流程,更要关注程序执行的环境及程序执行对这一环境带来的改变

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值