手撸嵌入式操作系统

一,先了解一些基本概念

1,什么是操作系统?

操作系统是为了解决计算机资源争抢而编写的一个程序

2,什么是资源争抢?

多个任务在执行的过程中需要共享有限的资源

3,什么是任务?

计算机需要完成的某一项工作

4,顺序执行?

任务一个接一个的执行

5,多任务并行:

同时运行多个任务

6,任务优先级:

根据任务的重要性和使用频度决定工作的优先级

7,进程:

正在进行的任务

8,类比现实生活来理解:

①系统资源:在学校的操场上,有很多资源供学生玩耍,比如篮球场,足球场,篮球,足球。这相当于计算机中的系统资源

②任务:每个学生都有自己喜欢玩的项目,比如跳绳,踢足球,玩沙子。这些需求相当于计算机里的任务

③进程:当一个小朋友在玩耍。例如玩皮球,那么这个正在进行的活动就是一个进程

④顺序执行:如果操场上只有一个足球,那么小朋友需要一个接一个的踢足球,小明踢完,小红踢。相当于计算机里面的顺序执行。任务一个接一个的执行

⑤多任务并行:在这个情况下,操场上有非常多的资源供所有的小朋友玩。

例如:小明可以踢皮球,小红可以玩跳绳,小浩可以玩沙子,他们都在同时玩各自的游戏。这就相当于计算机里面的多任务并行,各个任务可以同时进行。

在学校里面,老师(操作系统)负责管理操场上的资源(系统资源),确保每个小朋友都能有序的玩耍(任务)。老师可以按实际情况选择让同学按顺序玩耍或同时玩耍,以便更好的利用操场上的资源。

9,高级操作系统特性:

高级操作系统具有任务切换、多任务并行和任务优先级设置的功能。

①任务切换:假设有两个任务:一个是小明想喝水,另一个是小红想画画。老师先满足了小明的需求,然后满足小红的需求,在这个过程中,老师从小明的需求切换到小红的需求。

②多任务并行:如果学校的资源足够丰富,大家可以同时玩耍。小明可以踢皮球,小红可以玩跳绳,小浩可以玩沙子,他们都在同时玩各自的游戏。这就相当于计算机里面的多任务并行,各个任务可以同时进行。

③任务优先级:小明和小红都想玩足球,此时发生了资源的争抢。但是小红的爸爸是校长,小红说我想先玩这个,老师就先让小红先玩了,这就是任务的优先级。计算机优先执行高优先级任务。

10,时间片轮转和上下文切换

假设老师需要在一段时间内满足多个小朋友的需求,例如小明想玩积木,小红想画画,小刚想听故事,并且只有一位老师,他们想得到老师的帮助。这时,老师会用“时间片”来分配自己的时间。

①时间片: 老师为每个小朋友分配固定时间,例如5分钟。这段时间被称为“时间片”。在这个时间片内,老师会专注于帮助一个小朋友。例如,老师先花5分钟陪小明玩积木,然后花5分钟陪小红画画,最后花5分钟给小刚讲故事。

②上下文切换:每当一个时间片结束,老师需要从当前任务(陪小明玩积木)切换到下一个任务(陪小红画画)。在这个过程中,老师需要记住前一个任务的状态(小明已经搭好了几个积木),以便在下一个时间片回到这个任务时可以继续帮助小明。这种在任务间进行状态切换的过程为“上下文切换”。

通过合理的分配时间片和进行上下文切换,老师能够高效的管理多个任务。计算机使用这个机制来确保计算资源得到合理的分配。

假设时间片非常短,5ms。先花10ms陪小明搭积木,然后花10ms陪小红画画,最后花10ms给小刚讲故事。因为小朋友的反应没那么快,感觉老师一直在跟自己玩。

11,操作系统和资源调度

在学校中,也可能会出现资源争抢的问题。例如,如果只有一套画笔和颜料,两个小朋友(小明,小红)同时想画画,那他们就发生了争抢,而老师(操作系统)需要采取措施来解决这个问题。

①优先级分配,可以先把画笔和颜料分给优先级比较高的任务。例如,如果小明需要完成画画作业,而小红只是想随手画个小老鼠,那老师就会把画笔和颜料优先分配给小明。

