mirror of
https://gitee.com/cosyos/cosyos.git
synced 2026-02-05 19:39:42 +08:00
167
说明文档/CosyOS原理与应用.md
Normal file
167
说明文档/CosyOS原理与应用.md
Normal file
@@ -0,0 +1,167 @@
|
||||
## 第一章、任务篇
|
||||
|
||||
### 一、任务优先级分组
|
||||
您可在系统配置文件中配置任务优先级分组。<br>
|
||||
共有六个分组可供选择,8级、16级、32级、64级、128级、256级,您也可自定义级数。<br>
|
||||
如您配置的分组为8级,则最高优先级为7级,最低优先级为0级。<br>
|
||||
<br>
|
||||
|
||||
### 二、时间片模式
|
||||
CosyOS有三种时间片的定义模式,全局时间片、算法时间片、自定义时间片,需在系统配置文件中定义。<br>
|
||||
**1. 全局时间片** 所有任务采用统一的时间片。<br>
|
||||
**2. 算法时间片** 不同优先级的任务时间片不同,采用一个算法公式来描述。<br>
|
||||
**3. 自定义时间片** 不同优先级的任务时间片不同,用户自定义各优先级的时间片。<br>
|
||||
全局时间片简单高效,时间片轮转调度性能为最佳;算法时间片、自定义时间片可实现不同优先级任务精细的时间片控制。<br>
|
||||
时间片的取值范围:1~65535,单位为滴答周期。<br>
|
||||
<br>
|
||||
|
||||
### 三、安全运行时
|
||||
安全运行时是CosyOS的安全关键技术之一,是为了防止某任务长期独占或超时使用处理器。当任务累计运行时间超过安全运行时,仍不能被比它优先级低的任务所切换,则进入超时状态并放弃处理器的使用权,直到系统空闲任务运行时才能恢复。<br>
|
||||
安全运行时的取值范围:0~65535,单位为时间片,0为无限长。<br>
|
||||
所有空闲任务无法应用安全运行时,创建任务时,安全运行时输入0即可。<br>
|
||||
安全运行时的应用技巧:开发初期,所有任务的安全运行时可设置为0;待开发测试阶段中后期,再根据任务各自的特点及测试经验合理的调整为有效值。<br>
|
||||
<br>
|
||||
|
||||
### 四、支持任务/钩子
|
||||
|
||||
* **系统任务** <br>
|
||||
由CosyOS自主创建并自动启动的任务。<br>
|
||||
**1. 任务管理器(Taskmgr)** 优先级固定为最高优先级。<br>
|
||||
**2. 调试任务(Debugger)** 优先级固定为最高优先级,用做命令行和任务管理器的串口接收解析。<br>
|
||||
**3. 启动任务(Starter)** 优先级固定为比最高优先级低一级,通过调用启动钩子来启动用户任务,而后删除自身。<br>
|
||||
**4. 系统空闲任务(Sysidle)** 优先级固定为最低优先级0级,是系统级的空闲任务。<br>
|
||||
|
||||
* **系统钩子** <br>
|
||||
由CosyOS自主创建并自动调用的函数,并由用户来写代码。<br>
|
||||
**1. 初始化钩子(init_hook)** 在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。<br>
|
||||
**2. 启动钩子(start_hook)** 在启动任务中被调用,用于启动用户任务。用户可在启动钩子内调用API来启动用户任务。<br>
|
||||
**3. 滴答钩子(tick_hook)** 每个系统滴答周期,在SysTick_Handler/定时器0中断中都会被调用一次,适用于每滴答周期/秒/分/时/...做一次的工作。<br>
|
||||
**4. 空闲钩子(idle_hook)** 在系统空闲任务中被调用,用户可添加自己的代码做一些没有实时性要求的工作。<br>
|
||||
**5. 挂起服务钩子(pendsv_hook)** 详情见全局变量访问相关介绍及说明。<br>
|
||||
**6. 全局变量钩子(gvar_hook)** 用于更新全局变量的副本。详情见全局变量访问相关介绍及说明。<br>
|
||||
|
||||
* **定时任务/钩子** <br>
|
||||
包括定时中断任务/钩子和定时查询任务/钩子,其实质都是软件定时器中断。<br>
|
||||
**1. 定时中断任务/钩子** 由用户设定定时时间,当定时器溢出时,系统将自动恢复/调用与其绑定的任务/钩子并自动重复定时(如果您已开启定时器的自动重装载)。<br>
|
||||
**2. 定时查询任务/钩子** 由用户设定定时时间,当定时器溢出后,系统在每个滴答周期都会查询用户定义的事件,若事件为真,系统将自动恢复/调用与其绑定的任务/钩子并自动重复定时(如果您已开启定时器的自动重装载)。系统初始化后,所有定时查询定时器的值均为零,相当于已经溢出,系统已经开始查询用户定义的事件了。<br>
|
||||
**3. 任务与钩子的区别** 由于定时中断钩子、定时查询钩子都是在SysTick_Handler/定时器0中断中被调用,所以只有相对精简的代码才适合创建钩子,耗时长的代码应创建为任务。再有,钩子相当于比任务具有更高的优先级,可更及时的被执行。<br>
|
||||
|
||||
* **一般用户任务** <br>
|
||||
对于一般用户任务,只要优先级为0级,就是空闲任务。用户空闲任务内都要有阻塞事件,以保证所有空闲任务都有机会被运行。<br>
|
||||
最高优先级固定分配给任务管理器和调试任务,建议用户任务不要使用。<br>
|
||||
<br>
|
||||
|
||||
### 五、任务状态
|
||||
CosyOS的任务状态较传统RTOS划分更为详细,以便用户在使用任务管理器监控任务时,能够更加精准的判断各任务的运行情况。<br>
|
||||
具体划分如下:<br>
|
||||
注:[]为在任务管理器中显示的任务状态<br>
|
||||
* **运行状态[RDY]** 任务正在运行。<br>
|
||||
* **就绪状态[RDY]** 任务已经准备就绪,可以参与任务调度并运行了。<br>
|
||||
* **延时阻塞状态[DLY]** 由阻塞延时而导致任务进入阻塞状态,直到延时时间结束转为就绪状态。<br>
|
||||
* **超时阻塞状态** :<br>
|
||||
**1. 二值信号量阻塞状态[BIN]** 由二值信号量等待或获取而导致任务进入阻塞状态,直到成功或超时转为就绪状态。<br>
|
||||
**2. 互斥信号量阻塞状态[MUT]** 由互斥信号量获取而导致任务进入阻塞状态,直到成功或超时转为就绪状态。<br>
|
||||
**3. 计数信号量阻塞状态[SEM]** 由计数信号量获取而导致任务进入阻塞状态,直到成功或超时转为就绪状态。<br>
|
||||
**4. 等待标志组阻塞状态[GRP]** 由事件标志组等待而导致任务进入阻塞状态,直到成功或超时转为就绪状态。<br>
|
||||
**5. 接收私信阻塞状态[ TM]** 由接收私信而导致任务进入阻塞状态,直到收到私信或超时转为就绪状态。<br>
|
||||
**6. 接收飞信阻塞状态[FET]** 由接收飞信而导致任务进入阻塞状态,直到收到飞信或超时转为就绪状态。<br>
|
||||
**7. 接收邮件阻塞状态[MAL]** 由接收邮件而导致任务进入阻塞状态,直到收到邮件或超时转为就绪状态。<br>
|
||||
**8. 接收消息阻塞状态[MSG]** 由接收消息而导致任务进入阻塞状态,直到收到消息或超时转为就绪状态。<br>
|
||||
* **浮动状态[RDY]** <br>
|
||||
浮动状态是临时的就绪状态。<br>
|
||||
超时阻塞的任务,当阻塞条件解除时,会转为浮动状态;<br>
|
||||
浮动状态的任务,当阻塞条件具备时,会转回阻塞状态。<br>
|
||||
浮动状态在任务管理器中显示为就绪状态。<br>
|
||||
* **超时状态[OSR]** <br>
|
||||
当任务累计运行时间超过安全运行时,仍不能被比它优先级低的任务所切换,则进入超时状态并放弃处理器的使用权,直到系统空闲任务运行时才能恢复。<br>
|
||||
* **挂起状态[SPD]** <br>
|
||||
任务暂停运行,除任务状态变为挂起外,任务的其它相关信息和数据均保持不变,当恢复任务后,可继续挂起时的断点运行。<br>
|
||||
运行状态的任务被挂起,恢复后为就绪状态;其它状态的任务被挂起,恢复后为原状态。<br>
|
||||
* **停止状态** <br>
|
||||
任务停止运行,不可恢复。<br>
|
||||
**1. 任务栈溢出停止[!OF]** 由任务栈溢出而导致任务停止运行。<br>
|
||||
**2. 任务栈重分配失败停止[!RF]** 由任务栈重分配失败而导致任务停止运行。<br>
|
||||
* **删除/未启动状态(Deleted)** <br>
|
||||
任务被删除或未启动,若想再次运行该任务,必须重新启动该任务。<br>
|
||||
|
||||
<br>
|
||||
—————————— CosyOS-任务状态图 ——————————<br>
|
||||
<br>
|
||||
|
||||
### 六、任务队列
|
||||
CosyOS全局只有一个任务队列,为双向循环链表,所有已启动且未删除的任务,都会在队列上排队。<br>
|
||||
* **排队原则** <br>
|
||||
**1.** 在队列上从头至尾,按任务优先级由大到小排列。<br>
|
||||
**2.** 如果任务优先级相同,则按任务启动顺序排列(先启动的任务排在前面)。<br>
|
||||
**3.** 如果启用了任务管理器,那它一定是任务队列上的第一个任务(头节点)。<br>
|
||||
**4.** 唯一的例外,系统空闲任务是任务队列上的最后一个任务(尾节点),其它所有任务都会排在它的前面。<br>
|
||||
|
||||
CosyOS任务管理器真实的反应了整个任务队列的当前形态。<br>
|
||||
其中任务ID(TID)是按任务的启动顺序动态分配的(从1开始++),真实的反应了任务的启动顺序。<br>
|
||||
下方示例中消失的任务(TID:2)为系统启动任务(Starter),任务启动完成后,该任务默认被自动删除。<br>
|
||||

