[应用相关] 调度锁保护

[复制链接]
968|21
 楼主| dingbo95 发表于 2019-6-22 14:56 | 显示全部楼层 |阅读模式
上次我们通过添加临界区保护操作来解决共享资源冲突的问题。在临界区保护的基础上我们引入了调度锁保护操作,以后在多个任务共享资源时可以直接使用调度锁保护操作。


 楼主| 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);
}
 楼主| 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();
}
 楼主| dingbo95 发表于 2019-6-22 14:58 | 显示全部楼层
下面进行一个小测试,该测试时在上一个工程上直接进行,暂时不加入调度锁,在没有加入调度锁时任务1和任务2直接访问共享资源,看会发生什么问题,在加入调度锁时任务1和任务2访问共享资源是否会恢复正常呢?
 楼主| dingbo95 发表于 2019-6-22 14:58 | 显示全部楼层
首先用于测试的全局变量uint32_t类型  SchedLockTestCount
685185d0dd190b975a.png
 楼主| dingbo95 发表于 2019-6-22 14:58 | 显示全部楼层
在任务1 函数中我们对SchedLockTestCount进行一下操作,故意在触发任务调度的延时TaskDelay(10)之后对SchedLockTestCount重新赋值。
664775d0dd1a07d93f.png
 楼主| dingbo95 发表于 2019-6-22 14:58 | 显示全部楼层
在任务2函数中我们只对SchedLockTestCount变量进行自加操作。
533405d0dd1b1e2ace.png
 楼主| dingbo95 发表于 2019-6-22 14:59 | 显示全部楼层
开始Debug进行测试,在Count1 = SchedLockTestCount处放置断点,全速运行到此处,此时SchedLockTestCount的值为0
607055d0dd1cac17db.png
 楼主| dingbo95 发表于 2019-6-22 14:59 | 显示全部楼层
接着F11  在执行TaskDelay(10)时被切换到task2任务中执行。
468005d0dd1de841cf.png
 楼主| dingbo95 发表于 2019-6-22 15:00 | 显示全部楼层
接着F11,task2任务中将会对SchedLockTestCount自加1
861405d0dd1f345851.png
 楼主| dingbo95 发表于 2019-6-22 15:00 | 显示全部楼层
在Count1++处设置断点,全速运行,tsak1延时完毕会切换到tsak1中来。
126735d0dd20562a81.png
 楼主| dingbo95 发表于 2019-6-22 15:00 | 显示全部楼层
F11单步运行,tsak1中对Count1++操作将值再传递给SchedLockTestCount,SchedLockTestCount的值改为1,显然Count1的值不受tsak2中SchedLockTestCount++ 的影响,也就是说tsak2中SchedLockTestCount++ 的操作被遗弃了。
324385d0dd2173db3c.png
 楼主| dingbo95 发表于 2019-6-22 15:01 | 显示全部楼层
为了解决这个问题,我们将任务调度锁加入到共享资源的代码区域,在任务1中加入调度锁上锁和解锁函数。
925845d0dd22be8602.png
 楼主| dingbo95 发表于 2019-6-22 15:01 | 显示全部楼层
同样的在任务2中也加入调度锁上锁和解锁函数。
678525d0dd23ebfa27.png
 楼主| dingbo95 发表于 2019-6-22 15:01 | 显示全部楼层
初始化任务调度锁函数,即是将 SchedLock的值设为0
426145d0dd250bac61.png
 楼主| dingbo95 发表于 2019-6-22 15:02 | 显示全部楼层
写不完的程序和代码,疲倦还剩下黑眼圈,又要开始debug!!!加上任务调度锁后看下会不会发生奇迹。同样在task1中的TaskSchedLockDisable()处设置断点。
294085d0dd2675f888.png
 楼主| dingbo95 发表于 2019-6-22 15:02 | 显示全部楼层
接下来单步执行,SchedLockTestCount的值会Count1赋值为1,由于加入了任务调度锁,TaskDelay(10)不会触发任务切换,task1会一直执行到任务调度锁解锁。
445785d0dd2769d680.png
 楼主| dingbo95 发表于 2019-6-22 15:02 | 显示全部楼层
在执行任务调度锁解锁后,程序会被切换到任务2函数中。
823305d0dd289a5d78.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

1197

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部