51系列小型操作系统精髓 简单实现4

本文介绍了一种基于51单片机的简单多任务调度实现方法,通过定义任务堆栈、任务ID等变量,并利用任务切换函数实现任务间的轮询执行。通过具体的示例代码展示了如何创建和启动两个简单的测试任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <REG52.H>


#define MAX_TASKS 2 //任务槽个数.必须和实际任务数一至
#define MAX_TASK_DEP 12 //最大栈深.最低不得少于2 个,保守值为12.
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.
unsigned char idata task_sp[MAX_TASKS];
unsigned char task_id; //当前活动任务号


//任务切换函数(任务调度器)
void task_switch(){
task_sp[task_id] = SP;
if(++task_id == MAX_TASKS)
task_id = 0;
SP = task_sp[task_id];
}
//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任
//务,则原任务丢失,但系统本身不会发生错误.
void task_load(unsigned int fn, unsigned char tid){
task_sp[tid] = task_stack[tid] + 1;
task_stack[tid][0] = (unsigned int)fn & 0xff; //低字节
task_stack[tid][1] = (unsigned int)fn >> 8;     //高字节
}
//从指定的任务开始运行任务调度.调用该宏后,将永不返回.
#define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}
/*============================以下为测试代码==========================*/
void task1(){
static unsigned char i;
while(1){
i++;
task_switch();//编译后在这里打上断点
}
}
void task2(){
static unsigned char j;
while(1){
j+=2;
task_switch();//编译后在这里打上断点
}
}
void main(){
//这里装载了两个任务,因此在定义MAX_TASKS 时也必须定义为2
task_load(task1, 0);//将task1 函数装入0 号槽
task_load(task2, 1);//将task2 函数装入1 号槽
os_start(0);

}

以上为网摘

以下为本人改进:任务函数切换

#include <REG52.H>

#define MAX_TASKS 2 //任务槽个数.必须和实际任务数一至
#define MAX_TASK_DEP 12 //最大栈深.最低不得少于2 个,保守值为12.
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.
//unsigned char idata task_sp[MAX_TASKS];
unsigned char task_id; //当前活动任务号

//任务切换函数(任务调度器)
void task_switch(){
//	task_sp[task_id] = SP;
	if(++task_id == MAX_TASKS)
		task_id = 0;
	SP = task_stack[task_id] + 1;
}
//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任
//务,则原任务丢失,但系统本身不会发生错误.
void task_load(unsigned int fn, unsigned char tid){
//	task_sp[tid] = task_stack[tid] + 1;
	task_stack[tid][0] = (unsigned int)fn & 0xff;	 //低字节
	task_stack[tid][1] = (unsigned int)fn >> 8;	     //高字节
}
//从指定的任务开始运行任务调度.调用该宏后,将永不返回.
#define os_start(tid) {task_id = tid,SP = task_stack[tid] + 1;return;}
/*============================以下为测试代码==========================*/
void task1(){
	static unsigned char i;
	while(1){
		i++;
		task_switch();//编译后在这里打上断点
	}
}
void task2(){
	static unsigned char j;
	while(1){
		j+=2;
		task_switch();//编译后在这里打上断点
	}
}
void main(){
	//这里装载了两个任务,因此在定义MAX_TASKS 时也必须定义为2
	task_load(task1, 0);//将task1 函数装入0 号槽
	task_load(task2, 1);//将task2 函数装入1 号槽
	os_start(0);
}

以本人再改进:任务断点切换

//任务切换函数(任务调度器)
void task_switch(){
	//保存当前断点;
	task_stack[task_id][0] =*((unsigned char *)(SP-1));
	task_stack[task_id][1] =*((unsigned char *)(SP-2));
	//设置任务优先级

	//切换到下一任务  ,如果没有下一任务,则回到0任务,切换到哪里?
	if(task_id==0)
		SP=SP-2;  //切换出去,接着执行
	else
	{
			SP = task_stack[task_id] + 1;    //


	}
				
}



全部程序

#include <REG52.H>

