返回> 网站首页
8051内核多任务切换
yoours2023-02-01 19:31:20
简介一边听听音乐,一边写写文章。
#include <stdlib.h>
#include "ioCC1110.h"
// 任务函数类型
typedef void (*Fun)();
// 任务槽个数.必须和实际任务数一至
#define MAX_TASKS 2
// 最大栈深.最低不得少于2个,保守值为12
#define MAX_TASK_DEP 12
// 当前活动任务号
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];}
// 任务切换函数(任务调度器)
void task_switch()
{
task_sp[task_id] = SP;
if(++task_id == MAX_TASKS)
task_id = 0;
SP = task_sp[task_id];
// 本函数返回时,PC取SP指针数据,取两次
}
// 任务装入函数
// 将指定的函数(参数1)装入指定(参数2)的任务槽中.
// 如果该槽中原来就有任务,则原任务丢失,但系统本身不会发生错误.
void task_load(Fun fn, unsigned char tid)
{
// 堆栈通常设在30H~7FH这一段片内RAM中,堆栈区是向地址增大的方向生成的.
// 且由于CPU是8位的,数据入栈时,SP先加1,然后数据再压入SP指向的单元;
// 数据出栈时,先将指向的单元的数据弹出,然后SP再减1。(以字节为单位)
// 含义为:压栈两次
// 未压栈时,SP指向堆栈外面。
// 第一次压栈时指向task_stack[tid][0],第二次压栈时指向task_stack[tid][1]
// 出栈时,PC取堆栈SP数据。
// 先取数据,再减一,取两次
task_sp[tid] = (unsigned int)(task_stack[tid] + 1)&0xFF;
// 函数地址为2字节
task_stack[tid][0] = (unsigned int)fn & 0xff;
task_stack[tid][1] = (unsigned int)fn >> 8;
}
void task1()
{
static unsigned char i;
while(1)
{
i++;
task_switch();
}
}
void task2()
{
static unsigned char j;
while(1)
{
j+=2;
task_switch();
}
}
void rtosInit()
{
// 这里装载了两个任务,因此在定义MAX_TASKS时也必须定义为2
// 将task1函数装入0号槽
task_load(task1, 0);
// 将task2函数装入1号槽
task_load(task2, 1);
os_start(0);
}
// 调用
extern void rtosInit();
void main(void)
{
rtosInit();
}