坚持再坚持 发表于 2023-9-18 19:26:13

在FreeRTOS中,一个软件定时器的回调函数中启动另一个软件定时器

图中只是一个大体的示意,在FreeRTOS中,一个软顶定时器的回调函数中启动另一个定时器:在一个软件定时器的回调函数中执行
if(xTimerStart(BBB, 0) == pdPASS)
{
      DEBUG_TRACE(debugLevel, "Successful start");
}
也已经打印出来了“Successful start”,说明指令已经发送给定时器的队列了,请问为什么定时器BBB到时间了,其软件回调函数没有执行?

坚持再坚持 发表于 2023-9-18 19:29:35


eric2013 发表于 2023-9-18 21:02:22

帮你测试了,我这里没问题,正常启动。



/*
*********************************************************************************************************
*
*        模块名称 : 主程序模块。
*        文件名称 : main.c
*        版    本 : V1.0
*        说    明 : 本实验主要学习FreeRTOS的定时器组
*            实验目的:
*                1. 学习FreeRTOS的定时器组
*            实验内容:
*                1. 按下按键K1可以通过串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)
*                   =================================================
*                   任务名      任务状态 优先级   剩余栈 任务序号
*                   vTaskUserIF   R       1       320   1
*                   IDLE            R       0       117   5
*                   Tmr Svc         B       2       224   6
*                   vTaskMsgPro   B       3       483   3
*                   vTaskLED      B       2       483   2
*                   vTaskStart      B       4       489   4
*                  
*                   任务名       运行计数         使用率
*                   vTaskUserIF   641             <1%
*                   IDLE            171716          99%
*                   vTaskMsgPro   0               <1%
*                   vTaskLED      0               <1%
*                   vTaskStart      1               <1%
*                   Tmr Svc         43            <1%
*                  串口软件建议使用SecureCRT(V6光盘里面有此软件)查看打印信息。
*                  各个任务实现的功能如下:
*                   vTaskTaskUserIF 任务: 接口消息处理       
*                   vTaskLED      任务: LED闪烁
*                   vTaskMsgPro   任务: 消息处理,这里用作LED闪烁
*                   vTaskStart      任务: 启动任务,也就是最高优先级任务,这里实现按键扫描
*                2. 任务运行状态的定义如下,跟上面串口打印字母B, R, D, S对应:
*                  #define tskBLOCKED_CHAR                ( 'B' )阻塞
*                  #define tskREADY_CHAR                  ( 'R' )就绪
*                  #define tskDELETED_CHAR                ( 'D' )删除
*                  #define tskSUSPENDED_CHAR          ( 'S' )挂起
*                3. 创建两个软件定时器。
*            注意事项:
*                1. 本实验推荐使用串口软件SecureCRT,要不串口打印效果不整齐。此软件在
*                   V6开发板光盘里面有。
*                2. 务必将编辑器的缩进参数和TAB设置为4来阅读本文件,要不代码显示不整齐。
*
*        修改记录 :
*                版本号    日期         作者            说明
*       V1.0    2016-03-15   Eric2013    1. ST固件库到V1.6.1版本
*                                        2. BSP驱动包V1.2
*                                        3. FreeRTOS版本V8.2.3
*
*        Copyright (C), 2016-2020, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "includes.h"


/*
**********************************************************************************************************
                                                                                        函数声明
**********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters);
static void vTaskLED(void *pvParameters);
static void vTaskMsgPro(void *pvParameters);
static void vTaskStart(void *pvParameters);
static void AppTaskCreate (void);
static void AppObjCreate (void);
static void vTimerCallback(xTimerHandle pxTimer);

/*
**********************************************************************************************************
                                                                                        变量声明
**********************************************************************************************************
*/
static TaskHandle_t xHandleTaskUserIF = NULL;
static TaskHandle_t xHandleTaskLED = NULL;
static TaskHandle_t xHandleTaskMsgPro = NULL;
static TaskHandle_t xHandleTaskStart = NULL;
static TimerHandle_t xTimers = {NULL};

