原文:http://blog.csdn.net/zcshoucsdn/article/details/54670473
最近公司搞新项目,需要使用FreeRTOS,之前只有Linux的基础(学了个皮毛),对于FreeRTOS不是非常了解。在官网转悠的时候发现了有个可视化分析工具:FreeRTOS+Trace,感觉应该不错!下载后发现其是http://percepio.com/这个网站上的东西。到官网看了看,功能确实非常强大!
不过这个东西是收费的,虽然也提供了免费版本,但是免费版功能确实太少了,只能查看各全局图,没有详细信息!不过,对于个人使用,可以申请30天的评估版License。
目前,Tracealyzer for FreeRTOS支持两种追踪模式:快照模式(Snapshot Mode)和流模式(Streaming Mode)
- 快照模式(Snapshot Mode):将追踪数据放到芯片的RAM中,然后读取出来分析显示(就相当于每次都取一次快照)
- 流模式(Streaming Mode):将追踪数据实时传送到PC机,目前Tracealyzer for FreeRTOS支持Jlink_RTT、 USB CDC、TCP/IP三种方式的流模式(官方将其称为streamports)。注意,虽然是实时传送过来的,在分析时还是需要停止后才能分析,即:不能实时分析
以上两种模式,都需要进行相关的配置,配置项目还是挺多的,详细的说明,可以参照官方的 User Manual!
仅适用于 FreeRTOS v7.3 及之后的版本
Trace源码
想要使用Tracealyzer for FreeRTOS,必须将Tracealyzer for FreeRTOS的Trace源码放到自己的项目中才可以!安装后打开软件(至于注册啥的就不说了)如下图所示
通过上图的菜单,可以定位到Tracealyzer for FreeRTOS的Trace源代码!各文件的说明见注释。
│ readme.txt
│ trcKernelPort.c
│ trcSnapshotRecorder.c
│ trcStreamingRecorder.c
├─config
│ trcConfig.h
│ trcSnapshotConfig.h
│ trcStreamingConfig.h
├─include
│ trcHardwarePort.h
│ trcKernelPort.h
│ trcPortDefines.h
│ trcRecorder.h
└─streamports
├─Jlink_RTT
│ │ Readme.txt
│ │ SEGGER_RTT.c
│ │ SEGGER_RTT_Printf.c
│ └─include
│ SEGGER_RTT.h
│ SEGGER_RTT_Conf.h
│ trcStreamingPort.h
├─TCPIP
│ │ Readme.txt
│ │ trcStreamingPort.c
│ └─include
│ trcStreamingPort.h
└─USB_CDC
│ Readme.txt
│ trcStreamingPort.c
└─include
trcStreamingPort.h
注意:
1. 官网最新的版本是3.1.0,从3.1.0开始,Trace源代码有了很大的改变,源码进行了整合,简洁了很多!
2. FreeRTOS的源码目录下,有个FreeRTOS-Plus目录,其中也有Trace源码,但是该源码也比较旧,不建议使用!
3. 网上现有资料也是针对旧源码的,和官方的User Manual不匹配。
Trace源码ARM-MDK使用
上面提到,Tracealyzer for FreeRTOS支持两种追踪模式,首先我们就要确定使用哪一种模式。Tracealyzer for FreeRTOS默认的模式是快照模式。这里,我以流模式使用Jlink_RTT方式为例来说明。使用的开发板为自己画的,芯片为STM32F205VE。在移植之前,首先确保已将FreeRTOS移植完成,并能正常运行。
首先对Trace的源代码进行一下整理(个人不喜欢在源码中放一堆实际用不到的文件),以下是我的目录结构(整个项目结构):
├─Docs // 文档
├─FreeRTOS // FreeRTOS源码的头文件和源文件
│ ├─inc
│ └─src
├─Libraries // STM32 标准外设库和CMSIS
│ ├─CMSIS // CMSIS
│ │ ├─Device
│ │ │ ├─Include
│ │ │ │ stm32f2xx.h
│ │ │ │ system_stm32f2xx.h
│ │ │ └─Source
│ │ │ startup_stm32f2xx.s
│ │ │ system_stm32f2xx.c
│ │ └─Include // ARM Cortex 核相关文件
│ └─STM32F2xx_StdPeriph_Driver // 标准外设库
│ ├─inc
│ └─src
├─MDK-ARM // MDK-ARM项目文件及其输出文件目录
│ │ E10.uvprojx
│ ├─Bin
│ ├─Listings
│ └─Objects
├─TraceRecorder // Trace的源码整理后
│ ├─inc
│ │ SEGGER_RTT.h
│ │ SEGGER_RTT_Conf.h
│ │ trcConfig.h
│ │ trcHardwarePort.h
│ │ trcKernelPort.h
│ │ trcPortDefines.h
│ │ trcRecorder.h
│ │ trcStreamingConfig.h
│ │ trcStreamingPort.h
│ │
│ └─src
│ SEGGER_RTT.c
│ trcKernelPort.c
│ trcStreamingRecorder.c
└─User // 用户自定义源码的头文件及源文件
├─inc
└─src
如果使用的是快照模式,streamports下的代码完全忽略即可。
接下来,在MDK-ARM中建立项目
(1)将各文件添加到MDK-ARM中,并且设置好MDK-ARM头文件路径(保证FreeRTOS以正常运行)
(2)打开trcConfig.h,修改如下,尤其是加注释的地方,特别注意。其他参数保持默认即可:
#ifndef TRC_CONFIG_H
#define TRC_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "trcPortDefines.h"
#include "stm32F2xx.h"
#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_ARM_Cortex_M
#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING
#define TRC_CFG_RECORDER_BUFFER_ALLOCATION TRC_RECORDER_BUFFER_ALLOCATION_STATIC
#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_9_X
#define TRC_CFG_MAX_ISR_NESTING 8
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
#include "trcSnapshotConfig.h"
#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
#include "trcStreamingConfig.h"
#endif
#ifdef __cplusplus
}
#endif
#endif /* _TRC_CONFIG_H */
(3)注意:由于默认情况下,Keil不支持C99特性,而Trace源码使用了C99特性(C99规定,变量声明可以放到函数的任何位置,而早期C规定,变量定义必须在函数开头)。在Keil中,将C99特性选中,如下图:
如果没有上面的设置,编译时,Keil报错:error: #268: declaration may not appear after executable statement in block.
(4)修改 FreeRTOSConfig.h。FreeRTOS 是一个高度可配置的系统。通常来说,我们只需要修改该配置文件即可,而不用去关注FreeRTOS的其他文件,修改后文件如下(注意图中注释部分):
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 24000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1 // 开启追踪调试
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1 // 启用一个可选函数(该函数被 Trace源码使用,默认该值为0 表示不用)
#define configKERNEL_INTERRUPT_PRIORITY 255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#if ( configUSE_TRACE_FACILITY == 1 )
#include "trcRecorder.h"
#endif
#endif /* FREERTOS_CONFIG_H */
注意:由于trcRecorder的源码是针对旧的FreeRTOS源码的,因此,configENABLE_BACKWARD_COMPATIBILITY
必须留空或者定义为 1以兼容旧的FreeRTOS源码
(5)在main函数中,启用trcRecorder中统一的API即可!启动追踪函数为 vTraceEnable(TRC_INIT)
。
注意:对于两种模式,trcRecorder中的公共API的传参是有区别的!例如:上面的vTraceEnable函数,在流模式下只能用:TRC_INIT或者TRC_START_AWAIT_HOST
至此,编译项目(我已经添加了两个任务),现在到开发板即可!打开Tracealyzer for FreeRTOS,如下,现在自己的芯片类型,然后,菜单->file->就可以开始追踪了!
我测试编译后程序未正常运行,发现heap不足,修改FreeRTOSConfig.h 中的configTOTAL_HEAP_SIZE 改大即可。使用的是 heap_4管理方案。
#define configTOTAL_HEAP_SIZE (( size_t ) ( 17 * 1024 ))