Nucleus PLUS的启动、运行线程和中断处理

nucleus系统是实时嵌入式操作系统,具有实时、任务抢先、多任务内核,其中95%的代码由C语言写成,极易移植,开放的源码使得配置和裁剪方便,再加上体积小(全部二进制映像可仅20K)、响应快速等特性,使得Nucleus PLUS得到广泛应用。另外,所谓的实时指的是对外部或者内部的事件在正确的时间内必须得到正确的响应,而不仅仅指的是“立即能够响应”。

(一)Nucleus PLUS启动流程

INT_Initialize 子程序在Nucleus PLUS 系统中是最先运行的。负责所有与目标硬件相关的初始化。INT_Initialize 完成后将控制权转移到高级Nucleus PLUS 初始化子程序INC_Initialize上并不再返回。INC_Initialize调用所有的Nucleus plus组件初始化函数、调用Application_Initialize创建用户任务等对象,最后将控制权交给调度函数TCT_schedule,系统启动完毕。

嵌入式实时操作系统内核Nucleus PLUS的启动过程如图1所示。其中

1,板级初始化INT_INITIALIZE()

在设置中,当系统reset后跳至执行地址0x0000 0000处开始执行,因此将函数INT_INITIALIZE()入口置于该地址(INT_Reset_Addr DCD  INT_Initialize)引导系统的运行,该函数一般在INT.S或者是INT_PID.S中。INT_Initialize需要根据具体的硬件环境做出修改,其主要执行功能:

1)将编译出来的已经初始化的数据从ROM中复制到RAM中,同时在RAM中建立ZI数据段,未初始化的数据;

2)初始化异常中断向量表;

3)设置处理器各运行模式的数据堆栈,计算出可用的存储器的首地址(first_available_memory);

4)时钟中断和一些硬件中断的设置;

5)将控制权转移到INC_INITIALIZE;

2,操作系统初始化(INC_Initialize(first_available_memory))

主要是完成邮箱、队列、管道、信号量、事件集等Nucleus PLUS软件组件的初始化;

3,应用程序初始化(Application_Initialize (first_available_memory))

主要是完成用户定义的应用程序初始化,如创建内存池,创建任务、创建信号量、创建中断、编写用户应用程序等。用户任务可事先定义好存于一个表中,Application_Initialize 根据该表创建所有的任务。

4,任务调度TCT_schedule

会按照任务优先级顺序调度所有的任务去完成各个任务基本的初始化,然后进入就绪或挂起状态。最后TCT_schedule会将控制权交给优先级最高的任务,系统任务开始运行。

图1 Nucleus PLUS 初始化流程

(二)Nucleus PLUS运行线程

一个Nucleus PLUS 系统组件或者应用程序总是八个可能运行线程中的一个。他们是:

1) 初始化(Initialization)线程

初始化线程是系统运行的第一个线程。初始化线程的起始是为INT_Initialize,在Application_Initialize 函数返回后中止,控制权转移至调度循环(Scheduling Loop)线程。

2) 系统错误(Ssytem Error)线程

这个线程在函数ERC_System 被调用时执行。系统启动、运行过程中有可能发生系统错误,它们中大多数在初始化期间被跟踪,堆栈溢出则在任务和HISR 运行过程中产生。默认情况,系统错误是致命的,因此该线程会暂停系统运行,详细的系统错误代码见Nucleus PLUS Reference。

3) 调度循环(Scheduling Loop)线程

调度循环线程的入口是TCT_Schedule。这个线程将CPU控制权转移给最高优先级的HISR 或

就绪状态的任务。当没有任务或HISRs 就绪时,就是TCT_Schedule 无限的循环。工程中为了省电,一般会创建一个优先级最低的Idle任务,当没有其他任何任务或者HISR要执行时,idle任务就会被调度使得系统进入睡眠状态。

4) 任务(Task)线程

每个任务有它自己的堆栈核控制结构,其入口在任务创建时指定。任务线程对访问Nucleus PLUS 服务没有任何限制。

5) 信号处理(Signal Handler)线程

信号处理线程运行在相关任务线程的顶端。信号处理器线程对Nucleus PLUS 服务访问有限制,主要限制就是信号处理线程不允许自挂起。

6) 用户中断处理子程序(User ISR)线程

此线程负责保存和恢复所有使用的寄存器。用户中断服务子程序线程是典型的少量汇编语言子程序,入口可直接挂在中断向量上。对此类型线程,Nucleus PLUS 服务完全不受限。

7) LISR线程

低级中断服务子程序允许Nucleus PLUS 在中断处理中保存和恢复所有有需要的寄存器。LISR 线程最重要的任务就是active_HISR 服务,其对Nulceus PLUS 服务访问受限,例如,如果某中断的处理需要切换任务就只能去激活HISR并在HISR中实现。下列服务从 LISRs 访问有效:

NU_Activate_HISR

NU_Local_Control_Interrupts

NU_Current_HISR_Pointer

NU_Current_Task_Pointer

NU_License_Information

NU_Retrieve_Clock

8) HISR线程

高级中断服务子程序是Nucleus PLUS 中断处理的第二部分。HISR 线程像任务线程一样被调度,可以访问大多数Nucleus PLUS 服务,不允许自挂起请求。HISR 线程程序入口点在HISR 创建期间确定。

(三)Nucleus中断处理

