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 ...
随机推荐
- 解决Windows server 2012 R2 系统使用IIS8浏览Asp程序出现"An error occurred on the server when processing the URL"错误
进入IIS并将ASP里的“Send Error To Browser”设置为True后点击Appley保存即可 原因是IIS里的Asp设置禁用上当错误信息发送给浏览器,只要启用即可 如果没有Asp选项 ...
- Google帮助IE浏览器实现对SVG支持
可缩放矢量图形(SVG)的意识就是一个用于描述二维矢量图形的一种开放图形格式. SVG现在已经能够广泛得应用到许多的项目当中,包括KDE和维基百科等.但是 Internet Explorer浏览器的内 ...
- Linux ${} 变量内容的提取和替换功能等
[root@localhost log]# var=/dir1/dir2/file.txt 1.对变量取值 [root@localhost log]# echo ${var} /dir1/dir2/f ...
- 《tortoisegit》 Network error:Connection refused
在用tortoisegit克隆的时候,或者push的时候出现错误提示: 尝试修改:c:\windows\system32\drivers\etc\services 中的ssh端口,但是发现是22端口, ...
- .NET破解之爱奇迪(三)
本教程只能用于学习研究,不可进行任何商业用途.如有使用,请购买正版,尊重他人劳动成果和知识产权! .NET破解之爱奇迪(一) .NET破解之爱奇迪(二) 一打开软件,就看到各种注册和未注册提示信息,就 ...
- javascript代码在线测试
目前还不可用,有知道的怎么搞的,请告知我下,谢谢! alert("欢迎使用javascript在线测试工具");
- Android与WebView的同步和异步訪问机制
大家都知道.通过WebView,我们能够在Androidclient.用Web开发的方式来开发我们的应用. 假设一个应用就是单纯一个WebView.全部的逻辑都仅仅须要在网页上交互的话,那我们事实上就 ...
- 浅析JDK中ServiceLoader的源码
前提 紧接着上一篇<通过源码浅析JDK中的资源加载>,ServiceLoader是SPI(Service Provider Interface)中的服务类加载的核心类,也就是,这篇文章先介 ...
- 【Linux】cd命令
用途 cd命令的主要作用是变换目录 全称 cd的全称是Change Directory 案例 以下是一些基础的cd命令操作(酒红色字体为命令 ,蓝色字体为解释字体) [root@bigdata ~ ...
- window 10下 MySql5.7压缩包安装
步骤如下: 1. 解压缩到某位置, 在其根目录下 新建data空目录, 新建my.ini,内容如下: [mysql] default-character-set=utf8 [mysqld] port ...