基于汇编的操作系统


设计涉及到三个部分:要处理的对象、平台资源、设计方法

    要处理的对象包括:可平行运行的任务、突发外部中断、任务间的通信三大块。

    平台资源(相比C语言)包括:硬件堆栈有限、无函数堆栈、不易设置任务堆栈、任务间通信均采用全局变量。

       设计方法:主体任务管理、任务切换采用goto函数,每个任务均有20ms以内的执行完毕的限制,纯时间片轮番、不涉及任务优先级。

这样以来,不涉及到像uC/OS II那样的每个任务的各个状态的管理,减少了设计难度。实际上使用PIC的汇编是可以写出uC/OSII那样的操作系统的,虽然硬件堆栈有限,但是goto型函数和call型函数是相通的。

    具体结构如下:

 

全局变量定义:包括任务自身的变量、任务间的通信。

 

   普通中断:

   定时器中断(20ms----任务管理器():

                                                 任务环境初始化:

任务列表、切换

                                                

 

   任务1( ):

   任务2( ):

    。

       。

       。

       。

任务n( ):

说明:此只适用于简单、有多任务需求的项目。当然应用面很窄,电机阀寿命检测机就不适合,或者说其根本就不适合用操作系统。。。。。操作系统往往应用于强烈需要多任务共同运行的项目。

 

 

版本一:

顺便说下,基于C语言的操作系统。(我这种既不像uC/OS II,又不像Linux,属任务主动型操作系统,即任务的内容决定系统控制权)

构架如下(均采用结构体的方式):

任务信息存储区初始化: 每个任务的信息包括---任务名(每个任务的首地址)、任务堆栈区(保存该任务实际堆栈区的首地址)、任务优先级、状态(空闲态、就绪态、运行态、挂起态)、延时数据(为0说明不需要延时)、当前延时数据。此区可设置最大的任务数目,比如,uC/OS II有64个,我们也可以这样设置,这样在设计操作系统的时候,我们要为这个区保留适合对应的空间。

 

任务堆栈区初始化----用于保存每个任务的寄存器。对于PIC来说,只有3个寄存器需要保存---W、程序存储器指针和STATUS。而对于AVR,则有十几个寄存器需要保存。

 

主函数开始:-------------------------------

基于中断的操作系统定时器:为操作系统系统时钟,主要用于各任务的空闲延时。

在该定时器中断服务程序中,首先依次检查(链表形式)各个需要延时的任务是否已经延时到位,若是,则把该任务的状态改为“就绪态”。

再依次检查所建立的各个任务的“延时数据”,当任务需要延时时(检查标志位),在每次中断后,“当前延时数据”加一。

任务管理器:此相当于操作系统的主函数。

       保存上次执行的任务的“任务信息”以及“任务堆栈”。当任务是空闲态的时候,要对程序存储器指针最相应的处理(往后移动),因为该任务延时返回的。当任务是挂起态的时候,将程序存储器指针指向该任务的起始地址。

再依次巡检(链表形式)“任务信息存储区”中每个任务信息的“状态”,将处于“就绪态”的任务找出来;然后,再在上面的查找结果中,排查比较各任务的优先级,将优先级最高的任务划作为当前需执行的任务CurrentTask。

       对应恢复CurrentTask的“任务堆栈”到微处理器各寄存器;将该任务的状态设置为运行态;根据该任务保存的程序存储器指针恢复CurrentTask的执行。

 

 

具体的任务

       具体形式可以为While(1)型,也可以是固定次数型。

本任务主动让出系统控制权、返回到“任务管理器”的情况(与版本2相比,没有剥夺式的情况)-------延时(调用专用的延时函数),并设置其自身的状态为“空闲态”;执行完毕,以后不再执行(当然如需要还可以被其他任务该动,设置为可执行),设置其自身的状态为“挂起态”。

 

中断:和单片机的没有差别,都是先保持现场,处理完事物之后再恢复现场。

 

 

几个问题的说明

临界代码:通过关中断的方式。但是在该代码体中,不能使用基于定时器的中断延时函数,需要专用的延时函数。若采用基于定时器的中断延时函数,则将导致系统时钟停止,但是在随后的任务管理器中若再开全局中断的话,系统还是可以再活过来的。

任务间的通信:若对操作系统了若指掌的话,可以直接采用全局变量,而不需要另外的通信管理机制。当然若考虑到操作系统的模块化和可执行性的问题的话,可以设置邮箱、消息队列的管理机制(TCB)。

剥夺性内核适用于强烈要求实时性的项目。

本系统功能和移植性有待完善。

 

 

版本2

基于C语言仿uC/OS II的操作系统

构架如下(均采用结构体的方式):

任务信息存储区初始化: 每个任务的信息包括---任务名(每个任务的首地址)、任务堆栈区(保存该任务实际堆栈区的首地址)、任务优先级、状态(空闲态、就绪态、运行态、挂起态)、延时数据(为0说明不需要延时)、当前延时数据。此区可设置最大的任务数目,比如,uC/OS II有64个,我们也可以这样设置,这样在设计操作系统的时候,我们要为这个区保留适合对应的空间。

 

任务堆栈区初始化----用于保存每个任务的寄存器。对于PIC来说,只有3个寄存器需要保存---W、程序存储器指针和STATUS。而对于AVR,则有十几个寄存器需要保存。

 

基于中断的操作系统定时器:为操作系统系统时钟,主要用于各任务的空闲延时以及任务切换。

在该定时器中断服务程序中,首先依次检查所建立的各个任务的“延时数据”,当任务需要延时时(检查标志位),在每次中断后,“当前延时数据”加一。

(任务管理器功能,与版本1不同之处在于切换前的查找方式)然后依次检查(链表形式)各个需要延时的任务是否已经延时到位,若是,则把该任务的状态改为“就绪态”。把刚置为“就绪态”任务的优先级与正在处于“运行态”的任务的优先级比较(这个比较的触发也可以不用定时器,改为更实时的其他方式,比如,外部中断等),若前者高于后者,则将前者置为“运行态”,标记为CurrentTask,后者置为“就绪态”,并进行以下动作,否则退出,我们称这种为剥夺式切换;或者没有“运行态”的任务时,则依次巡检(链表形式)“任务信息存储区”中每个任务信息的“状态”,将处于“就绪态”的任务找出来,然后,再在上面的查找结果中,排查比较各任务的优先级,将优先级最高的任务划作为当前需执行的任务CurrentTask,之后也进行以下动作,我们称这种为自然式切换。

动作具体为:保存上次执行的任务的“任务信息”以及“任务堆栈”。当任务是剥夺式切换的时候,要对程序存储器指针最相应的处理(往后移动)。当任务是自然式切换的时候,将程序存储器指针指向上次任务的起始地址。对应恢复CurrentTask的“任务堆栈”到微处理器各寄存器;将该任务的状态设置为运行态;根据该任务保存的程序存储器指针恢复CurrentTask的执行。   

 

操作系统首次任务:(先找出处于就绪态并且优先级最高的任务执行)。

       开操作系统定时器中断。

依次巡检(链表形式)“任务信息存储区”中每个任务信息的“状态”,将处于“就绪态”的任务找出来;然后,再在上面的查找结果中,排查比较各任务的优先级,将优先级最高的任务划作为当前需执行的任务CurrentTask。

       对应恢复CurrentTask的“任务堆栈”到微处理器各寄存器;将该任务的状态设置为运行态;根据该任务保存的程序存储器指针恢复CurrentTask的执行。

    While(1);/防止程序乱发

 

 

 

具体的任务

       具体形式可以为While(1)型,也可以是固定次数型。

本任务主动让出系统控制权的情况(当然还有被动让出系统控制权,是剥夺式的情况)-------延时(调用基于定时器的延时函数,这个函数中要修改任务的延时时间,之后要有段代码等待延时完毕,即“延时时间结束的标志”置位),并设置其自身的状态为“空闲态”;执行完毕,以后不再执行(当然如需要还可以被其他任务该动,设置为可执行),设置其自身的状态为“挂起态”。

 

中断:和单片机的没有差别,都是先保持现场,处理完事物之后再恢复现场。

 

 

几个问题的说明

临界代码:通过关中断的方式。但是在该代码体中,不能使用基于定时器的中断延时函数,需要专用的延时函数。若采用基于定时器的中断延时函数,则将导致系统时钟停止,系统任务不能切换。

任务间的通信:若对操作系统了若指掌的话,可以直接采用全局变量,而不需要另外的通信管理机制。当然若考虑到操作系统的模块化和可执行性的问题的话,可以设置邮箱、消息队列的管理机制(TCB)。

剥夺性内核适用于强烈要求实时性的项目。

本系统功能和移植性有待完善。

 

 

具有部分“任务管理器”的功能:查找延时时间到,优先级高的处于就绪态的任务,进行执行,这也体现了剥夺型内核特点的主要部分(这一部分加上之后,就比较复杂了)

 

 

 

版本3

基于C语言的仿Linux操作系统

与上面不同之处在:任务管理器换做基于定时器的时间片(这里的时间片要比仿uC/OSII操作系统的定时器延时长的多)轮番。系统延时采用的另外的定时器。

    构架如下(均采用结构体的方式):

任务信息存储区初始化: 每个任务的信息包括---任务名(每个任务的首地址)、任务堆栈区(保存该任务实际堆栈区的首地址)、任务优先级、状态(空闲态、就绪态、运行态、挂起态)、延时数据(为0说明不需要延时)、当前延时数据。此区可设置最大的任务数目,比如,uC/OS II有64个,我们也可以这样设置,这样在设计操作系统的时候,我们要为这个区保留适合对应的空间。

 

任务堆栈区初始化----用于保存每个任务的寄存器。对于PIC来说,只有3个寄存器需要保存---W、程序存储器指针和STATUS。而对于AVR,则有十几个寄存器需要保存。

 

基于中断的操作系统定时器:为操作系统系统时钟,主要用于各任务的空闲延时。

在该定时器中断服务程序中,首先依次检查(链表形式)各个需要延时的任务是否已经延时到位,若是,则把该任务的状态改为“就绪态”。

再依次检查所建立的各个任务的“延时数据”,当任务需要延时时(检查标志位),在每次中断后,“当前延时数据”加一。

定时器时间片任务管理器:

       保存上次执行的任务的“任务信息”以及“任务堆栈”。当上次任务是运行态的时候,保存处理过的当前程序存储器指针地址。当任务是挂起态的时候,将程序存储器指针指向该任务的起始地址。

再依次巡检(链表形式)“任务信息存储区”中每个任务信息的“状态”,将处于“就绪态”的任务找出来;然后,再在上面的查找结果中,排查比较各任务的优先级,将优先级最高的任务划作为当前需执行的任务CurrentTask。

       对应恢复CurrentTask的“任务堆栈”到微处理器各寄存器;将该任务的状态设置为运行态;根据该任务保存的程序存储器指针恢复CurrentTask的执行。

操作系统首次任务:(先找出处于就绪态并且优先级最高的任务执行)。

       开操作系统定时器中断。

依次巡检(链表形式)“任务信息存储区”中每个任务信息的“状态”,将处于“就绪态”的任务找出来;然后,再在上面的查找结果中,排查比较各任务的优先级,将优先级最高的任务划作为当前需执行的任务CurrentTask。

       对应恢复CurrentTask的“任务堆栈”到微处理器各寄存器;将该任务的状态设置为运行态;根据该任务保存的程序存储器指针恢复CurrentTask的执行。

    While(1);/防止程序乱发

 

具体的任务

       具体形式可以为While(1)型,也可以是固定次数型。

       与版本1、2不同的是,具体的各个任务不需要故意考虑让不让出系统控制权的问题(不像版本1那样,需要Delay(),其他任务才能执行。这里可以一直执行,而不需要Delay),只考虑任务的状态:while(1)型任务运行过程中是不是需要进入空闲态,固定次数型任务执行完是不是要进入挂起态等。任务中的延时函数采用定时器方式,这三个版本都一样。

中断:和单片机的没有差别,都是先保持现场,处理完事物之后再恢复现场。

 

 

几个问题的说明

临界代码:通过关中断的方式。但是在该代码体中,不能使用基于定时器的中断延时函数,需要专用的延时函数。若采用基于定时器的中断延时函数,则将导致系统时钟停止。

任务间的通信:若对操作系统了若指掌的话,可以直接采用全局变量,而不需要另外的通信管理机制。当然若考虑到操作系统的模块化和可执行性的问题的话,可以设置邮箱、消息队列的管理机制(TCB)。

剥夺性内核适用于强烈要求实时性的项目。

本系统功能和移植性有待完善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值