#define MAX_TASKS 2 //任务槽个数.必须和实际任务数一至
#define MAX_TASK_DEP 2 //最大栈深.最低不得少于2 个,保守值为12.
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP]={0};//任务堆栈.
//unsigned char idata task_sp[MAX_TASKS];
unsigned char task_id=0; //当前活动任务号

//任务切换函数(任务调度器)
void task_switch(){
	//保存当前断点;
	task_stack[task_id][0] =*((unsigned char *)(SP-1));
	task_stack[task_id][1] =*((unsigned char *)(SP-2));
	//设置任务优先级


	//切换到下一任务  ,如果没有下一任务,则回到0任务,切换到哪里?

	
	if(task_id==0)
	{
		task_id=1;
		if(task_stack[1][0]==0 && task_stack[1][1]==0 )
		{
			SP=SP-2;  //切换出去,接着执行
		}
		else
		{		
			SP = task_stack[task_id] + 1;
		}

		
	}
	else
	{
		   	task_id=0;
			SP = task_stack[task_id] + 1;    //
	}
	//



}
/*
//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任
//务,则原任务丢失,但系统本身不会发生错误.
void task_load(unsigned int fn, unsigned char tid){
//	task_sp[tid] = task_stack[tid] + 1;
	task_stack[tid][0] = (unsigned int)fn & 0xff;	 //低字节
	task_stack[tid][1] = (unsigned int)fn >> 8;	     //高字节
}
//从指定的任务开始运行任务调度.调用该宏后,将永不返回.
#define os_start(tid) {task_id = tid,SP = task_stack[tid] + 1;return;}
*/
/*============================以下为测试代码==========================*/
void task1(){
	static unsigned char i;
	while(1){
		i++;
		task_switch();//编译后在这里打上断点
	}
}
void task2(){
	static unsigned char j;
	while(1){
		j+=2;
		task_switch();//编译后在这里打上断点
	}
}
void main(){
	task1();
	task2();
	/*
	//这里装载了两个任务,因此在定义MAX_TASKS 时也必须定义为2
	task_load(task1, 0);//将task1 函数装入0 号槽
	task_load(task2, 1);//将task2 函数装入1 号槽
	os_start(0);*/
}


一个小型操作系统,采用gcc进行开发,几千行的代码,方便初学者学习,内含有编译好的映像文件,及bochs模拟器配置文件,可在bochs下模拟运行。如下为源码包内的README文件: # # Snixos Project version 1.0, 2003.6 # (C) Copyright 2003,2004,2005 Jockeyson,KeqianGao # All Rights Reserved. # Distributed under the terms of the GNU General Public License. # # This program is a free and open source software and you can redistribute # it and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation. As no any liability is assumed # for any incidental or consequential damages in connection with the # information or program fragments contained herein,so any exception arised # is at your own risk. It is ABSOLUTELY WITHOUT ANY WARRANTY. # Bug report please send to Snallie@tom.com . # 0. What is Snixos Project? Snixos Project is an experimental operating system designed by Jockeyson , KeqianGao aiming at multitask/multithread, Chinese envionment including Chinese characters input and ouput etc... 1. What you need to run Snixos PC with the following minimum configuration: CPU: i386 or above MEM: 2M extended memory or more DISPLAY: VGA or above Floppy Drive: 1.44M 2. Compile Environment RH Linux 7.2 or above (kernel 2.4.7-10 ) NASM 0.98 gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-98) 3. Compile and install a. unpack the source package tar zxvf snixos_x.x_YYYYMMDD_HHMMSS.tgz b. cd to snixos cd snixos c. before make insert a 1.44M floppy in drive c.1 to make snixos run in VGA text mode make clean make VIDEO=TEXT diskimg make floppy c.2 to make snixos run VGA graphics mode make clean make diskimg make floppy d. bootup with the floppy just created in step c also you can follow this way to run snixos in bochs either in Windows or Linux a. just as the above b. just as the above c. invoke these command: make clean; make diskimg you'll get a snixos ima
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄人软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值