0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

无线MCU调试技巧汇总

jf_pJlTbmA9 来源:恩智浦MCU加油站 作者:恩智浦MCU加油站 2023-10-17 14:56 次阅读

对于初次接触无线MCU产品的人来说,拿到恩智浦的SDK后肯定需要一段时间适应,其实无线MCU也是MCU,只是在MCU的基础上增加了一个稍显复杂的射频单元,另外围绕这个射频单元增加了一些辅助组件,比如framework,FreeRtos等,当然因为射频部分具有最高的优先级,所以用户的应用必须附属在无线系统之上。

恩智浦旗下的无线MCU采用了与普通MCU相同的SDK架构,对于芯片间的切换其实是很方便的。

下面是我总结的一些开发无线MCU的经验,希望能帮到刚开始使用NXP无线MCU的同学们。

本文由如下几部分组成:

开发环境

如何开始

低功耗模式下的代码调试

空中包时序分析

Controller enhanced notifications

Timer、Event及其它资源分配

发射功率调节

Panic分析

本文所有实例基于KW38芯片讲解,但对于同一系列的其它KW3x芯片同样适用,对于使用同一SDK架构的其它无线芯片(如QN9080,QN9090)大多数适用。

开发环境

SDK版本:SDK_2_6_13_FRDM-KW38

SDK下载地址:https://mcuxpresso.nxp.com

开发板:FRDM-KW38

IDE:IAR EmbeddedWorkbench for Arm version 8.50

演示代码:https://github.com/N40E116/SDK_2_6_13_FRDM-KW38.git

如何开始

如果是第一次使用NXP的无线MCU,请先浏览SDK中的如下两个文件:

Bluetooth Low Energy Quick Start Guide.pdf

Bluetooth Low Energy Demo ApplicationsUser's Guide.pdf

本文中的所有演示操作基于项目temp_sens/freertos,之所以选择这个工程是因为它包含了低功耗和串口输出等功能,方便演示。

SDK中所有项目都包含bm和freertos两个版本,其中bm是不含RTOS的版本,FreeRtos是集成了RTOS的版本。

注意SDK中并非所有项目默认都是使能低功耗的,只有如下工程包含低功耗处理:

adv_ext_central /adv_ext_peripheral

beacon

ble_fscibb

hrs

temp_coll / temp_sens

建议在程序中增加打印复位源的功能,方便异常时的检测,实例代码如下:

void BleApp_Init(void)
{
…
    (void)Serial_Print(gAppSerMgrIf, "rnReset source:", gNoBlock_d);
    Serial_PrintDec(gAppSerMgrIf, PWR_GetSystemResetStatus());
    (void)Serial_Print(gAppSerMgrIf, "rn", gNoBlock_d);
}

如果你已经足够熟悉SDK的框架,现在准备开始开发自己的产品,强烈建议你只修改项目所在工程目录下的文件,因为其它文件是所有项目公用的,修改后可能导致其它项目的编译或运行问题,另外这样做的好处是,后续如果需要升级SDK,只需对比这些文件,进行移植即可,可大大节省升级时间。

如下是演示项目的工程目录结构,可以在这里修改或增加文件:

SDK_2_6_13_FRDM-KW38boardsfrdmkw38wireless_examplesbluetoothtemp_sens

wKgZomUD71WAOgdOAANAhBE38-8018.png

低功耗模式下的代码调试

如果直接将未经修改的temp_sens工程下载KW38中并开启调试,很快你就会收到如下错误提示,这是因为KW38进入了低功耗模式, SWD引脚失去调试功能,J-Link和KW38失去了通讯,所以调试器断开了。

wKgZomUD71aAVkw8AAB7A60zDAA896.png

要在低功耗的模式下调试代码,我们需要定时唤醒KW38,让debugger认为被调试芯片是一直在线的,我们可以让KW38一直处于广播或连接状态,这样KW38为了处理蓝牙事件会定时唤醒,从而保持住SWD连接。

另外KW38进入的低功耗模式也是有选择的,需要进入Low Power mode 1。如下是对应的代码修改:

#define gAppStartAfterReset_d           1
#define gAppDeepSleepMode_c             1

static void AdvertisingTimerCallback(void* pParam)
{
    /* Stop advertising */
//    if (mAdvState.advOn)
//    {
//        (void)Gap_StopAdvertising();
//    }
}

