打印
[应用相关]

调度锁保护

[复制链接]
493|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
上次我们通过添加临界区保护操作来解决共享资源冲突的问题。在临界区保护的基础上我们引入了调度锁保护操作,以后在多个任务共享资源时可以直接使用调度锁保护操作。


使用特权

评论回复
沙发
dingbo95|  楼主 | 2019-6-22 14:57 | 只看该作者
01.        调度锁计数器的初始化。
添加调度锁计数器变量:uint8_t SchedLock;
添加调度锁计数器初始化函数,在该函数中对调度锁计数器变量清0操作。
void TaskSchedLockInit()
{
SchedLock = 0;
}

使用特权

评论回复
板凳
dingbo95|  楼主 | 2019-6-22 14:57 | 只看该作者
02.        调度锁上锁操作。
先进入临界区保护操作:uint32_t status; status = TaskEnterCritical();
判断调度锁计数器变量的值是否加到255,否则执行自加操作。
if(SchedLock < 255)
        {
          SchedLock++;
        }
退出临界区保护操作:TaskExitCritical(status);
void TaskSchedLockDisable()
{
  uint32_t status;
        status = TaskEnterCritical();
        if(SchedLock < 255)
        {
          SchedLock++;
        }
        TaskExitCritical(status);
}

使用特权

评论回复
地板
dingbo95|  楼主 | 2019-6-22 14:57 | 只看该作者
03.        调度锁解锁操作。
先进入临界区保护操作:uint32_t status; status = TaskEnterCritical();
判断调度锁计数器变量的值是否大于0,然后执行自减操作,调度锁计数器变量为0时调用调度函数才开始切换任务。
if(SchedLock > 0)
        {
                if(--SchedLock == 0)
                {
                  umTaskSched();
                }          
        }
退出临界区保护操作:TaskExitCritical(status);
void TaskSchedLockEnable()
{
  uint32_t status;
        status = TaskEnterCritical();
        if(SchedLock > 0)
        {
                if(--SchedLock == 0)
                {
                  umTaskSched();
                }          
        }
        TaskExitCritical(status);
}

使用特权

评论回复
5
dingbo95|  楼主 | 2019-6-22 14:57 | 只看该作者
在任务调度函数中添加判断调度锁计数器变量是否大于0,即是判断调度器是否上锁,如果上锁直接退出,解锁时再进行任务切换。
//任务调度器
void umTaskSched()
{
        uint32_t status;
        status = TaskEnterCritical();
        if(SchedLock >0)  //判断调度器是否上锁
        {
                TaskExitCritical(status);
          return ;
        }
   if(currentTask == taskTable[2])//如果当前任务是空闲任务
         {
                         if(taskTable[0]->DelayTicks == 0)//如果任务1的延时完毕
                         {
                                 nextTask = taskTable[0]; //切换到任务1执行
                         }
                         else if(taskTable[1]->DelayTicks == 0)//如果任务2的延时完毕
                         {
                                 nextTask = taskTable[1];  //切换到任务2执行     
                         }
                         else         return;   //否则直接跳出                              
         }
        else
        {
           if(currentTask == taskTable[0])//如果当前任务是任务1
           {
                                if(taskTable[1]->DelayTicks == 0)
                                {
                                        nextTask = taskTable[1];
                                }
                                else if(currentTask->DelayTicks != 0)
                                {
                                        nextTask = taskTable[2];
                                }
                                else return;
          }
          else if(currentTask == taskTable[1])//如果当前任务是任务2
          {
                                if(taskTable[0]->DelayTicks == 0)
                                {
                                        nextTask = taskTable[0];
                                }
                                else if(currentTask->DelayTicks != 0)
                                {
                                        nextTask = taskTable[2];
                                }
                                else return;
          }
        }         
         umTaskSwitch();
}

使用特权

评论回复
6
dingbo95|  楼主 | 2019-6-22 14:58 | 只看该作者
下面进行一个小测试,该测试时在上一个工程上直接进行,暂时不加入调度锁,在没有加入调度锁时任务1和任务2直接访问共享资源,看会发生什么问题,在加入调度锁时任务1和任务2访问共享资源是否会恢复正常呢?

使用特权

评论回复
7
dingbo95|  楼主 | 2019-6-22 14:58 | 只看该作者
首先用于测试的全局变量uint32_t类型  SchedLockTestCount

使用特权

评论回复
8
dingbo95|  楼主 | 2019-6-22 14:58 | 只看该作者
在任务1 函数中我们对SchedLockTestCount进行一下操作,故意在触发任务调度的延时TaskDelay(10)之后对SchedLockTestCount重新赋值。

使用特权

评论回复
9
dingbo95|  楼主 | 2019-6-22 14:58 | 只看该作者
在任务2函数中我们只对SchedLockTestCount变量进行自加操作。

使用特权

评论回复
10
dingbo95|  楼主 | 2019-6-22 14:59 | 只看该作者
开始Debug进行测试,在Count1 = SchedLockTestCount处放置断点,全速运行到此处,此时SchedLockTestCount的值为0

使用特权

评论回复
11
dingbo95|  楼主 | 2019-6-22 14:59 | 只看该作者
接着F11  在执行TaskDelay(10)时被切换到task2任务中执行。

使用特权

评论回复
12
dingbo95|  楼主 | 2019-6-22 15:00 | 只看该作者
接着F11,task2任务中将会对SchedLockTestCount自加1

使用特权

评论回复
13
dingbo95|  楼主 | 2019-6-22 15:00 | 只看该作者
在Count1++处设置断点,全速运行,tsak1延时完毕会切换到tsak1中来。

使用特权

评论回复
14
dingbo95|  楼主 | 2019-6-22 15:00 | 只看该作者
F11单步运行,tsak1中对Count1++操作将值再传递给SchedLockTestCount,SchedLockTestCount的值改为1,显然Count1的值不受tsak2中SchedLockTestCount++ 的影响,也就是说tsak2中SchedLockTestCount++ 的操作被遗弃了。

使用特权

评论回复
15
dingbo95|  楼主 | 2019-6-22 15:01 | 只看该作者
为了解决这个问题,我们将任务调度锁加入到共享资源的代码区域,在任务1中加入调度锁上锁和解锁函数。

使用特权

评论回复
16
dingbo95|  楼主 | 2019-6-22 15:01 | 只看该作者
同样的在任务2中也加入调度锁上锁和解锁函数。

使用特权

评论回复
17
dingbo95|  楼主 | 2019-6-22 15:01 | 只看该作者
初始化任务调度锁函数,即是将 SchedLock的值设为0

使用特权

评论回复
18
dingbo95|  楼主 | 2019-6-22 15:02 | 只看该作者
写不完的程序和代码,疲倦还剩下黑眼圈,又要开始debug!!!加上任务调度锁后看下会不会发生奇迹。同样在task1中的TaskSchedLockDisable()处设置断点。

使用特权

评论回复
19
dingbo95|  楼主 | 2019-6-22 15:02 | 只看该作者
接下来单步执行,SchedLockTestCount的值会Count1赋值为1,由于加入了任务调度锁,TaskDelay(10)不会触发任务切换,task1会一直执行到任务调度锁解锁。

使用特权

评论回复
20
dingbo95|  楼主 | 2019-6-22 15:02 | 只看该作者
在执行任务调度锁解锁后,程序会被切换到任务2函数中。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

1197

帖子

5

粉丝