搜索

[STM32] 基于PendSV 双任务时间片切换

[复制链接]
90|10
 楼主 | 2020-9-30 16:58 | 显示全部楼层 |阅读模式
  1. // 定义任务
  2. um_task task1;      //任务1
  3. um_task task2;      //任务2
  4. um_task task_idle;  //空闲任务

  5. // 定义任务堆栈
  6. um_stack  task1_stack[1024];
  7. um_stack  task2_stack[1024];
  8. um_stack  task_idle_stack[1024];



  9. um_task *CurrentTask,*NextTask;
  10. um_task *TaskTable[3];


  11. void task1_thread(void *param);
  12. void task2_thread(void *param);
  13. void TaskInit(um_task *task,void(*entry)(void*),void *param,unsigned int *task_tack);
  14. void Um_TaskSched();
  15. void ProductPendSV();
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 16:59 | 显示全部楼层
  1. // 任务调度
  2. void Um_TaskSched()
  3. {
  4.   if(CurrentTask == TaskTable[2])
  5.         {
  6.             if(TaskTable[0]->DelayTicks == 0)
  7.                                 NextTask = TaskTable[0];
  8.                         else if(TaskTable[1]->DelayTicks == 0)
  9.                                 NextTask = TaskTable[1];
  10.                         else  return;
  11.         }
  12.         else
  13.         {
  14.             if(CurrentTask == TaskTable[0])
  15.                         {
  16.                                 if(TaskTable[1]->DelayTicks == 0)
  17.                                         NextTask = TaskTable[1];
  18.                                 else if(CurrentTask->DelayTicks != 0)
  19.                                         NextTask = TaskTable[2];
  20.                           
  21.                         }
  22.                         else if(CurrentTask == TaskTable[1])
  23.                         {
  24.                           if(TaskTable[0]->DelayTicks == 0)
  25.                                         NextTask = TaskTable[0];
  26.                                 else if(CurrentTask->DelayTicks != 0)
  27.                                         NextTask = TaskTable[2];
  28.                         }
  29.         }
  30.                  
  31.         ProductPendSV();
  32. }
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 16:59 | 显示全部楼层
  1. // 设置Systick 中断定时
  2. void SetSysTickPeriod(unsigned int ms)
  3. {
  4.          SysTick->LOAD = ms * SystemCoreClock/1000 -1;
  5.          NVIC_SetPriority(SysTick_IRQn,(1<<__NVIC_PRIO_BITS)-1);
  6.          SysTick->VAL = 0;
  7.          SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  8.                    SysTick_CTRL_TICKINT_Msk   |
  9.                    SysTick_CTRL_ENABLE_Msk;
  10.        

  11. }
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 17:01 | 显示全部楼层
  1. // Systick 中断函数
  2. void SysTick_Handler()
  3. {
  4.    int i;
  5.    for(i=0;i<2;i++)
  6.    {
  7.       if(TaskTable[i]->DelayTicks >0)
  8.                         {
  9.                            TaskTable[i]->DelayTicks--;
  10.                         }
  11.    }       
  12.          Um_TaskSched();
  13. }
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 17:02 | 显示全部楼层
  1. // 任务延时函数
  2. void TaskDelay(unsigned int delay)
  3. {
  4.   CurrentTask->DelayTicks = delay;
  5.         Um_TaskSched();
  6. }
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 17:03 | 显示全部楼层
  1. // 任务1 任务2 空闲任务 初始化任务
  2. unsigned char flag1,flag2;
  3. void task1_thread(void *param)
  4. {
  5.          SetSysTickPeriod(10);
  6.         while(1)
  7.         {
  8.            flag1 = 1;
  9.            TaskDelay(10);
  10.            flag1 = 0;
  11.            TaskDelay(10);                 
  12.         }       
  13. }
  14. void task2_thread(void *param)
  15. {
  16.         while(1)
  17.         {
  18.            flag2 = 1;
  19.            TaskDelay(10);
  20.            flag2 = 0;
  21.            TaskDelay(10);
  22.         }       
  23. }
  24. void idel_thread(void *param)
  25. {
  26.        
  27.         while(1)
  28.         {
  29.           
  30.         }       
  31. }

  32. void FirstTask()
  33. {
  34.         __set_PSP(0);
  35.   ProductPendSV();
  36. }
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 17:03 | 显示全部楼层
主函数

  1. int main()
  2. {

  3.          
  4.    TaskInit(&task1,task1_thread,(void*)1234,&task1_stack[1024]);
  5.          TaskInit(&task2,task2_thread,(void*)5678,&task2_stack[1024]);
  6.          TaskInit(&task_idle,idel_thread,(void*)0023,&task_idle_stack[1024]);
  7.        
  8.          TaskTable[0] = &task1;
  9.          TaskTable[1] = &task2;
  10.          TaskTable[2] = &task_idle;
  11.        
  12.          NextTask = TaskTable[0];
  13.          FirstTask();
  14.                
  15. }