|
||||
<br>
|
||||
—————————— CosyOS-任务管理器 ——————————-———————— CosyOS-启动钩子 ————————<br>
|
||||
<br>
|
||||
|
||||
### 七、任务调度
|
||||
CosyOS的任务调度类型包括 **抢占式调度** 、 **时间片轮转调度** 。不同优先级的任务实行抢占式调度,<br>
|
||||
相同优先级的任务按先入先出实行时间片轮转调度,“入”指的是加入到任务队列,即启动任务。<br>
|
||||
|
||||
CosyOS的任务调度时机分为 **定时调度** 与 **临时调度** 。<br>
|
||||
* **定时调度** <br>
|
||||
在每个系统滴答周期,SysTick_Handler/定时器0中断,都会触发一次任务调度。<br>
|
||||
* **临时调度** <br>
|
||||
**1.** 当前任务被阻塞、挂起、超时、停止、删除时,会立即触发任务调度。<br>
|
||||
**2.** 恢复任务时,如果恢复后该任务可以运行并且它的优先级高于当前任务的优先级,会立即触发任务调度。<br>
|
||||
**3.** 设置任务优先级时,如果该任务可以运行并且它的新优先级高于当前任务的优先级,会立即触发任务调度。<br>
|
||||
**4.** 设置阻塞时间为零或清除阻塞时,该任务会转为就绪状态,如果它的优先级高于当前任务的优先级,<br>
|
||||
会立即触发任务调度。<br>
|
||||
**5.** 归还互斥信号量完成时,如果发生过优先级继承(该任务的优先级被提升),会恢复该任务的原优先级,<br>
|
||||
并立即触发任务调度。<br>
|
||||
**6.** 用户通过调用服务,直接触发的任务调度,包括任务级任务调度和中断级任务调度。<br>
|
||||
|
||||
CosyOS的任务调度策略可最大程度的实现尽可能实时高效的任务切换,使CosyOS的实时性更为优异。<br>
|
||||
<br>
|
||||
|
||||
### 八、任务栈
|
||||
* **任务栈模式** <br>
|
||||
CosyOS把任务栈的处理方式称之为任务栈模式,共包括三种类型,MSP模式、PSP模式、MSP+PSP模式。<br>
|
||||
**MSP模式** 任务切换时,先拷贝主栈内容至当前任务栈(保存现场);再拷贝新任务栈内容至主栈(恢复现场)。<br>
|
||||
**PSP模式** 每个任务的任务栈都是主栈,哪个任务运行时,哪个任务的任务栈(当前任务栈)就是当前主栈。<br>
|
||||
**MSP+PSP模式** 中断时为Handler模式,入栈入的是主栈;任务时为Thread模式,入栈入的是当前任务栈。<br>
|
||||
1、对于51来说,CosyOS采用了搬栈这一传统方案,也就是MSP模式。<br>
|
||||
2、对于Arm来说,CosyOS所采用的方法当然是主流的双栈指针了,也就是MSP+PSP模式。<br>
|
||||
3、对于251来说,CosyOS支持MSP模式、PSP模式,这两种栈模式供用户选择。<br>
|
||||
**PSP模式与MSP+PSP模式的异同** :PSP模式,中断入栈也入任务栈,相比MSP+PSP模式,需要更大的任务栈,也就是需要更大的edata内存。<br>
|
||||
* **MSP模式的优势** <br>
|
||||
凡事都是辩证的,有一利必有一弊。<br>
|
||||
MSP模式虽然在任务切换时会保存并恢复现场,导致效率较低,但只要主栈和内存池足够大,就可确保所有任务栈永不溢出。<br>
|
||||
当然,前提是任务栈得是动态的,CosyOS将自动启用任务栈重分配机制,以抵御任务栈溢出的风险。<br>
|
||||
这一点是PSP模式、MSP+PSP模式所不具备的。PSP模式、MSP+PSP模式,一旦任务栈溢出,既成事实,数据覆盖可能已经发生,无法挽回。<br>
|
||||
* **任务栈重分配机制** <br>
|
||||
任务栈重分配机制,在正式的产品中可有效抵御任务栈溢出的风险。<br>
|
||||
在概率上,也许测试一年也不会碰到一次任务栈溢出,但大批量产品投入使用后不一定哪天就会碰到。<br>
|
||||
如果内存足够大,问题也好解决,但51/251的内存有限,既要节约着用还不要栈溢出就得用点策略了。<br>
|
||||
任务栈重分配机制的意义就在于此。<br>
|
||||
重点是,任务栈重分配机制是做为一种补救手段,不建议用户过分依赖。<br>
|
||||
开发调试时,还是要配置够用的任务栈,保证测试阶段不会溢出(不会发生重分配)。<br>
|
||||
任务栈重分配次数多了会导致内存碎片,如果过分依赖的话,反而会导致内存更加不够用。<br>
|
||||
任务栈重分配机制,就是为了当万一哪一天任务栈溢出了呢?能够满血复活。<br>
|
||||
任务栈重分配机制的启用条件:<br>
|
||||
1、对于8051,当任务创建模式非静态创建时,CosyOS将自动启用任务栈重分配机制。<br>
|
||||
2、对于80251,当任务栈模式为MSP模式、任务创建模式非静态创建时,CosyOS将自动启用任务栈重分配机制。<br>
|
||||
* **任务栈之初始定义**
|
||||
1、对于51及251的MSP模式,当任务创建模式非静态创建时,任务栈的初始定义可以小(因为有重分配机制),而后根据监控及报警情况再调整(增大)。
|
||||
2、对于251的PSP模式及Arm的MSP+PSP模式,任务栈的初始定义一定要够大,否则可能会运行不起来或死机,而后再根据测试情况重新调整任务栈。
|
||||
3、对于251的PSP模式,由于中断入栈也入任务栈,所以需要用户自己根据中断的使用情况来计算一个中断嵌套入栈的最大size(不必包括最低优先级的中断入栈),累加到“前面的字节数”中,看是否会大于 “后面的字节数”,再行调整。
|
||||
|
||||
### 九、任务管理器
|
||||
|
||||
## 第二章、中断篇
|
||||
|
||||
## 第三章、线程同步
|
||||
|
||||
## 第四章、互斥访问
|
||||
|
||||
## 第五章
|
||||
Reference in New Issue
Block a user