②时间片轮转:老师可以分配时间片来保证两个人都能使用资源。例如,小明和小红轮流使用画笔和颜料,每次5分钟。防止某个小朋友长时间独占资源。

12,中断系统

在学校中,我们可以将中断理解为突发事件,需要老师(操作系统)立即处理,暂停正在进行的活动。

情景:假设老师正在帮助小明绘画调色,此时小红摔倒了,受了伤。这个突发事件好比是一个“中断”。

在这种情况下,老师需要立刻暂停正在进行的绘画活动,处理突发事件。老师取查看小红的伤势,处理伤口。处理完之后,老师会重新回到绘画活动中,继续之前的工作,帮小明调色。

在计算机系统中,中断是类似的,当一个突发事件(外设发的信号、计时器到期或紧急报错)发生,CPU会停止正在执行的任务,转而处理这个事件,处理完之后,CPU会返回到原来的任务,从中断前的位置继续执行。

在计算机系统中,中断使得CPU能够在执行任务的同时,及时响应和处理紧急事件,提高系统的实时性和灵活性。

13,实时操作系统和非实时操作系统

实时操作系统:假设有一天,学校要举办一个晚会,需要老师(操作系统)来调度表演节目以及处理突发状况。在这个场景中,老师需要在特定的时间完成特定的任务。以确保晚会的顺利举办。;例如,老师需要在晚会开始前确保所有的节目都准备好,还需要在特定的时间开始和结束某个节目。如果某个节目没有按时开始或者结束,可能会影响整个晚会的进程。这种在特定时间内完成任务的操作系统就是实时操作系统。

非实时操作系统:我们来看另一个场景。假设在普通的上课日,老师需要安排各种活动,比如上课,吃饭,午休。在这种情况下,老师需要确保每个活动都安排,但没有严格的时间限制。例如,吃饭早一点,午休晚一点,不会产生严重影响。这种就是非实时操作系统。

实时操作系统分为硬实时和软实时:

硬实时:在晚会中,假如有一个节目需要在特定的时间点精确开始,例如在晚会开始后5min内。如果这个节目没有在这个时间点内准时开始,可能会导致晚会的失败,或产生严重的后果。在这种情况下,老师必须确保这个节目在特定的时间内开始,这就是硬实时,意味着任务必须在严格的时间限制内完成,否则会导致严重后果。

软实时:在晚会中,如果有一个节目希望在晚会10min内开始,但是如果晚一点也没关系。这种情况下,老师还是会尽力保证节目暗示开始,但即使稍微晚一点,给晚会影响也不大。这就是软实时。任务有时间限制,但即使没有完全满足时间要求,也不会导致系统失效或产生严重后果。

基于时间片切换的操作系统属于软实时操作系统。

14,操作系统概念总结一把

操作系统概念学校场景
系统资源玩具、游戏场地、定时器、秒表
任务小朋友喜欢做的事情(画画,踢球)
进程小朋友正在进行的活动(画画,踢球)
顺序执行老师依次满足每个小朋友的需求
多任务并行老师同时满足多个小朋友的需求
任务优先级根据小朋友的需求紧急程度安排先后顺序
任务切换老师在不同小朋友的需求之间切换
时间片老师给每个小朋友分配一段时间
上下文切换老师满足一个小朋友需求之后,快速切换满足另一个小朋友需求
上下文保存老师在切换前记住第一个小朋友的状态,方便一会切回来继续满足他的需求
中断突发事件导致老师暂停当前活动,处理紧急问题
资源争抢与解决办法多个小朋友争抢玩具,老师协调和安排轮流使用或分享
实时操作系统老师能够满足小朋友的需求,并按时完成时间要求
非实时操作系统老师满足小朋友的要求,但不能保证完成任务的时间
硬实时老师必须在规定时间内完成任务,否则会产生能够产生严重后果
软实时老师尽量在规定时间内完成任务,但延迟不会产生严重后果

二,单片机的内存结构

寄存器组:地址范围0x00-0x1f。包含4组8位寄存器,分别R0-R7,对应的寄存器组选择由PSW中的RS0和RS1控制。

位寻址区:地址范围0x20-0x2f,包含了128位,可以直接使用位操作指令进行访问

字节寻址区:地址0x30-0x7f,用于一般数据存储

