设为首页收藏本站

腾控科技论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4636|回复: 1

[管理员已阅读]一次调试之殇(STM32)

[复制链接]
steelen 发表于 2013-5-20 10:01:28 | 显示全部楼层 |阅读模式
最近调试一段代码,发现一个很奇怪的现象,有一个函数放在一个位置,代码的执行结果是正确的。如果放在其他地方就会出现问题,同样的一个函数,为什么会出现这样的差距呢?
看到这里,或许很多人已经猜出问题的原因了。
但是,对于当时还在调试这段代码的人来说,或许是思维进入了一种惯性模式,看不到障眼法背后的实质原因。
一直以为是,函数的位置导致了程序执行结果的偏差。
甚至当时的心情,都有些向《代码大全》中提到的,“我的代码被狗吃了”。想怀疑是编译器出问题了,但是,《代码大全》让我知道,现在 的编译器出现问题的概率是极小的。如果我遇上了,几乎相当于买彩票中几百万的大奖。
还是要回到代码本身,代码出现问题,一般不是因为其他而导致的。程序是人写的,人在这个过程中,是最有可能出错的。也是出错概率最大的。平均,代码中30%左右的错误是因为输入拼写错误导致的。
但是,当自己找了很长时间,还是没有找到原因。因为找了很长时间,当时有些想放弃找到这个问题的真正原因了。然而,在分析其他代码的时候,突然想到如果有一个地方失误了,可能导致这个问题:即,变量使用的是一个随机值。
而造成随机值的原因,就是初始化问题。

想到这里,将出现问题的函数后重新check了一下,发现写入时,对于某些变量可能出现没有初始化的情况,这样将造成变量的值随机。
修正后,出问题的函数,不在出现了放置位置导致的执行效果,出错的问题。
对于此,想到几点:
  • 代码完成后,休息一下,然后check几遍,check找到bug的效率是调试的几倍;
  • 发现代码中的漏洞,很多时候,都是我们自己引起的;
  • 关于这几天调试程序问题,有几方面原因:
    • 开始时,一次调试需要很长时间,这里只在意尽快调试,没有把主要精力放在,代码check上;
    • 调试时,过于集中于代码本身,而忽视了本质问题;
    • 本次调试时,明显分析能力下降不少,只注重了表象,没有关心实质问题;
    • 调试的心态不对,要注意;
  • 还是没有做好这些东西;
  • 学会放置代码,以后再进行检查,避免进入思维惯性;
  • 不以物喜,不以己忧,尚要努力;
附注:
调试过程中的分析记录:
  • cnt,记录下这个变量的值,使用这个值进行测试;
  • 同时注释掉,删除下载文件的代码,使用这段代码进行升级下载测试;
  • cnt = 0x103,下载文件结束偏移20400;
  • 是什么原因,导致了升级时的APP_FAULT_ISR;
  • 同时对于升级参数中,应该有一个判断是否升级成功的标识,这样避免的那个升级不成功的时候,恢复到原来版本时,擦出原来版本。
  • 由断点调试发现,是重启后,没有跳转到升级后的FLash地址上运行,造成了还是在原版本上跳转,但是这里的问题是,为什么原有的程序也执行失败了?
  • 怀疑是后边升级时写入Flash的问题。
  • 升级部分的代码,确实很令人费解,一个函数的位置,竟然影响程序的生死,但是按照语言规则,不会有这么灵异的事情;
  • 看到f_close和f_mount,怀疑是不是跟这两个函数有关系;
  • 测试发现,这里跟f_close,f_mount没有关系,只跟判断到HEX文件的结束标志后,要立即复位,进行程序更新,否则就会出现问题。
  • 造成了,程序的中断向量区,似乎没有进行更新,还是跑的以前的代码段,并跳转到了以前的main函数执行,但是经过了OSStart之后,程序发生了崩溃,回到了APP_FAULT_ISR的地方;这中间的问题,具体还没有想清楚;
  • 首先先以(a方式)每次循环中都关闭的情况,来测试下看看;测试通过;
  • 其次使用(b方式)先打开,在循环中读取并写入内部Flash,最后再关闭文件;测试不通过;现象:
    • 程序启动后,跳转到原来版本的入口地址处;
    • 之后程序能够正常初始化等,但是在OSStart函数之后,执行出现异常;
    • 跳转到APP_FAULT_ISR;
    • 重复以上步骤。
  • 第三次,重复(1)的步骤,进行再次验证;测试通过;
  • 由此说明(2)的方式在程序中通不过;
  • 关于这个情况,描述下问题:
    • 这里需要从外部Flash中读取一个文件,并将其写入到内部Flash中,然后完成程序复位,实现程序的升级;
    • (a)中的方式是,每次读取一定的字节数时,先打开文件进行读取,读取结束后关闭文件,然后校验读取到的数据,校验成功,写入到内部Flash中,文件读取结束后,调用升级函数实现程序复位及升级;、
    • (b)中的方式是,先打开外部Flash文件,读取一定的字节数据,然后校验读取到的数据,校验成功,写入内部Flash,文件读取结束后,关闭外部Flash文件,调用升级函数实现程序复位及升级;
  • 关于两种方式,第一种会引起每次循环都有打开与关闭外部Flash文件的情况,第二种只有一次打开与关闭外部Flash文件的情况,理论上(b)的执行效率更高。但是实际测试发现,复位后(a)程序跳转正常,(b)程序跳转异常;这里边的原因,尚没有找到;
  • 现猜测是由于Flash操作的问题;
  • 先暂定使用(a)方式,如果以后需要效率问题,这里是个可以提升的地方,但是要详细测试;
  • (a)方式,在将upgrade_program,放在发送回复之后,出现问题;
  • 总之,这里得出一个结论,将程序写入内部Flash后,马上调用复位函数,进行程序升级;如果以后还需要对这里进行优化,可以详细测试下这里的原因,再行决定更合适的方案;
  • (9)不是Flash操作的问题。
  • 发现这里只跟何时调用upgrade_program函数有关系,检测到HEX文件的结束符,之后马上进行,程序复位,将不会引起错误;这个需要分析下原因在哪里;
  • 发现,是在更新的时候,出现的错误;由于修改升级函数,但是没有及时将其bReadBkpDR,bWriteBkpDR函数没有配对使用;






该贴已经同步到 steelen的微博
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
 楼主| steelen 发表于 2013-5-20 10:01:53 | 显示全部楼层
http://forum.eet-cn.com/BLOG_ART ... ick_from=8800102519,8879421582,2013-05-20,EECOL,FORUM_ALERT
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
您需要登录后才可以回帖 登录 | 注册

本版积分规则

产品样机试用申请

QQ|小黑屋|手机版|Archiver|腾控科技|腾控科技 ( 京ICP备09109731号  

GMT+8, 2020-10-25 07:24 , Processed in 0.125779 second(s), 19 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表