以前用过Vxworks, 由于工作需要,接触到Nucleus, 随手写的一个读书笔记,主要注重Nucleus Plus (NP)和其他Embedded OS 的差别。 1.1 About Nucleus Plus 实时、抢占、多任务内核,用于时间要求严格的嵌入式应用;95%的Nuclear PLUS用ANSI C写成;便于移植,能用于绝大多数微处理器架构。 片上RTOS! Nuclear PLUS常作为C库来使用。其发布形式为源码方式。 1.2 实时应用 不用多说了,J 1.3 Why Nucleus PLUS 提供任务管理(调度),任务间通信,任务同步,时钟,内存管理。 1.4 How to use Nucleus PLUS 将Nuclear PLUS当成一个C库来用。应用软件中用到的服务从Nuclear PLUS库中获取,和应用目标组合得到完整的映像(可执行代码)。映像被下载到目标机系统或ROM中。
使用Nuclear PLUS的一般步骤: 1) 如果必要,可以修改地及初始化文件,INT.* 注意:该文件常为汇编语言形式,其扩展名根据开发工具指定; 2) 定义Application_Initialize函数,其在Nuclear PLUS引导系统前执行。注意:为了进行NP的系统调用,文件NUCLEUS.H必须被包含; 3) 定义应用任务。如果使用了NP服务,NULCEUS.H必须包含; 4) 编译/汇编所有的应用软件,包括底层的系统初始化文件INT.*; 5) 连接INT,所有的应用目标文件以及NP库,以及任何必要的开发库; 6) 下载完整的应用映像到目标系统,Run it! 1.4.1 Application Initialization 典型结构: #include void Application_Initialize(void *first_available_memory) { /* Application-specific initialization of Nucleus PLUS objects, including the creation of tasks,mailboxes, queues, pipes, event groups, and memory pools. */ } 1.4.2 目标系统要求 NP大小:CISC系统上最大20Kb,RISC系统上40Kb;需要1.5Kb RAM。以上不包括应用程序,队列,管道或其他NP对象用到的内存。 NP不试图改变任何存在的数据元素,其容易被放在ROM中。对每个开发环境来说,NP都存在ROM可用的属性。 目标包括TRM(Target-Resident Monitor)的情况.... 1.4.3 配置选项 1.4.4 系统初始化 INT_INITIALIZE例程一般为NP中第一个执行的。对大部分目标环境,INT_INITIALIZE包含硬件复位向量,其负责所有目标相关的初始化,如建立不同的处理器控制寄存器,中断向量表,全局C数据变量,几个NP变量,系统堆栈指针。
系统初始化完成后,控制流进入NP高级初始化INC_INITIALIZE。注意,不会在返回系统初始化。
INC_INITIALIZE调用用户初始化例程,Application_Initialize() (简称AI)。AI负责初始化应用环境,如初始化应用任务,邮箱(mailboxes),队列,管道,信号灯,事件组,内存池,其他NP变量。
AI完成后,INC_Initialize()初始化任务调度。 1.4.5 内存的使用 NP提供给应用定制每个系统对象使用内存的能力。系统对象包括:任务,HISRs(硬件中断??),队列,管道,邮箱,信号灯,事件标志组,内存分区池,动态内存池,I/O驱动。每个系统对象需要一个控制结构(变量),某些对象需要附加的内存。
分配系统对象内存的几种方法:1) 最简单的办法,用C的全局数据结构来分配;2) 动态分配内存,可以从动态内存池,或分区内存池;3) 从目标系统的绝对物理地址分配内存。 1.4.6 执行的线程 NP有8种线程执行模式:初始化,系统错误,调度循环,任务,信号处理,用户ISR,LISR(Low-Level ISR), HISR(High-Level ISR)。 1.5 任务控制 任务是一个有特定目的的半独立程序。现代实时应用常为多任务,而且任务的重要性常发生变化。 任务状态:执行,准备,悬挂,终止,完成 抢占、放弃(同优先级轮转),时间片,动态创建(任务数量也许没限制,每个任务需要控制块和堆栈),确定性,堆栈检测,任务信息,优先级(0~255,0最高) "饥饿",高优先级总"Ready",则低优先级任务没机会执行。 1.6 动态内存分配 用户指定内存池大小;吃的内存为只有应用程序决定;支持变长度分配和释放。 分配规则:First Fit 支持"延迟"分配,FIFO或优先级确定顺序。 内存池可以动态创建。 确定性问题:分配~不确定,释放~确定 1.7 分区内存 分区内存池包含用户指定固定大小的内存区。其位置、大小有应用程序决定。在分区池中进行单个的分区的分配和释放。需要一些附加工作! 延迟(悬挂):无条件,超时,无悬挂 可以动态创建和消除 确定性:无需搜索,分配和释放分区的过程快速且固定(时间一定)。但其处理时间,受悬挂任务的优先级顺序等影响。 1.8 Mailboxes "邮箱"提供了低代价的简单信息传递机制。每个Mailbox能够储存4个32位的字(WORDS)。消息的发送和接收为值。发送消息时,需要将消息Copy到"邮箱",接受消息需要将消息Copy出邮箱。 延迟:无条件延迟,超时,无延迟 广播:Mailbox消息可以是广播的。 动态创建和删除 确定性:发送和接收消息的处理时间是常值的。但受悬挂任务的优先级影响。 1.9 队列 提供传送多消息的机制。消息的发送和接收为值。。。。 消息可以放队列头或尾。 消息大小:包括1个或多个32位字;支持固定或变长度的消息,队列创建时定义消息格式,变长度需要附加1个字。 1.10 管道 提供多消息传递机制;值;Copy入,Copy出;消息可以放在管道前或后。 消息大小:1个或多字节;固定或变长的消息被支持;创建时定义。 1.11 信号灯 信号灯提供应用程序关键部分的控制执行机制;NP提供的计数信号灯(可用信号灯)范围为0~4,294,967,294. 信号灯两个基本操作:获取、释放。 信号灯创建时指定初始值用于指示事件。
延迟:无条件,超时,无延迟 死锁:指当两个或更多的任务由于企图获取两个或更多信号灯而永远死锁。"阻止"(Prevention)是解决这个问题的好办法,具体依赖于应用,如每个任务不能占用1个以上的信号灯,或所有任务按相同顺序去获取多个信号灯,可选的"超时"设定等。 优先级反转:当高优先级的任务悬挂在低优先级拥有的信号灯上。该情况在不同优先级共享相同的保护资源时是客观存在的。此时,反转的时间有限或可估计时,是可接受的。然而,如果在优先级反转期间,低优先级任务被中等优先级任务抢占,则反转的时间则是不确定,该种情况应该避免,可以通过使得所有使用相同信号灯的任务具有相同的优先级。 (???这个和Vxworks有点不一样??) 1.12 事件组(Event Group) 指示某确定系统事件发生。一个事件由事件组中的单个位表示,该位叫事件标志位。每个事件组有个32个事件标志位。 用AND/OR去设置或清除事件标志。此外,当事件被接收后,事件标志可能被自动复位。 1.13 信号(Signals) 信号在某些方面和事件类似,然而,在操作上大不相同。时间标志的使用天生是同步的,任务指导指定的服务需要被给定后,才会去存取事件标志,判断其是否存在。信号操作为异步的,当信号存在时,任务预先指定的信号处理例程被执行,而任务被悬挂。每个任务可以处理32个信号。每个信号由单个位表示。 信号处理例程:必须在任何信号被处理前,指定信号处理例程。在信号处理例程内部遵守的约束和高级终端服务差不多。基本上,大部分NP服务都是可用的,但自身悬挂需要避免。 使能信号处理:缺省信号处理是Diable的。 信号清除:当引用信号处理例程后,信号自动被清除。信号处理例程不会被新的信号例程中断。此外,对信号进行恳求(solicited)请求,信号被清除。注意!!任务不能在信号恳求时悬挂。 多个信号:一旦信号例程开始,该任务的信号就被清除。信号处理不会被新的信号请求终止,在当前信号处理完成后处理新的信号。先前发送的相同信号被抛弃。 1.14 时钟 绝大部分实时系统需要周期时间间隔的处理。每个NP任务有一个内建的时钟,该时钟用于提供任务睡眠或系统调用悬挂超时。 Ticks(嘀嗒):时间的基本单位。每个Tick对应单个硬件时钟中断。每个Tick表示的实际时间量有用户编程设定。 错误边界:时钟请求可能比实际的时间早一个Tick,这是因为在时钟请求后,Tick可以马上发生。 硬件需求:NP需要周来自迎接的周期时钟中断。如果没有这个中断,时钟工具将不可用。然而,其他的NP工具不会因为缺少时钟工具而被影响(!!强,J) 连续时钟:NP维护一个连续技术Tick时钟,其最大值为4,294,967,294 (232),达到最大值后,自动复位。该连续时钟被保留,不用于其他应用使用,可以被应用在任何时候读或写。 任务时钟:每个任务有一个内建时钟能够。用于任务睡眠或悬挂超时,此外,对需要时间片的任务,有个时间片时钟可用。 应用时钟:NP提供给应用可编程时钟。当该时钟到时,执行用户指定的例程。该例程作为高级中断服务例程执行。因此,自悬挂请求是不允许的。此外,处理时间应该尽可能的短。 重新调度:当时钟过期,预先指定例程被执行。执行结束后,时钟可以消失或重新调度。如果重新调度值为零,则初次过期后,时钟消失。如果不为零,则重新调度时钟,设定为这个调度值。
Enable/Disable:在创建期间时钟被自动使能。可以被动态的使能或Diable。 1.15 中断 中断是提供队内部或外部事件立刻反应的机制。当中断发生时,处理器悬挂当前执行路径,把控制流转移到中断服务程序(ISR)。一个中断的精确操作是跟处理器相关。 NP支持可管理或不可管理的ISRs。可管理ISR是指那些不需要保存和恢复上下文的情况,而不可管理是指其负责保存和恢复所用泳道的寄存器。可管理的ISR可以用C或汇编写成;而不可管理的ISR几乎都是汇编写成。 保护:对于所有的实时内核,中断总是产生一些感兴趣的问题。NP当然也不例外。主要问题来自于ISRs需要存取的NP的服务。表面上,这个看起来不是个问题,然而,其需要在系统服务代用期间,防止同时被ISR存取。最简单的方法是在终端服务期间锁住中断。 对中断响应快速实时系统的基础。因此,锁住中断来保护内部数据是不被希望的。NP处理这个问题是通过把应用ISR分为高级和低级部分。
低级ISR(LISR):LISR和正常ISR一样,使用当前的堆栈。NP在调用LISR前保存上下文,执行LISR后恢复上下文。因此,LISR可用C写,而且可以调用其他C例程。然而,仅有少量的NP服务对LISR可用。如果中断处理例程需要其他的NP服务,则高级ISR(HISR)被激活。NP支持多LISR嵌套。 高级ISR(HISR):HISR被动态创建或删除。每个HISR拥有自己的堆栈和自己的控制块,其内存有应用提供。当然,在LISR激活前,HISR必须被创建。 由于HISR有自己的堆栈和控制块,当其存取正在被存取的NP数据结构时,可以被临时阻塞。 HISR可以存取绝大部分NP服务,除了自悬挂服务。此外,由于HISR不能悬挂NP服务,其悬挂参数必须总是被设定为NU_NO_SUSPEND。 HISR有3个优先级可用,如果在处理低优先级的HISR时,高优先级的HISRj激活,则低优先级的被"抢占",这个任务抢占是一样的。相同优先级的HISR根据激活顺序,依次执行(注意!不是轮转哦!!)在正常的任务调度以前,所有激活的HISR被执行。 每个HISR有个激活计数器。该计数器用于保证每个激活都被执行一次。 1.16 I/O驱动 (略) 2004/4 (后来懒,就没有写下去了,:)
|