复制代码


使用特权

评论回复
 楼主 | 2020-9-30 17:03 | 显示全部楼层
//任务初始化函数
void TaskInit(um_task *task,void(*entry)(void*),void *param,um_stack *task_tack)
{
   *(--task_tack) = (unsigned long)(1<<24);
         *(--task_tack) = (unsigned long)entry;   //pc寄存器
         *(--task_tack) = (unsigned long)0x14;
         *(--task_tack) = (unsigned long)0x12;
         *(--task_tack) = (unsigned long)0x3;
         *(--task_tack) = (unsigned long)0x2;
         *(--task_tack) = (unsigned long)0x1;
         *(--task_tack) = (unsigned long)param;
       
         *(--task_tack) = (unsigned long)0x11;
         *(--task_tack) = (unsigned long)0x10;
         *(--task_tack) = (unsigned long)0x9;
         *(--task_tack) = (unsigned long)0x8;
         *(--task_tack) = (unsigned long)0x7;
         *(--task_tack) = (unsigned long)0x6;
         *(--task_tack) = (unsigned long)0x5;
         *(--task_tack) = (unsigned long)0x4;
         task->stack_addr = task_tack;
         task->DelayTicks = 0;
}

使用特权

评论回复
 楼主 | 2020-9-30 17:03 | 显示全部楼层
// 进入临界区保护
unsigned int TaskEnterCritical()
{
  unsigned int primask;
       
        primask = __get_PRIMASK();
        __disable_irq();
        return primask;
}

// 退出临界区保护
void TaskExitCritical(unsigned int status)
{
   __set_PRIMASK(status);
}

使用特权

评论回复
 楼主 | 2020-9-30 17:04 | 显示全部楼层
// PendSV异常
void ProductPendSV()
{
   *(volatile unsigned long *)NVIC_SYSPRI2 = NVIC_PENDSV_PRI;
   *(volatile unsigned long *)NVIC_INT_CTRL = NVIC_PENDSV_SET;
}       

// PendSV中断处理函数
__asm__ void PendSV_Handler(void)
{
                   
         IMPORT CurrentTask
         IMPORT NextTask
         MRS R0, PSP                   //将PSP寄存器保存到R0中
         CBZ R0,PendSVHander_nosave    //判断PSP寄存器的值是否为0 从而判断是否是
                                       //FirstTask任务触发还是umTaskSwitch()触发
         STMDB R0!,{R4-R11}
         LDR R1, = CurrentTask
         LDR R1,[R1]
         STR R0,[R1]

PendSVHander_nosave
   LDR R0, = CurrentTask     //完成了nextTask向currentTask赋值操作
   LDR R1, = NextTask
   LDR R2,[R1]   
   STR R2,[R0]        
   LDR R0,[R2]              //从currentTask取出堆栈的地址
   LDMIA R0!,{R4-R11}       //批量加载R4-R11寄存器
   MSR PSP,R0        
   ORR LR,LR,#0x04
   BX  LR         
       
}

使用特权

评论回复
| 2020-10-3 12:38 | 显示全部楼层
不错

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

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