BleApp_ConnectionCallback() -> case gConnEvtDisconnected_c:
#if defined(cPWR_UsePowerDownMode)    (cPWR_UsePowerDownMode)
            /* UI */
            Led1Off();
            /* Go to sleep */
            SleepTimeoutSequence();
            /* restart advertising*/
            BleApp_Start();
#else

如果需要上电后或复位后马上开启广播,可使能如下宏定义:

#define gAppStartAfterReset_d     1

对于各功耗模式的介绍可参考源码文件PWR_Configuration.h。

为了快速扫描连接到设备,可以修改一下KW38的广播间隔,实例代码如下:

gapAdvertisingParameters_t gAdvParams = {
    /* minInterval */         gGapAdvertisingIntervalRangeMinimum_c, //0x12C0,
    /* maxInterval */         gGapAdvertisingIntervalRangeMinimum_c, //0x1900,
…
}

如果向已经下载过使能低功耗程序的开发板再次下载代码,有时会无法识别到芯片,此时需要按住开发板的SW3键以唤醒KW38,再点击下载按钮。

如果你现在没有调试低功耗功能,为方便开发调试,建议先禁用低功耗模式,只需修改如下宏定义:

#define cPWR_UsePowerDownMode    0

如果你的产品最终选择的功耗模式是需要MCU进入VLLSx模式的,比如low power mode:5/8/9,那么每次休眠唤醒后,需要重新初始化外设,因为从这些模式唤醒走的是reset流程,不过进入休眠后IO引脚的输出电平状态是可以保持的。

空中包时序分析

使用Ellisys的Bluetooth Tracker抓包工具,结合它的逻辑分析仪功能,我们可以抓取到蓝牙空中包和IO的时序关系,以下是我们使用该功能分析KW38功耗状态的一个实例。进入低功耗模式前拉低LED1引脚,退出低功耗模式后置高LED1。

#define gLEDSupported_d             1

#include "LED.h"
void BOARD_EnterLowPowerCb(void)
{
    Led1Off();
…
}

void BOARD_ExitLowPowerCb(void)
{
    Led1On(); 
…
}

抓取到的空中数据和LED1引脚数据如下:

wKgaomUD71iAdLOrAABq9zj_9c0521.png

聚焦到一个连接事件,我们看到KW38在空中包到来之前大约3ms唤醒了MCU,在处理完蓝牙事件后大约304us进入低功耗模式。

wKgaomUD71mAfQsgAABP7syG5PU427.png

Controller enhanced notifications

该特性可以产生额外的如下图所示蓝牙事件,但是默认只有wireless_uart使能了该功能,如果需要这些额外的event,请参考工程wireless_uart。

wKgaomUD71uAdInQAAIee00qhlE341.png

Timer、Event及其它资源分配

强烈建议用户仔细浏览一遍app_preinclude.h文件,该文件中包含了大多数项目配置信息,如果用户有增加的配置项的话,也建议放到这个文件中统一管理。

如用户需要自己创建Timer或Event的话,则如下配置参数需要对应的增加。

/* Defines number of OS events used */
#define osNumberOfEvents        5

/* Defines number of timers needed by the application */
#define gTmrApplicationTimers_c   (4 + gRepeatedAttemptsTimers_d + gAppAllowDeviceToSleepTimers_d)

app_config.c文件中包含了蓝牙的配置信息,如广播内容,安全设置,如有需要可修改该文件。

gatt_db.h文件定义了蓝牙的service,可以参考该文件增加或修改用户自定义的service。

发射功率调节

KW36系列通过如下宏定义,配置蓝牙的发射功率,但是该值对应的实际发射功率是如何计算的呢?

#define mAdvertisingDefaultTxPower_c  20
#define mConnectionDefaultTxPower_c    20

#define mDefaultTxPowerUsePaBump_c    0

在KW36的datasheet里有如下表格,有两种方法计算实际发射功率:

第一种,设置值直接对应下面表格里的行数(从行0开始),如设置TxPower_c为3,则发射功率对应的PA_POWER[5:0]= 6,对应的25℃发射功率为-15.6。

