写一个属于自己的RTOS(day-1)

本文记录了作者学习RTOS的第一天,从论文中的启发开始,探讨如何建立一个简单的RTOS,涉及堆栈、函数调用及任务调度的概念。通过实例解释了前后台系统、协作式系统和抢占式系统的区别,并描述了RTOS中任务切换的寄存器保存和恢复过程。作者以延时服务的协作式内核为例,阐述了任务调度的工作流程。
摘要由CSDN通过智能技术生成

RTOS Once More

大三的时候,我也看过有关实时操作系统的论文与程序,并没有太在意这一知识点、没有去深刻的学习有关的知识,显然我是被论文中的一句话所坑了“实时性最好的还是裸机跑程序”,确实。想想我大学四年的开发中无论是学习还是比赛,都是“裸奔”的。由于STM32F103的主频够快,也感觉不到控制输出有延迟。现在当我去做FlightFight游戏时,却实现不了两个对象的分别控制,才想起RTOS。2020/4/19今天是第一天学习,总结一下今天的成果。今天是从文章“建立一个属于自己的AVR的RTOS”开始的。
知识点回顾
专门与堆栈和PC指针打交道的一类指令
rcall 相对调用子程序指令
icall 间接调用子程序指令
ret 子程序返回指令
reti 中断返回指令
ret与reti,都是将堆栈顶的两个字节弹出来送入程序计数器PC中,一般用来从程序或中断中推出。其中reti还可以在退出中断时,重新开启全局中断使能。这些都是学习汇编的时候提到的。
启发
有了相应的知识点基础,并加上RTOS是利用函数地址调用函数的。我们可以模拟一下操作系统调用函数的过程:将函数的地址存到私有堆栈中。当某任务就绪时,将该任务的函数入口地址,给SP,当使用ret 返回时SP的值恢复到了PC中,进而PC指向了某个函数。所以先建立私有堆栈试一试。

void fun1(void)
{
   
	unsigned char i=0;
	while(1)
	{
   
		PORTB=i++;
		PORTC = 0X01<<(i%8);
	}
}
unsigned char Stack[100];//建立一个100字节的人工堆栈
void RunFunInNewStack(void (*pfun)(),unsigned char *pStack)
{
   
	*pStack --=(unsigned )pfun;//将函数的地址低位压入堆栈
	*pStack --=(unsigned int)pfun>>8;//将函数的地址高位压入堆栈
	SP = pStack;//将堆栈指针指向人工堆栈的栈顶
}
int main(void)
{
   
	RunFunInNewStack(fun1,&Stack[99]);
}

该程序的运行过程是:函数RunFunInNewStack()将指向函数的指针的值保存到一个unsigned char的数组Stack中,作为人工堆栈。并且将栈顶的数组传递给堆栈指针SP。因此当用ret返回时,从SP中恢复到PC中的值,就变成了指向fun1()的地址,开始运行fun1()。
问题发现
其一:通常大家都会认为,在任务调度时,当然要将所有的通用寄存器都保存,并且还应该保存程序状态寄存器SREG。然后再根据相反的次序,将任务内容恢复。这是不对的。反复试验用到的寄存器为第一类第二类第三类寄存器。如果在中断函数中有调用其它函数,会在进入中断后,固定的将第一类寄存器和第三类寄存器入栈 ,在退出中断又将他们入栈。
其二:前后台系统,协作式内核系统 ,抢占式内核系统,有何不同?
举个例子:排队打饭。你正在打饭,身后是院长,院长身后是校长。
如果是前后台系统:不管是谁都得排队一个一个来。也就是我们的裸奔系统。
如果是协作式系统:等你打完饭,让校长先吃上饭,院长最后才吃上饭。
如果是抢占式系统:不论是谁在打饭还是排队,只要有更高级别的人在等着,都要第一时间让出来,让最高级别的校长第一个打饭。
实战1--------写一个只有延时服务的协作式内核

#define OS_TASKS 3
unsigned char Stack[200];
register unsigned char OSRdyTb1 asm("r2");  //运行任务就绪表
register unsigned char OSTaskRunningPrio asm("r3");
//正在运行的任务
struct TaskCtrBlock{
    //任务控制块
	unsigned int OSTaskStackTop;//保存任务的栈顶
	unsigned int OSWaitTick;//任务延时时钟
}TCB[OS_TASKS+1];
//防止被编译器占用
register unsigned char tempR4 asm("r4");
register unsigned char tempR5 asm("r5");
register unsigned char tempR6 asm("r6"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值