woshi_ziyu
发表于: 2022-9-6 11:47:46 | 显示全部楼层

本篇文章主要介绍了如何使用VisualGDB构建、调试和探索无线STM32WL55 微控制器的示例项目。我们将展示如何克隆STM32WL55 SDK中包含的LocalNetwork示例,对其进行调整以启用调试,并修复导致其开箱即用的崩溃问题。


LocalNetwork示例由2个项目组成:发送周期性信标事件的集中器和响应它们的传感器。为了学习本教程,您需要两块NUCLEO-WL55JC1开发板,因为STM32WL55 SDK 1.0仅包含此类开发板的示例。


1.  启动Visual Studio,然后打开VisualGDB Embedded Project Wizard:

01-newprj-2.png

2.  为第一个项目选择一个名称和位置。请注意,由于我们使用两个开发板,因此需要创建两个单独的项目:

02-name.png

3.  在下一页上,选择“Create a new project -> Embedded Application -> Advanced CMake”:

03-app.png

4.  选择ARM工具链并选择STM32WL55JC器件。点击“Install”,自动下载安装STM32WL55 SDK:

04-install.png

5.  现在SDK已安装,您可以继续使用器件的默认设置:

05-device.png

6.  STM32WL55 BSP包含大量从原始SDK衍生的示例。您可以通过选择下一页顶部的“STM32CubeMX Samples”来查看它们。当我们第一次创建集中器项目时,选择LocalNetwork_Concentrator并按“下一步”继续:

06-sample.png

7.  将您的开发板连接到USB端口并等待VisualGDB识别它。请注意,编程到板上的默认固件通常会进入低功耗模式,从而阻止调试器连接到它。为了避免这种情况,请确保选中“connect under reset”复选框:

07-debug.png

8.  点击“Finish”创建项目。创建完成后,您可以通过按Ctrl-Shift-B来构建它:

08-built.png

9.  尝试按F5运行项目。 VisualGDB将在main()中显示“Signal 0”,OpenOCD将报告JTAG状态错误。这实际上意味着与开发板的JTAG/SWD通信在main()中的初始断点之后丢失:

09-sig0.png

10.  发生这种情况是因为开发板进入睡眠模式,禁用了调试器相关的逻辑。您可以通过将代码资源管理器切换到全局视图来跟踪此代码的位置,将详细信息配置为仅显示Outgoing Calls,多次按下“全部展开”按钮,然后搜索“sleep”:

10-sleep.png

这将指向DBG_Init ()函数检查DEBUGGER_ON宏。

11.  按F12进入DEBUGGER_ON的定义并将其从0更改为1。请注意,这会使编译的固件变大,并会大大增加功耗:

11-debug.png

12.  除非您通过COM端口明确请求,否则Concentrator项目不会开始发送信标数据包。为此,请将原始终端(需要自定义版本)配置为以9600位/秒的速度连接到ST-Link端口,或使用任何其他终端程序:

12-com.png

13.  现在您可以再次运行该项目,通过COM端口发送“AT+BEACON_ON”命令并确认板子响应“OK”:

13-beacon.png

警告:为了符合您当地的射频频谱规定,您可能需要设置设备区域通过单独的AT命令。有关详细信息,请参阅项目目录中的 readme.txt 文件。

14.  现在我们将为第二块开发板创建另一个项目。让第一个项目保持运行并启动另一个Visual Studio实例。选择第二个项目的名称和位置:

14-newsensor.png

15.  选择相同的项目类型和工具链,但这次在Sample Selection页面上选择LocalNetwork_Sensor:

15-prj.png

16.  在Debug Method页面记下第一块板的序列号。然后,插入第二个,并选择新出现的ST-Link作为调试方法:

16-dbg2.png

不要忘记勾选“Connect under reset”复选框,否则无法调试!

17.  按照与之前相同的步骤启用DEBUGGER_ON宏,然后构建并运行项目:

17-debugger_on.png

18.  集中器项目将显示部分AT+RCV消息并停止响应。按Debug->Break All可以看到代码实际上卡在了HardFault_Handler()中:

18-stop.png

19.  调用堆栈不会很有意义,表明内存损坏错误。要追踪它,请在源代码中搜索“AT+RCV”,并在输出它的行处设置断点。然后,重新启动集中器,发出初始AT命令,最后重新启动传感器开发板:

19-toobig.png

如果您单步执行输出AT+RCV消息的CONC_Report_RCV()函数,您会注意到它调用memcpy()来设置数据变量不验证有效载荷大小。从SDK 1.0版本开始,它会导致尝试将20个字节复制到一个3字节变量中并覆盖堆栈中保存的寄存器地址。

20.  您可以使用调用堆栈视图发现20的值是通过从通过SUBGRF_GetPayload()接收的有效负载中减去6得出的:

20-size.png

21.  在传感器方面,这对应于设置为默认值的data_lim字段,并且永远不会被覆盖。您可以使用Find References命令 (Shift-F12) 以及Find Symbol Results窗口中的工具栏按钮来快速显示分配了变量的所有代码位置:

21-writes.png

22.  如果您在分配data_lim的两行都设置断点,第一个将在传感器准备好发送时立即触发,而第二个将永远不会触发:

22-size.png

23.  修复集中器崩溃的最简单方法是在错误的memcpy()调用之前添加大小检查:

  1. if (DataLen > sizeof(data))
  2.     DataLen = sizeof(data);
复制代码

现在您可以再次重新启动集中器,运行AT命令,启动传感器并确认成功接收到多个传感器数据包:

23-recv.png

24.  请注意,VisualGDB建议的默认项目参数不支持sprintf()中的“%hhu”说明符。您可以通过VisualGDB项目属性将C库类型从Newlib-Nano更改为Default来修复它:

24-newlib.png

25.  这将纠正AT+RCV的输出,但会增加FLASH和RAM的使用:

25-format.png


请注意,许多无线应用程序对时序至关重要,因此在断点处停止代码可能会中断通信。作为断点的替代方法,请考虑以下非侵入式调试技术:

◾    Live Watch 用于观察和绘制变量值(例如数据包计数器)

◾    带有自定义事件的实时手表,用于跟踪精确事件

◾    Live Code Coverage 用于实时查看正在运行的代码路径

◾    快速半主机作为COM端口的更快替代方案

◾    测试资源管理器,用于直接从STM32代码在开发计算机上创建二进制转储文件


您可以在我们的GitHub存储库中找到本文中显示的源代码。

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 33 | 回复: 100



手机版|

GMT+8, 2024-12-21 21:15 , Processed in 0.059875 second(s), 9 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

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