特殊功能寄存器(SFR):地址范围0x80-0xff,包含了所有特殊功能寄存器,如P0,P1,P2,P3等端口寄存器,ACC累加器,B寄存器,SP栈指针等。

0x0000到0xffff,这是程序存储器的地址范围,用于存储程序代码。这些数据是存在FLASH中的。

Flash存储器用于存储程序代码,RAM用于存储临时数据、变量、堆栈。程序代码冲FLASH存储器加载到RAM中,然后由CPU执行。

三,程序执行顺序切换的原理

计算机系统,通过修改PC的值可以修改下一行要执行程序的汇编代码的位置,但实际上stc单片机是没有汇编语言修改pc值的。因为程序计数器通常是由硬件自动递增的,用于指向将要执行的下一条指令的地址。

但我们可以通过其他手段来简介修改PC值,汇编语言有JUMP,和CALL,他们的区别就是有木有修改SP(堆栈指针)的内容。

四,show code 

1,定义操作系统的loadtask函数

#include <stc8h.h>
#define MAX_TASKS 2 //任务的堆栈指针,简化方便我们当前操作系统只有2个task
#define MAX_TASK_DEP 32 //堆栈的深度

unsigned char task_sp[MAX_TASKS];
unsigned char task_stack[MAX_TASKS][MAX_TASK_DEP]; //每一个task任务的堆栈

2,写两个执行的task:task0, task1

unsigned char task_id;//当前任务号,从0 开始

void task0()
{
	//第0号任务,代表第0个小朋友做的事情
	unsigned int a = 3;
	while (1)
	{
		a += 3;
	}
}

void task1()
{
	//第1号任务,代表第一个小朋友做的事情
	unsigned int b = 5;
	while (1)
	{
		b += 5;
	}
}

3,通过修改sp来修改调用的函数

void main()
{
	task_load(task0, 0);//把task0装载到内存中
	task_id = 0;
	SP = task_sp[0];//特殊功能寄存器  

}

4,定义一个任务调度器

//定义一个任务切换的函数
//任务调度器
void task_switch() {
	
	task_sp[task_id] = SP;//把当前系统的堆栈指针存入到某个小朋友的task_sp里面

	task_id = (task_id + 1);//任务加1

	if (task_id == MAX_TASKS) {
		task_id = 0;
	}
	SP = task_sp[task_id];//SP存的是上下文信息

}

最终代码:

#include <stc8h.h>
#define MAX_TASKS 2 //任务的堆栈指针,简化方便我们当前操作系统只有2个task
#define MAX_TASK_DEP 32 //堆栈的深度

unsigned char idata task_sp[MAX_TASKS];
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP]; //每一个task任务的堆栈
//iadata 访问最快的那一层空间  
unsigned char task_id;//当前任务号,从0 开始

//定义一个任务切换的函数
//任务调度器
void task_switch() {
	
	task_sp[task_id] = SP;//把当前系统的堆栈指针存入到某个小朋友的task_sp里面

	task_id = (task_id + 1);//任务加1

	if (task_id == MAX_TASKS) {
		task_id = 0;
	}
	SP = task_sp[task_id];//SP存的是上下文信息

}

void task0()
{
	//第0号任务,代表第0个小朋友做的事情
	static unsigned int a = 3;
	while (1)
	{
		a += 3;
		task_switch();
	}
}

void task1()
{
	//第1号任务,代表第一个小朋友做的事情
	static unsigned int b = 5;
	while (1)
	{
		b += 5;
		task_switch();
	}
}
//幼儿园老师,加载任务
//fn是一个函数的指针,注意数据类型是int
//tid  task id,是8位的  0,1
//把一个task的函数指针放入对应的堆栈空间
void task_load(unsigned int fn, unsigned chat tid)
{
	task_sp[tid] = task_stack[tid] + 1;//把任务的指针往下一个空间挪一格,两个char

	task_stack[tid][0] = fn & 0xff;
	task_stack[tid][1] = fn >> 8; 
}

void main()
{
	task_load(task0, 0);//把task0装载到内存中
	task_load(task1, 1);//把task1装载到内存
	task_id = 0;
	SP = task_sp[0];//特殊功能寄存器  

}

一个小的操作系统就是这样的,复杂一点的哥们还没学,继续加油兄弟们!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值