一路向北lm 发表于 2020-9-30 16:58

基于PendSV 双任务时间片切换

// 定义任务
um_task task1;      //任务1
um_task task2;      //任务2
um_task task_idle;//空闲任务

// 定义任务堆栈
um_stacktask1_stack;
um_stacktask2_stack;
um_stacktask_idle_stack;



um_task *CurrentTask,*NextTask;
um_task *TaskTable;


void task1_thread(void *param);
void task2_thread(void *param);
void TaskInit(um_task *task,void(*entry)(void*),void *param,unsigned int *task_tack);
void Um_TaskSched();
void ProductPendSV();


一路向北lm 发表于 2020-9-30 16:59

// 任务调度
void Um_TaskSched()
{
if(CurrentTask == TaskTable)
        {
          if(TaskTable->DelayTicks == 0)
                                NextTask = TaskTable;
                        else if(TaskTable->DelayTicks == 0)
                                NextTask = TaskTable;
                        elsereturn;
        }
        else
        {
          if(CurrentTask == TaskTable)
                        {
                                if(TaskTable->DelayTicks == 0)
                                        NextTask = TaskTable;
                                else if(CurrentTask->DelayTicks != 0)
                                        NextTask = TaskTable;
                          
                        }
                        else if(CurrentTask == TaskTable)
                        {
                          if(TaskTable->DelayTicks == 0)
                                        NextTask = TaskTable;
                                else if(CurrentTask->DelayTicks != 0)
                                        NextTask = TaskTable;
                        }
        }
                 
        ProductPendSV();
}

一路向北lm 发表于 2020-9-30 16:59

// 设置Systick 中断定时
void SetSysTickPeriod(unsigned int ms)
{
       SysTick->LOAD = ms * SystemCoreClock/1000 -1;
       NVIC_SetPriority(SysTick_IRQn,(1<<__NVIC_PRIO_BITS)-1);
       SysTick->VAL = 0;
       SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;
       

}

一路向北lm 发表于 2020-9-30 17:01

// Systick 中断函数
void SysTick_Handler()
{
   int i;
   for(i=0;i<2;i++)
   {
      if(TaskTable->DelayTicks >0)
                        {
                           TaskTable->DelayTicks--;
                        }
   }       
       Um_TaskSched();
}

一路向北lm 发表于 2020-9-30 17:02

// 任务延时函数
void TaskDelay(unsigned int delay)
{
CurrentTask->DelayTicks = delay;
        Um_TaskSched();
}

一路向北lm 发表于 2020-9-30 17:03

// 任务1 任务2 空闲任务 初始化任务
unsigned char flag1,flag2;
void task1_thread(void *param)
{
       SetSysTickPeriod(10);
        while(1)
        {
           flag1 = 1;
           TaskDelay(10);
           flag1 = 0;
           TaskDelay(10);               
        }       
}
void task2_thread(void *param)
{
        while(1)
        {
           flag2 = 1;
           TaskDelay(10);
           flag2 = 0;
           TaskDelay(10);
        }       
}
void idel_thread(void *param)
{
       
        while(1)
        {
          
        }       
}

void FirstTask()
{
        __set_PSP(0);
ProductPendSV();
}

一路向北lm 发表于 2020-9-30 17:03

主函数

int main()
{

       
   TaskInit(&task1,task1_thread,(void*)1234,&task1_stack);
       TaskInit(&task2,task2_thread,(void*)5678,&task2_stack);
       TaskInit(&task_idle,idel_thread,(void*)0023,&task_idle_stack);
       
       TaskTable = &task1;
       TaskTable = &task2;
       TaskTable = &task_idle;
       
       NextTask = TaskTable;
       FirstTask();
               
}

一路向北lm 发表于 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;
}

一路向北lm 发表于 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);
}

一路向北lm 发表于 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,
       STR R0,

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

QuakeGod 发表于 2020-10-3 12:38

不错
页: [1]
查看完整版本: 基于PendSV 双任务时间片切换