zoukankan      html  css  js  c++  java
  • 【iCore4 双核心板_uC/OS-II】例程七:互斥信号量

    一、实验说明:

      在介绍互斥信号量前,我们先简单地描述一下什么是优先级反转。使用实时内核心,优先级反转问题是实时系统中出现得最多的问题。假设任务H优先级高于任务M,任务M优先级高于任务L。任务H和任务M处于挂起状态,等待某一事件发生,任务L正在运行。此时,任务L要使用共享资源。使用共享资源之前,首先必须得到该资源的信号量。任务L得到了该信号量,并开始使用该共享资源。由于任务H的优先级高,它等待的事件到来之后剥夺了任务L的CPU使用权,任务L被挂起,任务H开始运行。运行过程中任务H也要使用那个任务L正在使用着的资源,由于该资源的信号量还被任务L占用着,任务H只能进入挂起状态,等待任务L释放该信号量。任务L得以继续运行。由于任务M的优先级高于任务L,当任务M等待的事件发生后,任务M剥夺了任务L的CPU使用权并开始运行。处理它该处理的事件,直到处理完之后将CPU控制权还给任务L。任务L接着运行,直到释放那个共享资源的信号量。直到此时,由于实时内核知道有个高优先级的任务(任务H)在等待这个信号量,内核做任务切换,使任务H得到该信号量并接着运行。

      在这种情况下,任务H优先级实际上降到了任务L的优先级水平。因为任务H要等,一直等到任务L释放占有的那个共享资源。由于任务M剥夺了任务L的CPU使用权,使任务H的状况更加恶化,任务M使任务H增加了额外的延迟时间。任务H和任务M的优先级发生了反转。

      任务优先级反转是不允许出现的,因为它可能会造成不可预期的严重后果,因此uC/OS-II提供了一种特殊的二值信号量——互斥信号量,它能够顺利地解决这种现象。

    (1)任务H和任务M正在等待一个事件发生,处于挂起状态,任务L正在执行。

    (2)在某一时刻,任务L请求一个互斥信号量以能够访问一个共享资源。

    (3)任务L请求到共享资源的互斥信号量,开始访问该共享资源。

    (4)任务H等待的事件发生,由于任务H的优先级高于任务L的优先级,内核挂起了任务L开始执行任务H。

    (5)任务H开始执行。

    (6)任务H也想访问L现在正在访问着的共享资源(它想从任务L得到互斥信号量),为了尽快地让任务H请求到互斥信号量,并且在L访问共享资源过程中不再被其他中等优先级任务打断,uC/OS-II将任务L的优先级提升到任务H同等高度。

    (7)任务L继续访问共享资源,然而它现在是以任务H的优先级进行的,注意任务H还没有运行,因为它正在等待任务L释放互斥信号量,换句话说,任务H在该互斥信号量的等待列表中。

    (8)任务L完成共享资源的使用,释放掉互斥信号量 。uC/OS-II发现任务L的优先级被提高,因此将任务L的优先级降低到原来的高度。然后,uC/OS-II将释放的互斥信号量分配给正在等待的任务H。

    (9)任务H获得互斥信号量,开始访问共享资源。

    (10)任务H完成共享资源的使用,释放掉互斥信号量。

    (11)没有更高优先级的任务执行,因此任务H继续执行。

    (12)任务H完成,开始等待一个事件。这时uC/OS-II恢复当任务H或者任务L正在执行时处于就绪态的任务M。

    (13)任务M执行。

    二、实验截图:

    三、源代码下载链接:

    链接:https://pan.baidu.com/s/1qZavQpA 密码:o8p5

    四、核心代码

    /*
     * Name                : main
     * Description         : ---
     * Author              : liu.
     *
     * History
     * --------------------
     * Rev                 : 0.00
     * Date                : 07/12/2017
     * 
     * create.
     * --------------------
     */
    /*实验现象:
      打开串口工具putty.exe,终端显示此时任务AppTask1_task,AppTask2_task和AppTask3_task
      的运行状态,任务AppTask1_task请求到互斥信号量红色ARM.LED点亮,任务AppTask2_task运
      行过程中蓝色ARM.LED闪烁。
      备注:当任务AppTask1_task请求互斥态进入就绪态时,之后本应该执行的任务AppTask2_task
      (蓝色ARM.LED闪烁),由于任务AppTask3_task的优先级被提高(高于任务AppTask2_task),
      所以任务AppTask2_task就进入了就绪态(蓝色ARM.LED停止闪烁),等待任务AppTask3_task
      释放出信号量后继续执行。
      */
    int main(void)
    {
        system_clock.initialize();                               //系统时钟初始化
        led.initialize();                                        //LED初始化
        usart6.initialize(115200);                               //串口初始化
        key.initialize();
    
        OSInit(); 
    
        //UCOS初始化
        OSTaskCreate(start_task,                                 //创建开始任务
                (void*)0,                                   //任务参数
                (OS_STK*)&START_TASK_STK[START_STK_SIZE-1], //任务堆栈
                START_TASK_PRIO);                           //任务优先级
        OSStart();                                               //开启UCOS    
    }
    /*
     * Name                : start_task
     * Description         : ---
     * Author              : liu.
     *
     * History
     * --------------------
     * Rev                 : 0.00
     * Date                : 07/12/2017
     * 
     * create.
     * --------------------
     */
    void start_task(void *pdata)
    {
        INT8U      err;
        OS_CPU_SR cpu_sr;
    
        TaskMutex = OSMutexCreate(0, &err);//创建互斥信号量    
    
        OSStatInit();//初始化统计任务
    
        OS_ENTER_CRITICAL();//关中断
    
        OSTaskCreate(AppTask1_task,(void*)0,(OS_STK*)&AppTask1_TASK_STK[AppTask1_STK_SIZE-1],AppTask1_TASK_PRIO);//创建AppTask1任务
        OSTaskCreate(AppTask2_task,(void*)0,(OS_STK*)&AppTask2_TASK_STK[AppTask2_STK_SIZE-1],AppTask2_TASK_PRIO);//创建AppTask2任务
        OSTaskCreate(AppTask3_task,(void*)0,(OS_STK*)&AppTask3_TASK_STK[AppTask3_STK_SIZE-1],AppTask3_TASK_PRIO);//创建AppTask3任务
        OSTaskSuspend(OS_PRIO_SELF);//挂起start_task任务
    
        OS_EXIT_CRITICAL();//开中断
    }
    /*
     * Name                : AppTask1_task
     * Description         : ---
     * Author              : liu.
     *
     * History
     * --------------------
     * Rev                 : 0.00
     * Date                : 07/12/2017
     * 
     * create.
     * --------------------
     */
    void AppTask1_task(void *pdata)
    {
        u8 err;
    
        while(1){
            usart6.printf("x0c");                                           //清屏    
            usart6.printf("33[1;32;40m");                                  //设置字体终端为绿色
            usart6.printf("
     The Task1 is running!
    ");        
            OSTimeDlyHMSM(0,0,1,0);                                          //延时1s        
            usart6.printf("
     The Task1 is pending Mutex!
    ");
    
            /*等待一个互斥信号量*/
            OSMutexPend(TaskMutex, 0, &err);
            usart6.printf("
     The Task1 has got Mutex!
    ");
            LED_RED_ON;
            /*释放一个互斥信号量*/
            OSMutexPost(TaskMutex);
            OSTimeDlyHMSM(0,0,1,0);                                           //延时1s        
            LED_RED_OFF;
        }
    }
    /*
     * Name                : AppTask2_task
     * Description         : ---
     * Author              : liu.
     *
     * History
     * --------------------
     * Rev                 : 0.00
     * Date                : 07/12/2017
     * 
     * create.
     * --------------------
     */
    void AppTask2_task(void *pdata)
    {
        while(1){    
            usart6.printf("
     The Task2 is running!
    ");
            LED_BLUE_ON;
            OSTimeDlyHMSM(0,0,0,200);  //延时200ms
            LED_BLUE_OFF;
            OSTimeDlyHMSM(0,0,0,200);  //延时200ms
        }
    }
    /*
     * Name                : AppTask3_task
     * Description         : ---
     * Author              : liu.
     *
     * History
     * --------------------
     * Rev                 : 0.00
     * Date                : 07/12/2017
     * 
     * create.
     * --------------------
     */
    void AppTask3_task(void *pdata)
    {
        int i;
        u8 err;
    
        while(1){
            /*等待一个互斥信号量*/
            OSMutexPend(TaskMutex, 0, &err);
            usart6.printf("
     The Task3 is running!
    ");
            for(i = 0; i< 2000000; i ++){
                OS_Sched();
            }
            /*释放一个互斥信号量*/
            OSMutexPost(TaskMutex);
            OSTimeDlyHMSM(0,0,1,0);  //延时1s
        }
    }

    iCore4链接:

  • 相关阅读:
    JQuery优化之 -- 正确使用选择器
    Vue计算属性methords 与 computed 的区别
    HTML中常用字符实体
    SQL复习(w3school)笔记
    AndroidStudio中使用AndroidAnnotations时,build.gradle的配置
    JAVA的第一次作业
    input标签submit属性,用CSS控制样式时高度不好控制的解决办法
    微信小程序开发五:案例实践
    微信小程序开发四:接口
    微信小程序开发三:组件
  • 原文地址:https://www.cnblogs.com/xiaomagee/p/8430052.html
Copyright © 2011-2022 走看看