OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9071|回复: 22

FreeRTOS任务运行时间统计实验出现怪异现象

[复制链接]

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
发表于 2018-3-14 13:39:28 | 显示全部楼层 |阅读模式
1金钱
左哥:我按照第13.2讲的视频手把手跟着你的讲解在我的F1开发板(不是正点的板子)写了这个函数的实验“void vTaskGetRunTimeStats( char *pcWriteBuffer )”;是手把手跟你做的。Main函数如下所示。串口显示出了各个任务的执行时间计数以及所占CPU的百分比;但是板子上的LED1(相当于正点板子的LED0)一直常亮,不闪烁;LED2(相当于正点的LED1)我看到应该是按照1s 在闪烁。我的问题是LED1为什么不按照程序要求的每1s闪烁呢?难道是这个任务没有得到执行?
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "FreeRTOS.h"
#include "task.h"
/************************************************
ALIENTEK 战舰STM32F103开发板 FreeRTOS实验2-1
FreeRTOS任务状态与信息查询实验13.1视频-库函数版本
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司  
作者:正点原子 @ALIENTEK
************************************************/

//任务优先级
#define START_TASK_PRIO                1
//任务堆栈大小       
#define START_STK_SIZE                 128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO                2
//任务堆栈大小       
#define LED1_STK_SIZE                 50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);

//任务优先级
#define RUNTIMESTATS_TASK_PRIO                3
//任务堆栈大小       
#define RUNTIMESTATS_STK_SIZE                 256
//任务句柄
TaskHandle_t RunTimeStats_Handler;
//任务函数
void RunTimeStats_task(void *pvParameters);

char InfoBuffer[1000];

int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4         
        delay_init();                                            //延时函数初始化          
        uart_init(115200);                                        //初始化串口
        LED_Init();                                                          //初始化LED
        KEY_Init();               //初始化KEY
               
        //创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,            
                (const char*    )"led1_task",          
                (uint16_t       )LED1_STK_SIZE,
                (void*          )NULL,                               
                (UBaseType_t    )LED1_TASK_PRIO,       
                (TaskHandle_t*  )&LED1Task_Handler);   
    //创建QUERY任务
    xTaskCreate((TaskFunction_t )RunTimeStats_task,      
                (const char*    )"RunTimeStats_task",   
                (uint16_t       )RUNTIMESTATS_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )RUNTIMESTATS_TASK_PRIO,
                (TaskHandle_t*  )&RunTimeStats_Handler);         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
               
        vTaskDelay(1000);
    }
}   

//RunTimeStats任务函数
void RunTimeStats_task(void *pvParameters)
{
    u8 key,i;

                       
    while(1)
    {
                       
                        key=KEY_Scan(0);
                        if(key==WKUP_PRES)
                        {
                         vTaskGetRunTimeStats(InfoBuffer);
                               
                         printf("%s\r\n",InfoBuffer);
                               
                        }
                        i++;
                        if(i==100)
                        {
                         i=0;
                         LED2=!LED2;
                               
                        }
               
      vTaskDelay(10);
    }
}


按WKUP串口显示

按WKUP串口显示

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-14 13:45:20 | 显示全部楼层
定时器器里面的  函数还有 配置那几个宏的都是手把手跟你写的,应该没有问题,现在感觉点亮LED1的那个任务执行有问题!?左兄
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2018-3-14 14:55:47 | 显示全部楼层
LED1任务里面用串口随便打印什么数据看一下,看看发LED1是不是周期运行的
开往春天的手扶拖拉机
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-14 15:46:34 | 显示全部楼层
在LED1的任务 while(1)里添加了输出串口打印,串口显示LED1这个任务是每隔1s执行了的,但是LED1是常亮的,很奇怪,它不闪烁!?
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
   {
    LED1=!LED1;
    vTaskDelay(1000);
    printf("%s\r\n","led1_task running...");
   }
} QQ截图20180314132737-2.png

回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-14 15:48:35 | 显示全部楼层
左兄:我注意到了在LED1的任务里添加打印后,LED1这个任务的执行时间是比之前增加了。但是LED1怎么不和LED2一样的闪呢?
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-14 16:32:31 | 显示全部楼层
硬件LED1没有坏 我用跑马灯试了 。
回复

使用道具 举报

26

主题

68

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2016-7-1
在线时间
28 小时
发表于 2018-3-14 16:54:27 | 显示全部楼层
你设置的vTaskDelay()这个函数是不是1ms哦
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-14 17:02:41 | 显示全部楼层
vTaskDelay(1000) 就是延时1s
回复

使用道具 举报

26

主题

68

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2016-7-1
在线时间
28 小时
发表于 2018-3-14 18:46:50 | 显示全部楼层
wen619 发表于 2018-3-14 17:02
vTaskDelay(1000) 就是延时1s

看下你delay_init呢,如果你延时太短了,就看不见闪烁了吧
回复

使用道具 举报

6

主题

107

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
374
金钱
374
注册时间
2012-12-30
在线时间
48 小时
发表于 2018-3-15 00:01:52 | 显示全部楼层
你的LED1不是LED1
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-15 08:52:21 | 显示全部楼层
#include "delay.h"
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////          
//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"                                        //FreeRTOS使用                  
#include "task.h"
#endif
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//使用SysTick的普通计数模式对延迟进行管理(支持OS)
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/11/28
//版本:V1.8
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//修改说明
//////////////////////////////////////////////////////////////////////////////////  

static u8  fac_us=0;                                                        //us延时倍乘数                          
static u16 fac_ms=0;                                                        //ms延时倍乘数,在ucos下,代表每个节拍的ms数

