嵌入式系统数据可视化工具Freemaster入门
本文的内容在很早之前就在本站发过一次,今天再重发一次让大家温习一遍,下次将介绍这个工具的新版本。
概述
Freemaster是恩智浦免费为用户提供的,一种在PC电脑上对MCU程序中数据可视化的工具。
使用Freemaster工具不需要在目标工程中引用同Freemaster相关的源代码,只需要将需要实时显示的变量创建为全局变量即可,即在MCU的内存中分配一个固定的地址。之后,Freemaster将通过SWD通信接口读内存中的值,并实时显示到PC机的界面上。
通过SWD接口访问内存是ARM调试的基本方式,同常用的支持在线调试的调试器工作方式相同。
以下使用一个操作实例,来说明Freemaster的使用方法。
硬件平台
本例使用恩智浦官方在中国市场推出的LPC54114-Lite开发板作为目标设备。如图1所示。
图1 LPC54114-Lite开发板
LPC54114-Lite开发板以LPC54114为主控核心,板载集成了开源的CMSIS-DAP调试器,仅用一根USB数据线,就可以实现供电、调试、串口通信的功能, 适合随身携带和展示。
Freemaster支持多种连接MCU的通信协议,如图2所示,其中包括了常用的JLink和CMSIS-DSP。比较惊喜的是,Freemaster竟然还支持OSBDM通信协议,这就意味着一些基于JM60板载调试器的Kinetis开发板也能用起来了,较新的Kinetis开发板使用基于K20主控的板载调试器,可以自由变身为CMSIS-DAP、JLink或OpenSDA(使用OSBDM通信协议)。
图2 Freemaster支持多种同MCU的通信协议
LPC54114-Lite开发板板载基于LPC11U35的调试器使用了CMSIS-DAP的固件,本文中将使用CMSIS-DAP作为样例介绍Freemaster的用法,使用其它通信协议与CMSIS-DAP类似。
创建MCU样例工程
当使用调试接口作为Freemaster与MCU的通信接口有个极为明显的好处,就是不需要在用户程序中写任何关于Freemaster代码,这就是所谓的“非侵入性”调试。
用户程序只要将需要Freemaster进行图形化的数据安排到全局变量里,让编译过程能够为这些数据分配固定地址的内存。最终Freemaster会通过调试接口,直接访问MCU的内存,从而得到可显示的数据。
以下使用NXP MCUXpresso SDK中提供的lpc_adc_burst工程作为示例程序的基础,对这个工程进行简化和改造,实现让ADC0硬件对通道0(温度传感器)和通道3(板载电位器)连续采样。采样结果被保存在全局变量数组gAdcSensingValue[]中,再通过Freemaster显示到虚拟示波器界面上。
这里节选main.c文件中的关键代码如下:
- <font size="3" face="微软雅黑">#include "fsl_common.h"
- #include "board.h"
- #include "clock_config.h"
- #include "pin_mux.h"
- #include "fsl_clock.h"
- #include "fsl_power.h"
- #include "fsl_adc.h"
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- volatile uint32_t gAdcSensingValue[2];
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- static void ADC_Configuration(void);
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /*!
- * @brief Main function
- */
- int main(void)
- {
- uint8_t ch;
- BOARD_InitBootClocks();
- BOARD_InitBootPins();
-
- BOARD_InitDebugConsole();
-
- printf("HelloWorld.\r\n");
-
- ADC_Configuration();
- ADC_DoSoftwareTriggerConvSeqA(ADC0); /* software start the conversion. */
-
- while (1)
- {
- ch = getchar();
- putchar(ch);
- }
- }</font>
复制代码- <font size="3" face="微软雅黑">void ADC_Configuration(void)
- {
- adc_config_t adcConvConfigStruct;
- adc_conv_seq_config_t adcSeqConfigStruct;
- /* Enable power. */
- POWER_DisablePD(kPDRUNCFG_PD_ADC0); /* Power on the ADC converter. */
- POWER_DisablePD(kPDRUNCFG_PD_VD7_ENA); /* Power on the analog power supply. */
- POWER_DisablePD(kPDRUNCFG_PD_VREFP_SW); /* Power on the reference voltage source. */
- POWER_DisablePD(kPDRUNCFG_PD_TEMPS); /* Power on the temperature sensor. */
-
- /* Enable clock. */
- CLOCK_EnableClock(kCLOCK_Adc0);
-
- if (!ADC_DoSelfCalibration(ADC0))
- {
- printf("ADC_DoSelfCalibration() failed.\r\n");
- while (1);
- }
-
- /* Configure the converter. */
- adcConvConfigStruct.clockMode = kADC_ClockAsynchronousMode;
- adcConvConfigStruct.clockDividerNumber = 1u;
- adcConvConfigStruct.resolution = kADC_Resolution12bit;
- adcConvConfigStruct.enableBypassCalibration = false;
- adcConvConfigStruct.sampleTimeNumber = 7u;
- ADC_Init(ADC0, &adcConvConfigStruct);
-
- /* enable the temperature sensor connected to channel 0. */
- ADC_EnableTemperatureSensor(ADC0, true);
-
- /* Configure the sequence. */
- adcSeqConfigStruct.channelMask = (1u << 0u) | (1u << 3u) ; /* channel 0 and channel 3. */
- adcSeqConfigStruct.triggerMask = 0u; /* no hardware trigger. */
- adcSeqConfigStruct.triggerPolarity = kADC_TriggerPolarityPositiveEdge;
- adcSeqConfigStruct.enableSyncBypass = false;
- adcSeqConfigStruct.enableSingleStep = false;
- adcSeqConfigStruct.interruptMode = kADC_InterruptForEachSequence; /* interrupt at the end of the sequence. */
- ADC_SetConvSeqAConfig(ADC0, &adcSeqConfigStruct);
- ADC_EnableConvSeqA(ADC0, true);
-
- /* Enable interrupts. */
- ADC_EnableInterrupts(ADC0, ADC_INTEN_SEQA_INTEN_MASK);
- NVIC_EnableIRQ(ADC0_SEQA_IRQn);</font>
复制代码- <font size="3" face="微软雅黑">void ADC0_SEQA_IRQHandler(void)
- {
- adc_result_info_t adcResultStruct;
- uint32_t flags = ADC_GetStatusFlags(ADC0);
- if (kADC_ConvSeqAInterruptFlag == (kADC_ConvSeqAInterruptFlag & flags))
- {
- ADC_GetChannelConversionResult(ADC0, 0u, &adcResultStruct);
- gAdcSensingValue[0] = adcResultStruct.result;
- ADC_GetChannelConversionResult(ADC0, 3u, &adcResultStruct);
- gAdcSensingValue[1] = adcResultStruct.result;
- }
-
- ADC_ClearStatusFlags(ADC0, flags);
-
- ADC_DoSoftwareTriggerConvSeqA(ADC0);
-
- /*
- * Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
- * exception return operation might vector to incorrect interrupt.
- */
- #if defined __CORTEX_M && (__CORTEX_M == 4U)
- __DSB();
- #endif
- }</font>
复制代码 编译生成"lpc_adc_burst.out"文件,如图3所示。然后下载并运行。
图3 在Keil中设置生成映像文件格式
注意,如果是以调试方式下载程序,切记要确保下载后再退出调试模式,然后通过开发板上的复位按键硬件复位。此时Keil要让出对调试器的占用,在接下来的操作中要把调试通信总线交给Freemaster。
创建并配置Freemaster工程
Freemaster软件在NXP官网的产品主页是:
http://www.nxp.com/support/developer-resources/software-development-tools/freemaster-run-time-debugging-tool:FREEMASTER
创建Freemaster新工程
下载、安装软件后启动Freemaster软件,默认创建了一个新工程。
右键选中左侧树形目录中的工程名,选中“属性”,在弹出对话框中编辑工程名,本例中改为“lpc54114-lite”,如图4所示。
图4 创建Freemaster新工程
此时一定要先保存工程,让工程文件有个确定的文件地址,以便于后续关联其它文件时可以使用相对路径。
配置同MCU的通信协议并导入调试程序文件
配置新的Freemaster工程:
使用CMSIS-DAP通信协议,通过LPC54114-Lite板载的CMSIS-DSP调试器同主控芯片LPC54114通信。
导入"lpc_adc_burst.out"文件,Freemaster会自动分析出变量名对应的内存地址。
操作见图5所示 图5 配置同MCU的通信协议并导入调试程序文件
这里面有两个要点:
1.指定调试程序的映像文件时最好用相对路径,否则整个文件夹被复制到别的电脑上后会识别不出来原有电脑的路径。
2.为了确保变量的地址映射被成功识别出来,可以单击“View”查看解析出来的符号表,如图6所示。
图6 Freemaster从映像文件中解析出的符号表
生成Freemaster变量表
Freemaster工程需要在内部保存一个Freemaster变量的清单,为后续步骤提供操作对象。
Freemaster变量是对目标芯片上地址的封装,同时在Freemaster内部电脑的内存中,建立了一个定期刷新的数据缓存,并自动更新缓存中变量的值。后续示波器显示的变量,是直接从这个缓存中读取的。
创建变量表的操作如图7所示。
图7 生成Freemaster变量表
注意,只有在变量表中创建的变量才能被后续创建的虚拟示波器识别出来。
创建虚拟示波器页面并设定显示通道
右键选中工程名,在弹出菜单中选中“New Scope...”,创建新的示波器页面。
在配置新示波器页面中,为新示波器页面命名并指定该示波器页面的刷新周期,在“Setup”标签页中指定显示通道,为指定通道选择变量,并可为指定通道命名。此处在一个示波器页面中支持最多8个通道,并可分组显示。
操作界面如图8所示。
图8 创建新的示波器页面并设定显示通道
用户可以在一个Freemaster工程下面创建多个示波器页面。另外Freemaster还允许创建其它可视化数据的子模块,用户可以通过JavaScript和Html语言编写网页添加到其中。
启动Freemaster工程
此时全部配置工作就已经做好了,确保MCU端程序正在运行,并且电脑上没有其它程序占用同MCU连接的调试总线,就可以启动Freemaster开始采集和显示数据了。
点击Freemaster工程窗口工具栏中的“Start/Stop Communication(Ctrl+K)”图标,之后就能看到示波器页面上有曲线出来了。如图9所示。
图9 启动Freemaster工程
图中可以看到:
一条比较平稳的红色曲线,它显示的是变量gAdcSensingValue[0]的值,也就是芯片内部温度传感器的采样值。
一条变化剧烈的绿色曲线,它显示的是变量gAdcSensingValue[1]的值,也就是从板载电位器上取得带采样值。而此时,我正在用螺丝刀旋转它以改变采样值。
总结
本文基于NXP官方的LPC54114-Lite开发板,简单介绍了数据可视化工具Freemaster软件的用法。
Freemaster可以使用常用的CMSIS-DAP调试器作为通信媒介,使用通用的SWD接口通信,无需在应用程序中进行专门的通信协议移植工作,Freemaster软件不需要“侵入”目标程序,只要将待检测变量创建为全局变量即可。
使用Freemaster可以快速实现对MCU的数据可视化,方便调试。
另外,Freemaster具有非常丰富的功能和强大的可扩展性,例如,可以自动记录数据并导出到多种常用的数据文件格式,可以支持JavaScript和Html语言编程的网页,定制显示页面。这些功能读者在基于本文入门Freemaster软件后继续发掘。
作者:苏勇 文章出处:恩智浦MCU加油站
|