Nucleus PLUS 既支持可控(managed)也支持不可控(unmanaged)ISRs。可控的ISR 就是用户不需要存储和释放上下文信息,不可控ISRs 指的是用户要对保存和恢复所有使用寄存器负全责。可控ISRs 可以用C 或汇编编写,不可控ISRs 一般都用汇编。

对中断能够快速响应是RTOS系统的基础,Nucleus PLUS通过将ISR分成低级和高级两个部分来保证系统对中断的快速响应的同时保护系统服务的数据结构不受破坏。所以Nucleus PLUS的中断处理类似于Linux的两个半部中断处理机制。

低级中断处理运行在LISR线程,可由C语言编写或者被其他C函数调用。Nucleus PLUS调用/退出LISR之前会保存/恢复上下文。LISR支持中断嵌套,任务就是快速响应中断,然后激活HISR服务。

HISR完成中断的大部分处理任务,必须预先创建,其优先级分为3级,支持抢占,每个HISR都有独立的堆栈和控制块。

Nucleus PLUS的启动、运行线程和中断处理

时间: 2024-10-15 08:22:12

Nucleus PLUS的启动、运行线程和中断处理的相关文章

JVM 内部运行线程介绍

线程 所属 说明 Attach Listener JVM           Attach Listener线程是负责接收到外部的命令,而对该命令进行执行的并且吧结果返回给发送者.通常我们会用一些命令去要求jvm给我们一些反馈信息,如:java -version.jmap.jstack等等.如果该线程在jvm启动的时候没有初始化,那么,则会在用户第一次执行jvm命令时,得到启动. Signal Dispatcher JVM         前面我们提到第一个Attach Listener线程的职

老李推荐: 第8章4节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 1

老李推荐: 第8章4节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-启动AndroidDebugBridge 上一节我们看到在启动AndroidDebugBridge的过程中会调用其start方法,而该方法会做2个主要的事情: 715行startAdb:开启AndroidDebugBridge 722-723行:初始化android设备监控并启动DeviceMonitor设备监控线程. 其中第一点我们上一小节已经做了详尽分析了,那么我们往下就去分析下第2点. Dev

第8章6节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动Monkey

大家可能会觉得奇怪,为什么启动目标设备端的monkey进程会放在"运行测试脚本"这一节之后来阐述. 纵观前面整个MonkeyRunner的启动流程,我们看到并没有提及到monkey进程启动的地方.那么就奇怪了,monkey是什么时候被MonkeyRunner启动起来的呢? 我们的测试脚本一开始时几乎毫无例外的都需要执行一个调用:MonkeyRunner.waitForConnection(),如果有多个设备连接到主机的话还需要指定设备序列号,还可以指定等待连接的Timeout时间,比如

第8章3节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge

用户在命令行运行monkeyrunner命令来执行测试脚本的时候ADB服务器有可能还没有起来,AndroidDebugBridge类的主要作用之一就是去开启一个新的进程来启动ADB服务器,这样我们的测试脚本才能发送命令给ADB服务器去驱动目标设备做事情,比如安装或者删除待测应用的安装包等. MonkeyRunner在启动的过程中会牵涉到一系列的调用并关联到不同的类来做不同的事情. 图8-3-1 启动AndroidDebugBridge涉及的类关系 以上类图列出了启动AndroidDebugBri

第8章2节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-解析处理命令行参数

MonkeyRunnerStarter是MonkeyRunner启动时的入口类,因为它里面包含了main方法.它的整个启动过程主要做了以下几件事情: 解析用户启动MonkeyRunner时从命令行传输进来的参数: 因为MonkeyRunner需要根据指定的参数才能做事情,比如输入的一个需要执行的脚本.如果确实不知道任何参数的话它就会进入MonkeyRunner的交互模式,其实就是Jythong的交互模式,让用户可以边写代码边执行 启动AndroidDebugBridge: 其实就是启动ADB服务

如何创建和启动一个线程?

原文转自:http://www.tqcto.com/article/recommend/137.html 一.定义线程 1.继承java.lang.Thread类. 此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法:否则,该方法不执行任何操作并返回. Thread 的子类应该重写该方法. 2.实现java.lang.Runnable接口. public  vo

启动一个线程是用run()还是start()

启动线程肯定要用start()方法.当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行.这并不意味着线程就会立即运行.当cpu分配给它时间时,才开始执行run()方法(如果有的话).start()是方法,它调用run()方法.而run()方法是你必须重写的. run()方法中包含的是线程的主体. 继承Thread类的启动方式: 1 public class ThreadStartTest { 2 public stati

如何定义,创建,启动一个线程

如何定义一个线程?第一通过继承java.lang.Thead类来定义一个线程.第二,通过实现java.lang.runnable接口定义一个线程. 为什么不采用run方法直接启动线程呢?线程是由操作系统来管理的,操作系统启动一个线程,会调用本地的一个代码,这个本地的代码会使系统初始化一个新的线程,由新的线程来启动Thead类中的run方法,所以要通过start方法来启动一个线程 两种定义线程的方式都有哪些优缺点?

Nginx学习笔记02Nginx启动运行与命令行

1.1. Nginx启动运行 Nginx的配置文件的一个简单的例子. conf目录下的nginx.cfg文件的内容如下: #worker进程个数. worker_processes  1; #事件模块. events { worker_connections  1024; } #http模块. http { include       mime.types; default_type  application/octet-stream; #在8000端口监听. server { listen