zoukankan      html  css  js  c++  java
  • 【STM32F407】第8章 RTX5任务优先级分配和修改

    论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=93149

    第8章   RTX5任务优先级分配和修改

    本章节主要为大家讲解RTX5任务优先级设置的注意事项,任务优先级的分配方案及其相关的一个例子,内容相对比较简单。

    8.1 任务优先级设置注意事项

    8.2 任务优先级分配方案

    8.3 任务优先级设置函数osThreadSetPriority

    8.4 任务优先级获取函数osThreadGetPriority

    8.5 实验例程说明

    8.6 总结

    8.1   RTX5支持的优先级设置

    RTX5操作系统支持的优先级设置如下:

    /// Priority values.
    typedef enum {
      osPriorityNone          =  0,         ///< No priority (not initialized).
      osPriorityIdle          =  1,         ///< Reserved for Idle thread.
      osPriorityLow           =  8,         ///< Priority: low
      osPriorityLow1          =  8+1,       ///< Priority: low + 1
      osPriorityLow2          =  8+2,       ///< Priority: low + 2
      osPriorityLow3          =  8+3,       ///< Priority: low + 3
      osPriorityLow4          =  8+4,       ///< Priority: low + 4
      osPriorityLow5          =  8+5,       ///< Priority: low + 5
      osPriorityLow6          =  8+6,       ///< Priority: low + 6
      osPriorityLow7          =  8+7,       ///< Priority: low + 7
      osPriorityBelowNormal   = 16,         ///< Priority: below normal
      osPriorityBelowNormal1  = 16+1,       ///< Priority: below normal + 1
      osPriorityBelowNormal2  = 16+2,       ///< Priority: below normal + 2
      osPriorityBelowNormal3  = 16+3,       ///< Priority: below normal + 3
      osPriorityBelowNormal4  = 16+4,       ///< Priority: below normal + 4
      osPriorityBelowNormal5  = 16+5,       ///< Priority: below normal + 5
      osPriorityBelowNormal6  = 16+6,       ///< Priority: below normal + 6
      osPriorityBelowNormal7  = 16+7,       ///< Priority: below normal + 7
      osPriorityNormal        = 24,         ///< Priority: normal
      osPriorityNormal1       = 24+1,       ///< Priority: normal + 1
      osPriorityNormal2       = 24+2,       ///< Priority: normal + 2
      osPriorityNormal3       = 24+3,       ///< Priority: normal + 3
      osPriorityNormal4       = 24+4,       ///< Priority: normal + 4
      osPriorityNormal5       = 24+5,       ///< Priority: normal + 5
      osPriorityNormal6       = 24+6,       ///< Priority: normal + 6
      osPriorityNormal7       = 24+7,       ///< Priority: normal + 7
      osPriorityAboveNormal   = 32,         ///< Priority: above normal
      osPriorityAboveNormal1  = 32+1,       ///< Priority: above normal + 1
      osPriorityAboveNormal2  = 32+2,       ///< Priority: above normal + 2
      osPriorityAboveNormal3  = 32+3,       ///< Priority: above normal + 3
      osPriorityAboveNormal4  = 32+4,       ///< Priority: above normal + 4
      osPriorityAboveNormal5  = 32+5,       ///< Priority: above normal + 5
      osPriorityAboveNormal6  = 32+6,       ///< Priority: above normal + 6
      osPriorityAboveNormal7  = 32+7,       ///< Priority: above normal + 7
      osPriorityHigh          = 40,         ///< Priority: high
      osPriorityHigh1         = 40+1,       ///< Priority: high + 1
      osPriorityHigh2         = 40+2,       ///< Priority: high + 2
      osPriorityHigh3         = 40+3,       ///< Priority: high + 3
      osPriorityHigh4         = 40+4,       ///< Priority: high + 4
      osPriorityHigh5         = 40+5,       ///< Priority: high + 5
      osPriorityHigh6         = 40+6,       ///< Priority: high + 6
      osPriorityHigh7         = 40+7,       ///< Priority: high + 7
      osPriorityRealtime      = 48,         ///< Priority: realtime
      osPriorityRealtime1     = 48+1,       ///< Priority: realtime + 1
      osPriorityRealtime2     = 48+2,       ///< Priority: realtime + 2
      osPriorityRealtime3     = 48+3,       ///< Priority: realtime + 3
      osPriorityRealtime4     = 48+4,       ///< Priority: realtime + 4
      osPriorityRealtime5     = 48+5,       ///< Priority: realtime + 5
      osPriorityRealtime6     = 48+6,       ///< Priority: realtime + 6
      osPriorityRealtime7     = 48+7,       ///< Priority: realtime + 7
      osPriorityISR           = 56,         ///< Reserved for ISR deferred thread.
      osPriorityError         = -1,         ///< System cannot determine priority or illegal priority.
      osPriorityReserved      = 0x7FFFFFFF  ///< Prevents enum down-size compiler optimization.
    } osPriority_t;

    大家设置任务优先级的时候需要调用这些指定的优先级,其中osPriorityIdle是最低优先级,供空闲任务使用,而osPriorityRealtime7是最高优先级。

    8.2   任务优先级分配方案

    对于初学者,有时候会纠结任务优先级设置为多少合适,因为任务优先级设置多少是没有标准的。对于这个问题,RTX5有一个推荐的设置标准,任务优先级设置推荐方式如下图8.1所示:

    图8.1 任务优先级分配方案

    •   IRQ任务:IRQ任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。
    •   高优先级后台任务:比如按键检测,触摸检测,USB消息处理,串口消息处理等,都可以归为这一类任务。
    •   低优先级的时间片调度任务:比如emWin的界面显示,LED数码管的显示等不需要实时执行的都可以归为这一类任务。实际应用中用户不必拘泥于将这些任务都设置为优先级1的同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。
    •   空闲任务:空闲任务是系统任务。
    •   特别注意:IRQ任务和高优先级任务必须设置为阻塞式(调用消息等待或者延迟等函数即可),只有这样高优先级任务才会释放CPU的使用权,从低优先级任务才有机会得到执行。

    这里的优先级分配方案是RTX操作系统推荐的一种方式,实际项目也可以不采用这种方法。调试出适合项目需求的才是最好的。

    8.3   任务优先级设置函数osThreadSetPriority

    函数原型:

    osStatus_t osThreadSetPriority(osThreadId_t    thread_id,

    osPriority_t   priority )   

    函数描述:

    此函数用于修改任务的优先级。

    函数参数:

    1、  第1个参数填任务的ID。

    2、  第2个参数是任务优先级。

    3、  返回值:

    •   osOK: 任务优先级修改成功。
    •   osErrorParameter: 任务ID是NULL或者优先级无效。
    •   osErrorResource: 任务处于无效状态。
    •   osErrorISR: 此函数不可以在中断服务程序里面调用。

    使用举例:

    /*
    **********************************************************************************************************
                                                 变量
    **********************************************************************************************************
    */
    static uint64_t AppTaskUserIFStk[512/8];  /* 任务栈 */
    
    /* 任务句柄 */
    OS_TID HandleTaskUserIF = NULL;
    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskChangePrio
    *    功能说明: 修改任务优先级
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    static void AppTaskDelete (void)
    {
        HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */ 
                                              1,                         /* 任务优先级 */ 
                                              &AppTaskUserIFStk,         /* 任务栈 */
                                              sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    
        if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
        {
            printf("任务AppTaskLED优先级修改成功\r\n");
        }
        else
        {
            printf("任务AppTaskLED优先级修改失败\r\n");                    
        }
        
    }

    8.4   任务优先级获取函数osThreadGetPriority

    函数原型:

    osPriority_t osThreadGetPriority (osThreadId_t thread_id )

    函数描述:

    此函数用于获取任务的优先级。

    函数参数:

    1、  第1个参数填任务的ID。

    2、  返回值:

    •   正常情况下,可以返回任务优先级。
    •   osPriorityError 任务优先级无法确定或者非法的,如果是在中断服务程序里面调用此函数也返回错误。

    使用举例:

    /*
    **********************************************************************************************************
                                                 变量
    **********************************************************************************************************
    */
    static uint64_t AppTaskUserIFStk[512/8];  /* 任务栈 */
    
    /* 任务句柄 */
    OS_TID HandleTaskUserIF = NULL;
    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskChangePrio
    *    功能说明: 修改任务优先级
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    static void AppTaskDelete (void)
    {
        HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */ 
                                              1,                         /* 任务优先级 */ 
                                              &AppTaskUserIFStk,         /* 任务栈 */
                                              sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    
        if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
        {
            printf("任务AppTaskLED优先级修改成功\r\n");
        }
        else
        {
            printf("任务AppTaskLED优先级修改失败\r\n");                    
        }
        
    }

    8.5   实验例程说明

    配套例子:

    V5-404_RTX5 Task Priority

    实验目的:

    1. 学习RTX的任务优先级设置。

    实验内容:

    1. K1键按下,设置任务优先级为osPriorityHigh。
    2. K2键按下,设置任务优先级为osPriorityHigh2。
    3. 各个任务实现的功能如下:

    AppTaskUserIF任务   : 按键消息处理。

    AppTaskLED任务      : LED闪烁。

    AppTaskMsgPro任务   : 消息处理。

    AppTaskStart任务      : 启动任务,也是最高优先级任务,这里实现按键扫描。

    osRtxTimerThread任务 : 定时器任务,暂未使用。

    串口打印信息:

    波特率 115200,数据位 8,奇偶校验位无,停止位 1。

     

    RTX配置:

    RTX配置向导详情如下:

      System Configuration

    •   Global Dynamic Memory size

    全局动态内存,这里设置为32KB。

    •   Kernel Tick Frequency

    系统时钟节拍,这里设置为1KHz。

      Thread Configuration

    •   Default Thread Stack size

    默认的任务栈大小,这里设置为1024字节

    RTX5任务调试信息:

    程序设计:

      任务栈大小分配:

    全部独立配置,没有使用RTX5默认配置:

    /*
    **********************************************************************************************************
                                                 变量
    **********************************************************************************************************
    */
    /* 任务的属性设置 */
    const osThreadAttr_t ThreadStart_Attr = 
    {
        /* 未使用 */
    //    .cb_mem = &worker_thread_tcb_1,
    //    .cb_size = sizeof(worker_thread_tcb_1),
    //    .stack_mem = &worker_thread_stk_1[0],
    //    .stack_size = sizeof(worker_thread_stk_1),
    //    .priority = osPriorityAboveNormal,
    //    .tz_module = 0
        
        .name = "osRtxStartThread",
        .attr_bits = osThreadDetached, 
        .priority = osPriorityHigh4,
        .stack_size = 2048,
    };
    
    const osThreadAttr_t ThreadMsgPro_Attr = 
    {
        .name = "osRtxMsgProThread",
        .attr_bits = osThreadDetached, 
        .priority = osPriorityHigh3,
        .stack_size = 1024,
    };
    
    const osThreadAttr_t ThreadLED_Attr = 
    {
        .name = "osRtxLEDThread",
        .attr_bits = osThreadDetached, 
        .priority = osPriorityHigh2,
        .stack_size = 512,
    };
    
    const osThreadAttr_t ThreadUserIF_Attr = 
    {
        .name = "osRtxThreadUserIF",
        .attr_bits = osThreadDetached, 
        .priority = osPriorityHigh1,
        .stack_size = 1024,
    };

      系统栈大小分配:

     

      RTX5初始化:

    /*
    *********************************************************************************************************
    *    函 数 名: main
    *    功能说明: 标准c程序入口。
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    int main (void) 
    {    
        /* HAL库,MPU,Cache,时钟等系统初始化 */
        System_Init();
    
        /* 内核开启前关闭HAL的时间基准 */
        HAL_SuspendTick();
        
        /* 内核初始化 */
        osKernelInitialize();                                  
    
        /* 创建启动任务 */
        ThreadIdStart = osThreadNew(AppTaskStart, NULL, &ThreadStart_Attr);  
    
        /* 开启多任务 */
        osKernelStart();
        
        while(1);
    }

      RTX5任务创建:

    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskCreate
    *    功能说明: 创建应用任务
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    static void AppTaskCreate (void)
    {
        ThreadIdTaskMsgPro = osThreadNew(AppTaskMsgPro, NULL, &ThreadMsgPro_Attr);  
        ThreadIdTaskLED = osThreadNew(AppTaskLED, NULL, &ThreadLED_Attr);  
        ThreadIdTaskUserIF = osThreadNew(AppTaskUserIF, NULL, &ThreadUserIF_Attr);  
    }

      四个RTX任务的实现:

    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskUserIF
    *    功能说明: 按键消息处理        
    *    形    参: 无
    *    返 回 值: 无
    *   优 先 级: osPriorityHigh1 (数值越小优先级越低,这个跟uCOS相反)
    *********************************************************************************************************
    */
    void AppTaskUserIF(void *argument)
    {
        uint8_t ucKeyCode;
    
        while(1)
        {
            ucKeyCode = bsp_GetKey();
            
            if (ucKeyCode != KEY_NONE)
            {
                switch (ucKeyCode)
                {
                    /* K1键按下,设置任务优先级为osPriorityHigh */
                    case KEY_DOWN_K1:
                        printf("K1键按下,设置任务 HandleTaskLED的优先级为osPriorityHigh\r\n");
                          osThreadSetPriority(ThreadIdTaskLED, osPriorityHigh);
    printf("任务ThreadIdTaskLED的优先级 = %d\r\n",osThreadGetPriority(ThreadIdTaskLED));
                        break;
                        
                    /* K2键按下,设置任务优先级为osPriorityHigh2 */
                    case KEY_DOWN_K2:
                        printf("K2键按下,设置任务 HandleTaskLED的优先级为osPriorityHigh2\r\n");
                        osThreadSetPriority(ThreadIdTaskLED, osPriorityHigh2);
                      printf("任务ThreadIdTaskLED的优先级 = %d\r\n", osThreadGetPriority(ThreadIdTaskLED));
                        break;
    
                    /* 其他的键值不处理 */
                    default:                     
                        break;
                }
            }
            
            osDelay(20);
        }
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskLED
    *    功能说明: LED闪烁。
    *    形    参: 无
    *    返 回 值: 无
    *   优 先 级: osPriorityHigh2 
    *********************************************************************************************************
    */
    void AppTaskLED(void *argument)
    {
        const uint16_t usFrequency = 200; /* 延迟周期 */
        uint32_t tick;
    
        /* 获取当前时间 */
        tick = osKernelGetTickCount(); 
        
        while(1)
        {
            bsp_LedToggle(2);
            /* 相对延迟 */
            tick += usFrequency;                          
            osDelayUntil(tick);
        }
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskMsgPro
    *    功能说明: 消息处理,暂时未用到。
    *    形    参: 无
    *    返 回 值: 无
    *   优 先 级: osPriorityHigh3  
    *********************************************************************************************************
    */
    void AppTaskMsgPro(void *argument)
    {
        while(1)
        {
            osDelay(10);
        }    
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: AppTaskStart
    *    功能说明: 启动任务,这里用作BSP驱动包处理。
    *    形    参: 无
    *    返 回 值: 无
    *   优 先 级: osPriorityHigh4  
    *********************************************************************************************************
    */
    void AppTaskStart(void *argument)
    {
        const uint16_t usFrequency = 1; /* 延迟周期 */
        uint32_t tick;
        
        /* 初始化外设 */
        HAL_ResumeTick();
        bsp_Init();
    
        /* 创建任务 */
        AppTaskCreate();
    
        /* 获取当前时间 */
        tick = osKernelGetTickCount(); 
        
        while(1)
        {
            /* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */
            bsp_ProPer1ms();
            
            /* 相对延迟 */
            tick += usFrequency;                          
            osDelayUntil(tick);
        }
    }

    8.6   总结

    本章节内容相对比较容易,重点是学习任务优先级分配方案,随着后面的学习,初学者需要慢慢积累这方面的经验。

    微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
  • 相关阅读:
    增强学习--值迭代
    makefile opencv的案例
    shiro拦截器处理链执行顺序
    HTTP头字段总结
    IntelliJ IDEA上创建Maven Spring MVC项目
    使用deploy命令发布jar到私服仓库nexus
    JAVA设计模式之单例模式
    java基础-I/O系统
    HTTP深入浅出 http请求
    HTTP Header 详解
  • 原文地址:https://www.cnblogs.com/armfly/p/15763163.html
Copyright © 2011-2022 走看看