extern void xPortSysTickHandler(void);

//systick中断服务函数,使用FreeRTOS时用到
void SysTick_Handler(void)
{       
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();       
    }
}

                          
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init()
{
        u32 reload;
        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟  HCLK
        fac_us=SystemCoreClock/1000000;                                //不论是否使用OS,fac_us都需要使用
        reload=SystemCoreClock/1000000;                                //每秒钟的计数次数 单位为M  
        reload*=1000000/configTICK_RATE_HZ;                        //根据configTICK_RATE_HZ设定溢出时间
                                                                                                //reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右       
        fac_ms=1000/configTICK_RATE_HZ;                                //代表OS可以延时的最少单位          

        SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;           //开启SYSTICK中断
        SysTick->LOAD=reload;                                                 //每1/configTICK_RATE_HZ秒中断一次       
        SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;           //开启SYSTICK   
}                                                                    


//延时nus
//nus:要延时的us数.       
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                                                              
void delay_us(u32 nus)
{               
        u32 ticks;
        u32 told,tnow,tcnt=0;
        u32 reload=SysTick->LOAD;                                //LOAD的值                     
        ticks=nus*fac_us;                                                 //需要的节拍数
        told=SysTick->VAL;                                        //刚进入时的计数器值
        while(1)
        {
                tnow=SysTick->VAL;       
                if(tnow!=told)
                {            
                        if(tnow<told)tcnt+=told-tnow;        //这里注意一下SYSTICK是一个递减的计数器就可以了.
                        else tcnt+=reload-tnow+told;            
                        told=tnow;
                        if(tcnt>=ticks)break;                        //时间超过/等于要延迟的时间,则退出.
                }  
        };                                                                                    
}  
//延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u32 nms)
{       
        if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
        {               
                if(nms>=fac_ms)                                                //延时的时间大于OS的最少时间周期
                {
                           vTaskDelay(nms/fac_ms);                         //FreeRTOS延时
                }
                nms%=fac_ms;                                                //OS已经无法提供这么小的延时了,采用普通方式延时   
        }
        delay_us((u32)(nms*1000));                                //普通方式延时
}

//延时nms,不会引起任务调度
//nms:要延时的ms数
void delay_xms(u32 nms)
{
        u32 i;
        for(i=0;i<nms;i++) delay_us(1000);
}







































回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-15 08:53:00 | 显示全部楼层
LED1 就是LED1
回复

使用道具 举报

23

主题

344

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2305
金钱
2305
注册时间
2017-7-6
在线时间
280 小时
发表于 2018-3-15 09:54:26 | 显示全部楼层

要么你把代码加附件,要么你去仿真看
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-15 11:01:11 | 显示全部楼层
左老师:你用战舰试过视频中手把手的代码吗?难道战舰上跑这个程序的时候点灯任务里的那个灯可以正常闪烁吗?我觉得可能是某些宏的修改或者执行vTaskGetRunTimeStats时会影响点灯任务!!!!!?????

我把移植程序下载试过了 我的板子上的两个灯可以正常闪烁,我用的也是那个移植程序里的LED文件夹,左老师。
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-15 13:43:18 | 显示全部楼层
再补充一个信息,用仿真可以观察到点灯任务好像是执行了的,但是并不是每次都是正常执行的。
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-15 20:14:56 来自手机 | 显示全部楼层
给左工看
回复

使用道具 举报

26

主题

68

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2016-7-1
在线时间
28 小时
发表于 2018-3-15 21:31:51 | 显示全部楼层

楼主搞出来没,我也在学这个,但是我这个是可以的,要不把工程文件发我,我看看,邮箱948820996@qq.com
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-16 08:54:20 | 显示全部楼层
修炼人生 发表于 2018-3-15 21:31
楼主搞出来没,我也在学这个,但是我这个是可以的,要不把工程文件发我,我看看,邮箱

谢谢,我发你。我用的不是正点的F103,是另一家的F103
回复

使用道具 举报

26

主题

68

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2016-7-1
在线时间
28 小时
发表于 2018-3-16 09:21:06 | 显示全部楼层
wen619 发表于 2018-3-16 08:54
谢谢,我发你。我用的不是正点的F103,是另一家的F103

没问题啊,我把你的程序移植到我f407上,都对的
回复

使用道具 举报

26

主题

68

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2016-7-1
在线时间
28 小时
发表于 2018-3-16 09:22:10 | 显示全部楼层
修炼人生 发表于 2018-3-16 09:21
没问题啊,我把你的程序移植到我f407上,都对的

检查你led1端口定义对不对哦
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-16 12:14:11 | 显示全部楼层
先放下吧,不管了
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
 楼主| 发表于 2018-3-16 15:15:31 | 显示全部楼层
QQ截图20180316151225.png
我拷贝过来的 timer.c里的 TIM3更新中断服务函数里有一个对LED1的操作(之前别的实验需要这么操作下),做任务统计的时候应该注释掉。犯了个低级的错误。

今天看了左老师的任务调度器的开启视频,到最后看不下去了,糊涂啊,哪位大神说说你们怎么理解的?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165369
金钱
165369
注册时间
2010-12-1
在线时间
2110 小时
发表于 2018-3-17 01:19:59 | 显示全部楼层
wen619 发表于 2018-3-16 15:15
我拷贝过来的 timer.c里的 TIM3更新中断服务函数里有一个对LED1的操作(之前别的实验需要这么操作下), ...

看文档教程。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-1-31 21:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表