/*
*********************************************************************************************************
*        函 数 名: main
*        功能说明: 标准c程序入口。
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
int main(void)
{
        /*
          在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
          这样做的好处是:
          1. 防止执行的中断服务程序中有FreeRTOS的API函数。
          2. 保证系统正常启动,不受别的中断影响。
          3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
          在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
          和cpsie i是等效的。
   */
        __set_PRIMASK(1);
       
        /* 硬件初始化 */
        bsp_Init();
       
        /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
                  目中不要使用,因为这个功能比较影响系统实时性。
           2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
        */
        vSetupSysInfoTest();
       
        /* 创建任务 */
        AppTaskCreate();

        /* 创建任务通信机制 */
        AppObjCreate();
       
    /* 启动调度,开始执行任务 */
    vTaskStartScheduler();

        /*
          如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
          heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
          #define configTOTAL_HEAP_SIZE              ( ( size_t ) ( 17 * 1024 ) )
        */
        while(1);
}

/*
*********************************************************************************************************
*        函 数 名: vTaskTaskUserIF
*        功能说明: 接口消息处理。
*        形    参: pvParameters 是在创建该任务时传递的形参
*        返 回 值: 无
*   优 先 级: 1(数值越小优先级越低,这个跟uCOS相反)
*********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters)
{
        uint8_t ucKeyCode;
        uint8_t pcWriteBuffer;

    while(1)
    {
                ucKeyCode = bsp_GetKey();
               
                if (ucKeyCode != KEY_NONE)
                {
                        switch (ucKeyCode)
                        {
                                /* K1键按下 打印任务执行情况 */
                                case KEY_DOWN_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);
                                        break;
                               
                                /* 其他的键值不处理 */
                                default:                     
                                        break;
                        }
                }
               
                vTaskDelay(20);
        }
}

/*
*********************************************************************************************************
*        函 数 名: vTaskLED
*        功能说明: LED闪烁       
*        形    参: pvParameters 是在创建该任务时传递的形参
*        返 回 值: 无
*   优 先 级: 2
*********************************************************************************************************
*/
static void vTaskLED(void *pvParameters)
{
        TickType_t xLastWakeTime;
        const TickType_t xFrequency = 200;

        /* 获取当前的系统时间 */
    xLastWakeTime = xTaskGetTickCount();
       
    while(1)
    {
                bsp_LedToggle(3);
               
                /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
      vTaskDelayUntil(&xLastWakeTime, xFrequency);
    }
}

/*
*********************************************************************************************************
*        函 数 名: vTaskMsgPro
*        功能说明: 消息处理,这里用作LED闪烁
*        形    参: pvParameters 是在创建该任务时传递的形参
*        返 回 值: 无
*   优 先 级: 3
*********************************************************************************************************
*/
static void vTaskMsgPro(void *pvParameters)
{
        TickType_t xLastWakeTime;
        const TickType_t xFrequency = 200;

        /* 获取当前的系统时间 */
    xLastWakeTime = xTaskGetTickCount();
       
    while(1)
    {
                bsp_LedToggle(4);
               
                /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
      vTaskDelayUntil(&xLastWakeTime, xFrequency);
    }
}

/*
*********************************************************************************************************
*        函 数 名: vTaskStart
*        功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
*        形    参: pvParameters 是在创建该任务时传递的形参
*        返 回 值: 无
*   优 先 级: 4
*********************************************************************************************************
*/
static void vTaskStart(void *pvParameters)
{
    while(1)
    {
                /* 按键扫描 */
                bsp_KeyScan();
      vTaskDelay(10);
    }
}
                               