第二种,设置值为0时,PA_POWER[5:0]=1, 设置值为其它值时,PA_POWER[5:0]为二倍的设置值,然后通过下表查询对应的发射功率,如设置值为5,则PA_POWER[5:0] = 5*2=10,查询下表对应的25℃发射功率为-11.2。

wKgZomUD71yAL7ZuAAFAH5lGrJQ384.png

上表对应的是未使能最大+5dBm输出时的配置,如果使能了+5dBm输出,请参考如下表格,修改宏定义mDefaultTxPowerUsePaBump_c为1,可使能+5dBm输出。

wKgZomUD712AGa-RAAFJbLlnNrU950.png

对于KW38系列,使用如下API配置发射功率,因为输入参数即为发射功率值,所以不再需要任何转换。
bleResult_t Controller_SetTxPowerLevelDbm(int8_t level_dbm, txChannelType_t channel);

Panic分析

这里的演示会使用到Segger的J-Link Commander,所以如果你的开发板的debugger固件呈现的不是J-Link的话,你需要按照如下链接里的说明更新debugger为Segger Jlink。或者使用一个外部的J-Link或J-Trace作为debugger。

OpenSDASerial and Debug Adapter | NXP Semiconductors

Panic是Framework下的一个十分有用的调试工具,在开发调试阶段用于捕捉各种错误,SDK中默认已经在很多异常处添加了Panic处理,但是该功能默认是关闭的,需要定义如下宏打开:

#define gUsePanic_c  1

Debugger在线调试分析

如果是连着Debugger的在线调试,我们只需暂停代码即可看到panic的位置,通过panic_data中保存的数据,我们能进一步定位到出问题时的更多信息,如下是我伪造的一个panic场景。

void BleApp_Start(void)
{
…
    panic(0,(uint32_t)BleApp_Start,1,2);
}

运行代码,程序卡死在panic里,暂停程序,并查看相关信息如下:

wKgaomUD71-AVpAXAANoh6XroX0964.png

将location里的地址0x234b9输入到汇编窗口的搜索栏,可以看到出问题的函数是BleApp_Start(),当然这个也可以通过Call Stack进行查看。另外我们可以看到出问题时的一些其它参数extra1和extra2。

wKgZomUD72CAQn28AAOOCn1ya1M621.png

离线分析

很多场景下,产品是在没有连接debugger的情况下出现了异常,此时我们就需要Segger的J-Link Commander工具了,注意调试使用的debugger必须是J-Link或J-Trace等Segger公司的产品。

刚才相同的代码,下载到开发板后,断开debugger让程序全速运行,此时程序应该也运行到了panic的位置,但是我们如何查看呢?

打开J-Link Commander,并连接到KW38芯片,输入命令‘h’,此时可看到程序PC指针为0x19160。

wKgZomUD72KAae8JAALJhM7mRzk855.png

通过addr2line工具我们可以定位到出问题的代码文件为Panic.c,行数为65,addr2line的安装十分简单,大家可自行搜索下载安装。

wKgaomUD72SADhCNAAFytyp_8w4576.png

对于出问题时的其它数据,我们可以通过变量panic_data查看,通过.map文件定位到panic_data的地址为0x2000421c。

wKgZomUD72WAVVCNAABNDsoZAVs141.png

结构体panic_data的定义如下:

typedef struct
{
    panicId_t id;
    uint32_t location;
    uint32_t extra1;
    uint32_t extra2;
    uint32_t linkRegister;
    uint32_t cpsr_contents;   /* may not be used initially */
    uint8_t stack_dump[4];    /* initially just contain the contents of the LR */
} panicData_t;

使用J-Link Commander的‘mem32’命令可以读取到如下图所示的panic_data数据,通过这些数据,查找出出问题的函数地址为0x234b9, extra1为1,extra2为2。

wKgZomUD72eAT1L6AAChH8rmlPo907.png

通过addr2line命令查询到出问题的函数位于temperature_sensor.c文件的179行,即BleApp_Start()函数,再结合当时保存的extra1和extra2参数,我们大概就能分析出问题的原因了。

wKgaomUD72mAB8QCAAD3GO1o0-s195.png
wKgaomUD72qAXwVsAABQhaU3m6U930.png

该方法用于panic后的代码追踪,当然也适用于程序跳入死循环、Hardfault及其它的一些debugger离线后的异常分析。

