CSDK程序死机了怎么办? ====================== 作者:陈之敏 时间:2020年08月15日 关键字:csdk、RDA8910、二次开发、死机调试、堆栈信息、变量数据 ## 目录 `点击这里查看所有博文 `__   最近听说有的小伙伴看了我的教程后,有一些问题都跑到官方的gitee上面去问去了。导致官方的人没搞懂问的是啥,小伙伴们也没能知道自己想要的答案。给大家造成了困扰,这里我说声抱歉。   既然出现了这个问题,我这里就声明一下,本系列教程所涉及的内容(demo)不是官方的作品。我个人觉得官方的demo内容太多太全,往往都是把一个模块内所有的东西全部放在一起。这样的话对新手不是很友好,阅读起来也比较费劲。我就把官方的部分demo进行相关的简化,并推出教程这样的话可能会对新手朋友们有一定的帮助。   有时候周末闲暇时间我也会加上一些我觉得好玩的模块在里面,这些可能在官方的demo都没有,比如cJSON、PAHO-MQTT、http-client。   这就是官方的代码仓库。 .. code:: c git clone --recursive https://gitee.com/openLuat/Luat_CSDK_Air724U.git   当然各位小伙伴在看本教程时,我建议还是使用我下面提供的仓库比较好,看完之后在迁移到官方的仓库⇧。 .. code:: c git clone --recursive https://gitee.com/chenxiahuaxu/RDA8910_CSDK.git   再看本教程过程中如果遇到了问题,可以在本人的代码仓库下面评论。也可以在本人的\ `博客 `__\ 下面评论。我要是看到的话,并且这个问题在我的能力范围的话我会尽力解答的(非官方,不要对我要求太多哦,要求太多我可能就不管啦)。 一、前言 --------   前几天米总直播iic遇到了死机的问题。哎,怎么找都找不到死在哪里。俗话说的好,解决bug的办法就是删除bug,于是乎米总就开始了删代码找bug之旅。 |在这里插入图片描述|   直播结束后,我也想到了之前我用csdk写代码的时候。那时遇到了错误,手上又没有什么有效的调试手段。只能采用\ ``printf``\ 调试大法,每一行执行结束都往串口打印一个数字,这样就能看到程序死机死在了哪里,变量信息也可以使用这个办法打印出来看。这仅限于代码量少的情况,可以尝试使用这个办法调试找bug。如果代码量多,这个办法根本就行不通。   那么今天,当你看到这篇文章的时候。这个问题又将不复存在。 .. figure:: https://img-blog.csdnimg.cn/20200725180356963.png :alt: 在这里插入图片描述 在这里插入图片描述   你猜的没错,我又带着解决办法来了,让你有办法能够轻松找到程序在什么地方发生了宕机。让你能够轻松的看到程序中的全局变量和局部变量的信息。让你找bug时不再是那么的费力! 二、编写程序 ------------ .. code:: c /*************** demo_hello_Debug ****************/ #include "iot_debug.h" #include "iot_os.h" HANDLE demo_hello_Debug_task; int demo_hello_Debug_num = 0; static void demo_hello_Debug(PVOID pParameter) { iot_debug_print("[hello]demo_hello_Debug"); //关闭看门狗,死机不会重启。默认打开 iot_debug_set_fault_mode(OPENAT_FAULT_HANG); //打开调试信息,默认关闭 iot_vat_send_cmd("AT^TRACECTRL=0,1,3\r\n", sizeof("AT^TRACECTRL=0,1,3\r\n")); volatile int n = 0; for (n = 0; n < 15; n++) { demo_hello_Debug_num++; iot_debug_print("[debug]hello world %d", n); iot_os_sleep(1000); } n++; OPENAT_assert(0, __func__, __LINE__); iot_os_delete_task(demo_hello_Debug_task); } int appimg_enter(void *param) { iot_debug_print("[hello]appimg_enter"); demo_hello_Debug_task = iot_os_create_task(demo_hello_Debug, NULL, 1024, 1, OPENAT_OS_CREATE_DEFAULT, "hello_Debug"); return 0; } void appimg_exit(void) { iot_debug_print("[hello]appimg_exit"); }   看到这段代码时,是不是感觉有点眼熟。没想到它又是helloworld,上篇博客也是,这篇博客还是。我就和helloworld杠上了! |image1|   上面的代码中用到了三个陌生的函数,它们分别是:   ``724内部自带软件看门狗,默认处于开启状态。只要程序运行异常,就会自动重启``\ 。重启后异常信息就会丢失,那就没办法读取异常的堆栈信息了,所以在调试阶段推荐使用下面的命令\ ``关闭软件看门狗``\ 。 .. code:: c /**设置软件异常时,设备模式 *@param mode: OPENAT_FAULT_RESET 重启模式 OPENAT_FAULT_HANG 调试模式 **/ - VOID ``iot_debug_set_fault_mode``\ (E_OPENAT_FAULT_MODE mode)   724默认关闭调试信息输出。一般情况下,设备运行后可以在通过串口调试助手发送AT命令\ ``AT^TRACECTRL=0,1,3``\ 来开启调试信息,每次下载后都需要重新开启。很麻烦,所以程序调试阶段推荐使用虚拟AT通道通过软件自动发送AT命令,达到自动打开调试信息输出的功能。 .. code:: c /**用来发送AT命令 *@param cmdStr: AT命令字符串 *@param cmdLen: AT命令长度 *@return TRUE: 成功 FALSE: 失败 *@note 注意,AT命令字符串cmdStr中需要包含"\r\n"或者"\r"结尾 **/ - BOOL ``iot_vat_send_cmd``\ (UINT8\* cmdStr, UINT16 cmdLen);   这一句代码就是搞事情的,它唯一的就是能让你的程序死机。本例程就是利用它创造了一个死机现场,用于演示。 .. code:: c /**assert断言 *@param condition: 断言条件 *@param func: 断言函数 *@param line: 断言位置 *@return TURE: 成功 * FALSE: 失败 **/ - VOID ``iot_debug_assert``\ ( BOOL condition, CHAR \*func,UINT32 line)   然后程序中还分别使用了一个全局变量和一个局部变量,等会死机时可以查看死机时的变量值,看看是不是符合预期。 三、下载验证 ------------   运行一切正常,没有问题。 |image2| |image3|   等等,好像觉得有什么不对,怎么打印个helloworld就没了。以前的教程到了下载验证确实就没了,但是今天才刚刚开始。 |image4|   只要等到了上面这样两个东西,那我们今天的内容就正式开始!(没有等到继续等,大概也就15s时间)。 四、启动调试 ------------ 4.1、GDB读取堆栈信息 -------------------- 4.1.1、点击\ ``Tools``\ 标签下面的\ ``GDB Launcher``\ 。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |image5| ### 4.1.2、在打开的小窗中选择相应的文件。 |image6|   ELF框内选择工程目录下\ ``~\iot_sdk_4g_8910Main\hex\Air720U_CSDK_demo_Debug_map\CSDK_RDA8910.elf``\ 文件不要选错了!!! |image7|   Mode框内选择\ ``8910 AP``\ 选项。然后点击Launch。 |image8| 4.1.3、加载app的elf文件 ~~~~~~~~~~~~~~~~~~~~~~~   正常情况你会看到这么一个界面。 |image9|   下面这几个按钮等会会用到先介绍一下。从左到右分别为:【寄存器信息】,【内 存信息】,【调用栈】,【查看全局变量】,【局部变量】,【不知道是什么】,【gdb控制台】。 |image10|   点击一下第三个按钮看看效果。看到一个\ ``OPENAT_assert``\ ,而它的上面就只有几个问号。我们的程序中调用的是\ ``iot_debug_assert``\ ,它们都有一个关键字那就是\ ``assert``\ 。实际上\ ``iot_debug_assert``\ 调用的就是底层提供的\ ``OPENAT_assert``\ 接口。那为什么调试工具能找到\ ``OPENAT_assert``\ 而找不到\ ``iot_debug_assert``\ 呢。 |image11|   上面的现象就是因为刚才加载的实际上是底层的elf文件,现在还没有加载用户编译的\ ``app.elf``\ 文件。想要加载用户的elf文件,只需要点击一下最后一个按钮(gdb控制台),然后在打开的窗口中输入下面这段命令\ ``source D:\AirJob\RDA8910CSDK\iot_sdk_4g_8910Main\start.gdb``\ 。这个命令不是固定的,需要根据你工程存放的实际位置修改。 |image12| ``注意``\ :输入之前先检查一下工程的根目录下是不是生成了一个\ ``start.gdb``\ 文件。这个文件是编译结束后\ ``自动生成的``\ ,需要在gdb控制台里面执行一下。 |image13|   输入结束后控制台会答应一段乱七八糟的数据,只要找一下里面有没有\ ``demo_Debug.c``\ 这个字段,如果找到了那就成功一半了。 |image14|   加载成功之后再次点击第三个按钮(需要将之前打开的Stack窗口关闭,重新打开)。这时发现之前的??被换成了函数。中间的一个\ ``demo_hello_Debug``\ 就是我们刚才编写的测试任务,在左边也看到了死机位置。 |image15| ## 4.2、查看变量信息   在demo中我们写了一个\ ``demo_hello_Debug_num``\ 的全局变量还有一个局部变量用来测试。这里看看能不能在死机时把变量的信息读取出来。 ### 4.2.1、通过内存信息读取(\ ``这个方法只适用于全局变量!!!`` )   打开\ ``~\iot_sdk_4g_8910Main\hex\Air720U_CSDK_demo_Debug_map\app.map``\ 文件,搜索\ ``demo_hello_Debug_num``\ 记住它前面的地址\ ``0x80f00620``\ 。\ |image16|   点击第三个按钮,输入地址信息,读取\ ``0x80f00620``\ 为首的四个字节\ ``0x0000000f``\ 。 |image17|   分析一下程序,全局变量int类型为4个字节。从0开始,在for循环内自加\ ``15``\ 次。退出循环,然后死机,那么\ ``demo_hello_Debug_num``\ 的结果为\ ``15``\ ,而\ ``15``\ 等于十六进制的\ ``0x0f``\ 。又因为int是四个字节,所以15应该等于\ ``0x0000000f``\ ,看一下是不是和上面读取到的数据一样。 .. code:: c int demo_hello_Debug_num = 0; ..... { ..... for (n = 0; n < 15; n++) { demo_hello_Debug_num++; iot_debug_print("[debug]hello world %d", n); iot_os_sleep(1000); } n++; iot_debug_assert(0, __func__, __LINE__); ..... } 4.2.2、通过Watch读取(局部变量也可以) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   有人讲,哎呦这好麻烦啊。还要看map里面的地址,自己去内存找。那么简单的方法来了。 |image18|   如上图所示,点击第4个按钮,在输入框分别输入\ ``demo_hello_Debug_num``\ 和\ ``n``\ ,最后窗口就会显示出变量的信息。 ``注意``\ :这里只能查看没有被编译器优化的局部变量值。如果被优化了那就看不了!定义变量时加上\ ``volatile``\ 关键词可防止被优化。 |image19| ### 4.2.3、简单残暴直接看   鼠标悬停在对应的变量上面稍等片刻,变量值就出来了 ̑̑ฅ( ˃̶˙ω˙˂̶ ฅ) ​​​ |image20| |image21| 不会下载的\ `点击这里 `__\ ,进去查看我的\ ``RDA8910 CSDK二次开发入门教程``\ 专题第一篇博文\ ``1、RDA8910CSDK二次开发:环境搭建``\ 里面讲了怎么下载 这里只是我的学习笔记,拿出来给大家分享,欢迎大家批评指正,本篇教程到此结束 .. |在这里插入图片描述| image:: https://img-blog.csdnimg.cn/20200725175952607.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image1| image:: https://img-blog.csdnimg.cn/20200725175411189.png .. |image2| image:: https://img-blog.csdnimg.cn/2020080120403767.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image3| image:: https://img-blog.csdnimg.cn/2020080120425334.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image4| image:: https://img-blog.csdnimg.cn/20200801204454986.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image5| image:: https://img-blog.csdnimg.cn/2020080120482662.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image6| image:: https://img-blog.csdnimg.cn/2020080120511991.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image7| image:: https://img-blog.csdnimg.cn/20200801205334162.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image8| image:: https://img-blog.csdnimg.cn/20200801215153581.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image9| image:: https://img-blog.csdnimg.cn/20200801205807969.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image10| image:: https://img-blog.csdnimg.cn/20200801210122442.png .. |image11| image:: https://img-blog.csdnimg.cn/20200801210502622.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image12| image:: https://img-blog.csdnimg.cn/20200801211140202.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image13| image:: https://img-blog.csdnimg.cn/20200801211419497.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image14| image:: https://img-blog.csdnimg.cn/2020080121155665.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image15| image:: https://img-blog.csdnimg.cn/20200801211944353.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image16| image:: https://img-blog.csdnimg.cn/20200801212701297.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image17| image:: https://img-blog.csdnimg.cn/2020080121291210.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image18| image:: https://img-blog.csdnimg.cn/20200801213926258.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image19| image:: https://img-blog.csdnimg.cn/2020080121430493.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDU3MDA4Mw==,size_16,color_FFFFFF,t_70 .. |image20| image:: https://img-blog.csdnimg.cn/20200801214810628.png .. |image21| image:: https://img-blog.csdnimg.cn/20200801214820380.png