zoukankan      html  css  js  c++  java
  • 心得小结,关于注重加强MCU下调试能力的意识

     

    这两个月没有怎么更新博文,最近换工作了,根据新工作安排,大半年内都做MCU开发(就不要叫单片机了,太老土了)。

    入职新工作了,需重构拳头产品的软件,所以每天加班加点。

     

    单片机与linux应用开发,开发过程中有什么区别之近日个人感悟:

    第一点,单片机往往配合仿真器调试,linux应用开发往往使用串口打印,或者经由以太网的gdb调试、生成coredump文件来定位常见的段错误。

    linux应用开发调试手段,可以参考我的博文: 

    嵌入式交叉编译GDB,结合vscode图形化调试C和C++代码 coredump定位段错误

    第二点,单片机开发会涉及中断,而linux应用开发不会涉及中断的概念。

    (linux驱动开发会涉及中断,但是一般驱动开发工作量少,某个SPI或IIC外设的驱动开发好了以后就可以一直被使用)

     

    近日遇到问题,迷糊了挺久,最后得以解决,在此总结心得。

    我的硬件环境:        MDK-ARM下调试stm32

    我的软件环境:        RT-Thread          PS:以前也常在业余时间了解RT-Thread,这次终于有机会用它做项目了,跃跃欲试。

    我遇到的问题: 

    翻车在一个GPIO上 开启pin中断 导致程序卡死

    具体描述:开启pin中断,就会导致程序卡死,rt_pin_mode()参数配置调整了几次也没用。 翻车在一个GPIO上了。

         硬件触发的信号是正常的高低变化的信号,示波器看过。 同时,我当前使用的是gitee-master版本,不是发布版。

     

    1. 仿真后运行程序,外界给入高低电平的信后,这时程序就会卡死,之后停止运行程序,MDK下并没有箭头指示当前C代码运行到哪里去了。

    但是这里显示PC是0x08004EE4.  

    我不知道是否可以根据此PC值定位出当前运行到哪里,以及如何根据此PC值定位出当前运行到了哪里。

    需要补充一个技能:根据当前的汇编代码定位出当前运行的C代码。

    2. RT-Thread版本,当前是 gitee-master版本,不是发布版。这个有点疑虑,不排除怀疑gitee-master版本的可靠性。但是基本认为gitee-master版本是可靠的。如果实在不行,可以换成release版本去试试。

     

    由于能力有限,目前这个仿真效果对我来说,没什么参考意义,所以我就只能想其他办法了。

    图省事,我直接在原工程上屏蔽了其他也操作了该PIN操作相关的地方,然后再次测试,还是卡死。《== 假设这是我改的一个测试程序,称呼其为测试程序1吧。

    问题解决后,回顾该调试过程,重现了下该测试过程

    这里我犯错了,因为总共就涉及到三四句代码而已,我图省事,直接在原工程上屏蔽一些代码然而当时我确实没有屏蔽完全!那么这样,造成的最终效果还是卡死!

    即我在修改出测试程序1的过程中又犯下了低级错误, 所以导致我又加深了对这个难点O的疑惑。

    展示下我的低级错误:

    我的外部中断是配合一个人感传感器使用的,由于manager_initialization()函数内没有屏蔽掉人感相关代码,间接导致device_human_sensor_init函数被调用,如下图所示,
    这里又再次配置了该外部中断脚。 

    编译程序并烧录,由于没有进行规范的外部中断脚的配置,造成的最终效果还是卡死!

     

    接着说当时的调试,偶然又发现如果烧录该工程到0x08000000的flash起始地址上,我的中断可以正常跑。

    我的项目是使用了OTA的,我当前所编写的是APP代码,所以我就开始怀疑是我的OTA或者称为IAP导致的这个问题。

    Q群讨论,知道了如何查看当前的异常向量表的地址,如下图

    重新实操了下,回顾再次回顾该步骤调试过程: 

    我当时肯定又进行了一些代码的修改,假设这是测试程序2 ,测试程序2直接烧录到0x08000000后外部中断正常,之前测试程序1是个有问题的程序,当时这个测试程序2恰好又被我改对了而已!

    我认为当时这个测试程序2作为APP,烧录到我的APP的0X08020000这个地址肯定也是可以正常运行和响应外部中断的。

    所以当时,我又没能调试好我的这个中断响应后卡死的问题。

    后来是怎么调试好的呢?接着说

    因为我使用的外部中断脚是PD11,那么它的中断服务函数归属于EXTI15_10_IRQHandler

    我一看,是个弱定义,又没搜索到函数定义,虽然我以前还阅读分析过RT-Thread的GPIO驱动框架的源码,但那都是一年半之前的一点兴趣爱好而已,早就忘干净了。

    于是又没继续下去了,现在回顾之前在MDK下的搜索方式,正确的方式应该是这样:

    全都勾选上。

    我当时只勾选了左侧两个,所以没有搜索到RT-Thread的drv_gpio.c内的 EXTI15_10_IRQHandler()函数定义。

    后来我在此处打上断点,然后外界给入高低电平,发现可以进入到这里!一步步运行, 能进入我的中断服务程序,在中断服务程序内打断点,发现一直在里面打转出不来。

     终于定位问题了。

    最后的问题原因在于:

    中断服务程序内一个链表头忘记初始化了,导致ISR内没出来,双向循环链表没初始化,for循环出不来了。

    总结: 

    1. 习惯要好。 如果要编写测试程序,哪怕只是三四句代码,最好也重新搞一个工程,或者,假设我要修改main函数,就屏蔽掉原来的main函数,重新搞一个main函数,而不是直接在main函数内部去修改。

    并且最好做到屏蔽掉无关的代码,即使自己以为很有把握,但是一句话说得好:难得糊涂。一糊涂可就完事了,完蛋了。难得糊涂是不被允许的。

    2. 要注重加强打断点调试,遇到相关的问题,从源头开始打断点,一步步仿真执行下去。仿真不是点击一个开始允许,和一个停止运行。

      例如我遇到的问题是STM32的基于HAL库的中断问题,那么就从对应引脚的HAL库中断服务函数处开始设置第一个断电,然后一步步进去。

      MDK的各个调试按钮、各类观察窗口要熟悉。

    3. 单片机上也会遇到段错误,没有coredump咋搞? RT-Thread官网介绍的CmBacktrace可以了解一下。

     

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    [USACO07FEB]银牛派对Silver Cow Party
    道路重建
    javascript基础
    css清除浮动
    css水平居中
    块元素与行内(内嵌)元素的区别
    hook
    回调函数
    Web服务API
    Enrolment注册插件
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/14965555.html
Copyright © 2011-2022 走看看