以上是我在使用无线MCU时总结的一点经验,希望能帮到刚刚入门无线产品的同学们。

来源:恩智浦MCU加油站
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 调试
    +关注

    关注

    7

    文章

    571

    浏览量

    33857
  • 无线MCU
    +关注

    关注

    2

    文章

    31

    浏览量

    17840
收藏 人收藏

    评论

    相关推荐

    各种无线供电方式汇总

    各种无线供电方式汇总
    发表于 08-20 17:28

    无线充电电源电路设计汇总

    无线充电电源电路设计汇总
    发表于 01-16 10:22

    无线充电技术大汇总

    无线充电技术大汇总
    发表于 07-22 20:18

    JTAG调试的知识点汇总,绝对实用

    JTAG调试的知识点汇总,绝对实用
    发表于 12-24 06:09

    MCU51的串口调试工具

    MCU51的串口调试工具:本站会员 gxujjd 及sltian 推荐的Mcu51网站的免费串口调试工具。此版本使用C++Builder编写.
    发表于 01-16 11:53 126次下载

    DSP CCS初学调试问题汇总

    DSP CCS初学调试问题汇总,又需要的下来看看。
    发表于 05-06 15:32 0次下载

    Cypress16位MCU调试软件

    本软件是Cypress16位MCU调试软件,可以在线烧写程序。
    发表于 08-18 18:00 50次下载

    10个MCU常用的基础知识汇总

    本文主要介绍了10个MCU常用的基础知识汇总,具体的跟随小编一起来了解一下。
    的头像 发表于 10-05 09:39 1w次阅读

    485调试助手_基于MM32 MCU的shell调试教程(一)

    对于做linux开发的研发人员来说,大家都喜欢通过输入指令符来执行一些命令操作,如果在MCU编程过程中有一个类似linux的shell命令工具可以通过串口调试助手输入命令然后运行一些调试函数,将会
    发表于 10-28 19:36 7次下载
    485<b class='flag-5'>调试</b>助手_基于MM32 <b class='flag-5'>MCU</b>的shell<b class='flag-5'>调试</b>教程(一)

    国产超低功耗华大MCU资料汇总

    国产超低功耗华大MCU资料汇总
    发表于 12-07 19:51 24次下载
    国产超低功耗华大<b class='flag-5'>MCU</b>资料<b class='flag-5'>汇总</b>

    MCU调试接口——怎么堵住这个后门?

    对于MCU的开发工程师来说,MCU调试接口是必不可少的开发利器。透过调试接口,我们可以监视MCU的运行状态,查看或修改寄存器的数值,观察内
    发表于 02-08 15:09 0次下载
    <b class='flag-5'>MCU</b>的<b class='flag-5'>调试</b>接口——怎么堵住这个后门?

    STM32 MCU TrustZone开发调试技巧分享

    电子发烧友网站提供《STM32 MCU TrustZone开发调试技巧分享.pdf》资料免费下载
    发表于 07-28 13:35 1次下载
    STM32 <b class='flag-5'>MCU</b> TrustZone开发<b class='flag-5'>调试</b>技巧分享

    HK32MCU应用笔记(六)| HK32MCU芯片调试心得

    HK32MCU应用笔记(六)| HK32MCU芯片调试心得
    的头像 发表于 09-18 10:59 736次阅读
    HK32<b class='flag-5'>MCU</b>应用笔记(六)| HK32<b class='flag-5'>MCU</b>芯片<b class='flag-5'>调试</b>心得

    MCU调试接口——怎么堵住这个后门?

    MCU调试接口——怎么堵住这个后门?
    的头像 发表于 10-31 17:02 471次阅读
    <b class='flag-5'>MCU</b>的<b class='flag-5'>调试</b>接口——怎么堵住这个后门?

    MCU不复位调试的小技巧

    场景,也并非无路可循。原则上只要我们通过仿真器调试时,做到代码不被重新下载覆盖,MCU 不被复位,就可能保留当前程序运行的状态,让 Bug 无处藏身。 02 实现方法 首先,我们将编译完成的工程烧录到 MCU,保证
    发表于 02-26 11:30 841次阅读
    <b class='flag-5'>MCU</b>不复位<b class='flag-5'>调试</b>的小技巧