/*
*********************************************************************************************************
*        函 数 名: AppTaskCreate
*        功能说明: 创建应用任务
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
static void AppTaskCreate (void)
{
    xTaskCreate( vTaskTaskUserIF,           /* 任务函数*/
               "vTaskUserIF",           /* 任务名    */
               512,                       /* 任务栈大小,单位word,也就是4字节 */
               NULL,                    /* 任务参数*/
               1,                       /* 任务优先级*/
               &xHandleTaskUserIF );/* 任务句柄*/
       
       
        xTaskCreate( vTaskLED,                    /* 任务函数*/
               "vTaskLED",                /* 任务名    */
               512,                         /* stack大小,单位word,也就是4字节 */
               NULL,                      /* 任务参数*/
               2,                         /* 任务优先级*/
               &xHandleTaskLED ); /* 任务句柄*/
       
        xTaskCreate( vTaskMsgPro,                   /* 任务函数*/
               "vTaskMsgPro",                   /* 任务名    */
               512,                             /* 任务栈大小,单位word,也就是4字节 */
               NULL,                         /* 任务参数*/
               3,                               /* 任务优先级*/
               &xHandleTaskMsgPro );/* 任务句柄*/
       
       
        xTaskCreate( vTaskStart,                   /* 任务函数*/
               "vTaskStart",                   /* 任务名    */
               512,                            /* 任务栈大小,单位word,也就是4字节 */
               NULL,                         /* 任务参数*/
               4,                            /* 任务优先级*/
               &xHandleTaskStart );   /* 任务句柄*/
}

/*
*********************************************************************************************************
*        函 数 名: AppObjCreate
*        功能说明: 创建任务通信机制
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
        uint8_t i;
        const TickType_txTimerPer = {100, 100};
static void AppObjCreate (void)
{

       
        /*
          1. 创建定时器,如果在RTOS调度开始前初始化定时器,那么系统启动后才会执行。
          2. 统一初始化两个定时器,他们使用共同的回调函数,在回调函数中通过定时器ID来区分
             是那个定时器的时间到。当然,使用不同的回调函数也是没问题的。
        */
        for(i = 0; i < 1; i++)
        {
                xTimers = xTimerCreate("Timer",          /* 定时器名字 */
                                                             xTimerPer,    /* 定时器周期,单位时钟节拍 */
                                                             pdFALSE,          /* 周期性 */
                                                             (void *) i,      /* 定时器ID */
                                                             vTimerCallback); /* 定时器回调函数 */

                if(xTimers == NULL)
                {
                        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
                }
                else
                {
                       /* 启动定时器,系统启动后才开始工作 */
                       if(xTimerStart(xTimers, 100) != pdPASS)
                       {
                               /* 定时器还没有进入激活状态 */
                       }
                }
        }
}

/*
*********************************************************************************************************
*        函 数 名: vTimerCallback
*        功能说明: 定时器回调函数
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
static void vTimerCallback(xTimerHandle pxTimer)
{
        uint32_t ulTimerID;

        configASSERT(pxTimer);

        /* 获取那个定时器时间到 */
        ulTimerID = (uint32_t)pvTimerGetTimerID(pxTimer);
       
        /* 处理定时器0任务 */
        if(ulTimerID == 0)
        {
//                bsp_LedToggle(1);
                for(i = 1; i < 2; i++)
                {
                        xTimers = xTimerCreate("Timer",          /* 定时器名字 */
                                                                           xTimerPer,    /* 定时器周期,单位时钟节拍 */
                                                                           pdFALSE,          /* 周期性 */
                                                                           (void *) i,      /* 定时器ID */
                                                                           vTimerCallback); /* 定时器回调函数 */

                        if(xTimers == NULL)
                        {
                                printf("ulTimerID000");
                                /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
                        }
                        else
                        {
                               /* 启动定时器,系统启动后才开始工作 */
                               if(xTimerStart(xTimers, 100) != pdPASS)
                               {
                                       /* 定时器还没有进入激活状态 */
                                       printf("ulTimerID1111");
                               }
                        }
                }
        }
       
        /* 处理定时器1任务 */
        if(ulTimerID == 1)
        {
                printf("ulTimerID333");
                bsp_LedToggle(2);
        }
}


/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/

坚持再坚持 发表于 2023-9-19 09:08:51

eric2013 发表于 2023-9-18 21:02
帮你测试了,我这里没问题,正常启动。




谢谢,问题解决了!是个人粗心的原因!
页: [1]
查看完整版本: 在FreeRTOS中,一个软件定时器的回调函数中启动另一个软件定时器