FreeRTOS 调试方法(printf---打印任务执行情况)
以下转载自安富莱电子: http://forum.armfly.com/forum.php
本章节为大家介绍 FreeRTOS 的调试方法,这里的调试方法主要是教会大家如何获取任务的执行情况,通过获取的任务信息,可以进一步的配置和优化工程,这种方法非常实用,建议初学者必须掌握。
串口打印调试说明
很多时候,我们需要了解任务的执行状态,任务栈的使用情况以及各个任务的 CPU 使用率,这时就
需要用到官方提供的两个函数 vTaskList和vTaskGetRunTimeStats。用户就可以通过这两个函数获得任
务的执行情况。
获取了任务执行情况后,可以通过串口将其打印出来,当然,也可以通过任何其它方式将其显示出来。
本教程配套的例子统一采用串口打印的方式显示任务的执行情况。另外有一点要特别注意,这种调试方式
仅限测试目的,实际项目中不要使用,这种测试方式比较影响系统实时性。
为了获取 FreeRTOS 的任务信息,需要创建一个定时器,这个定时器的时间基准精度要高于系统时钟
节拍,这样得到的任务信息才准确。这里提供的函数仅用于测试目的,切不可将其用于实际项目,原因有两点:
1. FreeRTOS 的系统内核没有对总的计数时间做溢出保护。
2. 定时器中断是 50us 进入一次,比较影响系统性能。
这里使用的是 32 位变量来保存 50us 一次的计数值,最大支持计数时间:2^32 * 50us / 3600s =
59.6 分钟。 运行时间超过了 59.6 分钟将不准确。
具体在 FreeRTOS 的工程中如何做才可以实现任务信息获取呢?
使能相关宏定义
需要在 FreeRTOSConfig.h 文件中使能如下宏定义:
/***freertosconfig.h***/ extern volatile uint32_t ulHighFrequencyTimerTicks ;
/* Run time and task stats gathering related definitions. */
#define configUSE_TRACE_FACILITY 1
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (ulHighFrequencyTimerTicks = 0ul)
#define portGET_RUN_TIME_COUNTER_VALUE() ulHighFrequencyTimerTicks
之前的博客:
使能了宏定义之后,必要完成portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()和portGET_RUN_TIME_COUNTER_VALUE()的定义,那么我们究竟应该如何定义并使用它们呢?
freertos官方网站给了提示(点击这里查看更多):
本次实验采用上面的做法,下面还有一个例子,但是没有上面好用:
现在我使用第一种方式,STM32F429,TIM6基本定时器,产生一个50us周期的中断,进一次中断,计数器的值加1:
由于在进入
/* 第三步:启动FreeRTOS,开始多任务调度,启动成功则不返回 */
vTaskStartScheduler();(在这个函数中调用了portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() )
这个函数之前,定时器计数已经执行计数功能很多次了,为了保证我们的基石相对准确,我们在启动freertos的API函数中将其置零,这也就是为什么那个宏#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() 要这样操作这个计数器ulHighFrequencyTimerTicks=0UL;这样从任务开启时,计数器从零开始计数,而portGET_RUN_TIME_COUNTER_VALUE()是为了得到最后的计数值,可以是一个函数,返回之前用户自定义的计数器的值,也可以直接把那个计数器的值进行宏替换,在uxTaskGetSystemState()函数调用形式如下:
可以知道,我们只是需要这个计数器的值作为右值最后打印显示。(一个比较好的参考,点击这里)-(stack overflow参考)-(博客参考)。
有了前面的铺垫之后,再来说说我们的验证试验:
功能描述:按下K1按键,打印出任务信息,函数如下:
static void vTaskWork(void *pvParameters)
{ uint8_t pcWriteBuffer[]; while()
{ if (key1_flag==)
{
key1_flag=;
/* K1键按下 打印任务执行情况 */ printf("=======================================================\r\n");
printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
vTaskList((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer); printf("\r\n任务名 运行计数 使用率\r\n");
vTaskGetRunTimeStats((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer); /* 其他的键值不处理 */ } vTaskDelay();
}
}
任务一,执行打印,任务二,LED闪烁,任务三,蜂鸣器
static void AppTaskCreate(void)
{ xTaskCreate(vTaskWork, /* 任务函数 */
"vTaskWork", /* 任务名 */
, /* 任务栈大小,单位word,也就是4字节 */
NULL, /* 任务参数 */
, /* 任务优先级*/
&xHandleTaskWork ); /* 任务句柄 */ xTaskCreate( vTaskLed1, /* 任务函数 */
"vTaskLed1", /* 任务名 */
, /* 任务栈大小,单位word,也就是4字节 */
NULL, /* 任务参数 */
, /* 任务优先级*/
&xHandleTaskLED1); /* 任务句柄 */ xTaskCreate( vTaskBeep, /* 任务函数 */
"vTaskBeep", /* 任务名 */
, /* 任务栈大小,单位word,也就是4字节 */
NULL, /* 任务参数 */
, /* 任务优先级*/
&xHandleTaskBeep ); /* 任务句柄 */ }
void vTaskLed1(void *pvParameters)
{
/* 任务都是一个无限,不能返回 */
while()
{
LED3_ON;
/* 阻塞延时,单位ms */
vTaskDelay( );
LED3_OFF;
vTaskDelay( );
}
}
void vTaskBeep(void *pvParameters)
{
/* 任务都是一个无限循环,不能返回 */
while()
{
BEEP_ON;
/* 阻塞延时,单位ms */
vTaskDelay( );
BEEP_OFF;
vTaskDelay( );
}
}
基本硬件初始化:
static void BSP_Init(void)
{
/*
* STM32中断优先级分组为4,即4bit都用来表示抢占优先级,范围为:0~15
* 优先级分组只需要分组一次即可,以后如果有其他的任务需要用到中断,
* 都统一用这个优先级分组,千万不要再分组,切忌。
*/
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); /* LED 初始化 */
LED_GPIO_Config();
/*串口初始化*/
Debug_USART_Config();
/*按键初始化*/
EXTI_Key_Config();
/*定时器6初始化*/
TIMx_Configuration();
/* 蜂鸣器初始化 */
Beep_GPIO_Config();
}
关于裸机部分的外设初始化配置不再赘述。这样,下载程序之后,LED灯闪烁并且蜂鸣器鸣叫,在按下k1按键时,串口输出如下:
有了这个可以知道,我们512字的任务栈空间实在有点浪费,最后的剩余栈单位也是字。
最后,关于vTaskList((char *)&pcWriteBuffer);vTaskGetRunTimeStats((char *)&pcWriteBuffer);这个缓冲区的大小,官网说的,一个任务,大约40个字节足够,我们取50字节,所以定义的缓冲区大小uint8_t pcWriteBuffer[500];可以足够打印10个任务状态。
FreeRTOS 调试方法(printf---打印任务执行情况)的更多相关文章
- 【RTOS】基于V7开发板的最新版FreeRTOS V10.2.0程序模板,含MDK和IAR,支持串口打印任务执行情况
模板下载: 链接:https://pan.baidu.com/s/1N32Hx7cTbDoRinuzTUB3zw 提取码:6aox 1.MDK使用MDK5.26及其以上版本. 2.IAR使用IAR ...
- 【安富莱专题教程第7期】终极调试组件Event Recorder,各种Link通吃,支持时间和功耗测量,printf打印,RTX5及中间件调试
说明:1.继前面的专题教程推出SEGGER的RTT,JScope,Micrium的uC/Probe之后,再出一期终极调试方案Event Recoder,之所以叫终极解决方案,是因为所有Link通吃. ...
- Linux内核调试方法总结【转】
转自:http://my.oschina.net/fgq611/blog/113249 内核开发比用户空间开发更难的一个因素就是内核调试艰难.内核错误往往会导致系统宕机,很难保留出错时的现场.调试内核 ...
- 【转】Linux内核调试方法总结
目录[-] 一 调试前的准备 二 内核中的bug 三 内核调试配置选项 1 内核配置 2 调试原子操作 四 引发bug并打印信息 1 BUG()和BUG_ON() 2 dump_sta ...
- linux设备驱动程序第四部分:从如何定位oops对代码的调试方法,驱动线
在一个我们谈到了如何编写一个简单的字符设备驱动程序,我们不是神,编写肯定会失败的代码,在这个过程中,我们需要继续写代码调试.在普通c应用.我们经常使用printf输出信息.或者使用gdb要调试程序,然 ...
- Perl的调试方法
来源: http://my.oschina.net/alphajay/blog/52172 http://www.cnblogs.com/baiyanhuang/archive/2009/11/09/ ...
- VxWorks操作系统shell命令与调试方法总结
VxWorks下的调试手段 主要介绍在Tornado集成开发环境下的调试方法,和利用支撑定位问题的步骤.思路. 1 Tornado的调试工具 嵌入式实时操作系统VxWorks和集成开发 ...
- 【安富莱】【RL-TCPnet网络教程】第11章 RL-TCPnet调试方法
第11章 RL-TCPnet调试方法 本章节为大家讲解RL-TCPnet的调试方法,RL-TCPnet的调试功能其实就是通过串口打印实时监控运行状态.而且RL-TCPnet的调试设置比较简单 ...
- Linux内核调试方法总结
Linux内核调试方法总结 一 调试前的准备 二 内核中的bug 三 内核调试配置选项 1 内核配置 2 调试原子操作 四 引发bug并打印信息 1 BUG()和BUG_ON() 2 ...
随机推荐
- vue项目启动出现cannot GET /服务错误
出现 Cannot GET/: 控制台中并没有报错:npm run dev命令行窗口也没有报错. 原因 在网上查了一堆,发现这个问题还挺多呢,而且各个回答的解决方式都竟然有许多不同… 于是把能改的 ...
- hdu2175之找规律
汉诺塔IX Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- VC++多线程--进程间通信
1.邮槽 邮槽是windows系统提供的一种单向通信的机制,邮槽能传输的数据非常小,一般在400k左右. 创建邮槽 HANDLE CreateMailslot( LPCTSTR lpName, //指 ...
- java设计模式6--适配器模式(Adapter )
本文地址:http://www.cnblogs.com/archimedes/p/java-adapter-pattern.html,转载请注明源地址. 适配器模式(别名:包装器) 将一个类的接口转换 ...
- SSIS无法在unicode和非unicode 字符串数据类型之间转换
场景:SSIS从oracle抽到sqlserver,一个表对表到数据仓库ODS层的抽取,没有任何逻辑结果遇到问题: SSIS无法在unicode和非unicode 字符串数据类型之间转换 如下图2个字 ...
- 扩展JQUERY 表单加载JSON数据
$.fn.extend({ //表单加载json对象数据 setForm : function (jsonValue) { var obj = this; $.each(jsonValue, func ...
- UG NX9.0.0 for linux安装
自:http://vivianyw.blog.163.com/blog/static/13454742220145601415881/?latestBlog NX9.0.0 for linux安装. ...
- centos7 yum安装遇到报错:Head V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEYer
centos7 yum安装时遇到错误:Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY 无法安装时,可按如下方法解决: This mini ...
- Oracle url编码与解码
Oracle url编码与解码 CreateTime--2018年3月30日17:26:36 Author:Marydon 一.url编码 实现方式:utl_url.escape() 说明:utl ...
- mysql.ini 配置
#记录所有sql语句 log=E:/mysqllog/mysql.log #记录数据库启动关闭信息,以及运行过程中产生的错误信息 log-error=E:/mysqllog/myerror.log # ...