返回> 网站首页 

8051内核多任务切换 - 改进

yoours2023-02-02 19:18:07 阅读 1259

简介一边听听音乐,一边写写文章。

一、介绍

    上一篇多任务有个问题,如果存在局部变量则任务切换会导致变量数值混乱。

   改进在原有基础上增加堆栈操作。


二、完整示例

#include  <stdlib.h>

#include "ioCC1110.h"


// 任务个数.必须和实际任务数一至 

#define MAX_TASKS 2

// 最大栈深.最低不得少于2个,压栈用到了15个,切换函数临时用了一个。该数值尽可能大一些

#define MAX_TASK_DEP 20

// 当前活动任务号

unsigned char task_id;


//任务的栈指针

unsigned char __idata task_sp[MAX_TASKS];

// 任务堆栈

unsigned char __idata task_stack[MAX_TASKS][MAX_TASK_DEP];

// 当前活动任务号

unsigned char task_id;


// 从指定的任务开始运行任务调度.调用该宏后,将永不返回.  

#define os_start(tid) {task_id = tid,SP = task_sp[tid];}

// 任务函数指针

typedef void (*Fun)();


// 堆栈 采用后进先出方式

// 全部压栈

#define PUSH_ALL() \

    asm("push psw");\

    asm("push dpH");\

    asm("push dpl");\

    asm("push a");\

    asm("push b");\

    asm("mov a, r0");\

    asm("push a");\

    asm("mov a, r1");\

    asm("push a");\

    asm("mov a, r2");\

    asm("push a");\

    asm("mov a, r3");\

    asm("push a");\

    asm("mov a, r4");\

    asm("push a");\

    asm("mov a, r5");\

    asm("push a");\

    asm("mov a, r6");\

    asm("push a");\

    asm("mov a, r7");\

    asm("push a");


// 全部出栈

#define POP_ALL()\

    asm("pop a");\

    asm("mov r7, a");\

    asm("pop a");\

    asm("mov r6, a");\

    asm("pop a");\

    asm("mov r5, a");\

    asm("pop a");\

    asm("mov r4, a");\

    asm("pop a");\

    asm("mov r3, a");\

    asm("pop a");\

    asm("mov r2, a");\

    asm("pop a");\

    asm("mov r1, a");\

    asm("pop a");\

    asm("mov r0, a");\

    asm("pop b");\

    asm("pop a");\

    asm("pop dpl");\

    asm("pop dpH");\

    asm("pop psw");


// 任务切换函数(任务调度器)  

// 进入调度函数时,本身会操作堆栈一次

// 在函数返回时会自动将sp中保存的pc程序指针读取到pc寄存器

void task_switch()

{

    task_sp[task_id] = SP;

    if(++task_id == MAX_TASKS)

        task_id = 0;

    SP = task_sp[task_id];

}


// 这里以及PUSH_ALL、POP_ALL,使用宏定义方式是为了避免函数调用的自然堆栈操作影响实际堆栈

#define Restore_task_switch()\

        PUSH_ALL();\    // 先压栈保存现场数据

        task_switch();\

        POP_ALL(); // 恢复切换的任务现场数据


void task_load(Fun fn, unsigned char tid)

{  

        task_sp[tid] = (unsigned int)(task_stack[tid] + 1)&0xFF;

        task_stack[tid][0] = (unsigned int)fn & 0xff;  

        task_stack[tid][1] = (unsigned int)fn  >> 8;  

}  


void task1()

{  

unsigned char i;  

while(1)

{  

i++;

Restore_task_switch();

}  

}  


void task2()

{  

unsigned char j;  

while(1)

{  

j+=2;  

Restore_task_switch();

}  

}


void rtosInit()

{

// 这里装载了两个任务,因此在定义MAX_TASKS时也必须定义为2  

task_load(task1, 0);// 将task1函数装入0号槽  

task_load(task2, 1);// 将task2函数装入1号槽  

os_start(0);  

}


微信小程序扫码登陆

文章评论

1259人参与,0条评论