基于ARM的nucleus plus的执行
来源:互联网 发布:阿里云邮件推送 编辑:程序博客网 时间:2024/06/08 19:44
一.ARM处理器的运行模式
ARM处理器在嵌入式系统中应用广泛,共有7种运行模式:
处理器模式
描述
用户模式
正常程序执行的模式
快速中断模式(FIQ)
用于告诉数据传输和通道处理
外部中断模式(IRQ)
用于通常的中断处理
特权模式(Supervisor ,SVE)
供操作系统使用的一种保护模式
数据访问中止模式(Abort)
用于虚拟存储以及存储保护
未定义指令中止模式(Undefined)
当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真
系统模式
用于运行特权级的操作系统任务
各种不同异常模式下使用的寄存器组:
运行模式位M[4:0]的具体含义
M[4:0]
处理器模式
可访问的寄存器
0b10000
用户模式
PC,CPSR,R0-R14
0b10001
FIQ模式
PC,CPSR, SPSR_fiq,R14_fiq-R8_fiq, R7~R0
0b10010
IRQ模式
PC,CPSR, SPSR_irq,R14_irq,R13_irq,R12~R0
0b10011
管理模式
PC,CPSR, SPSR_svc,R14_svc,R13_svc,,R12~R0,
0b10111
中止模式
PC,CPSR, SPSR_abt,R14_abt,R13_abt, R12~R0,
0b11011
未定义模式
PC,CPSR, SPSR_und,R14_und,R13_und, R12~R0,
0b11111
系统模式
PC,CPSR(ARM v4及以上版本), R14~R0
二.ARM处理器的异常中断
在ARM指令执行的过程中,通常有三种执行的方式:
1.顺序执行,每执行一个指令,程序计数器寄存器(PC)增加;如果执行ARM指令,程序计数器寄存器(PC)的值加4,如果执行Thumb指令,PC值加两个字节;
2.执行跳转指令,如B、BX、BL、BLX指令,程序可以跳转到特定的地址标号处执
3.异常中断发生时,程序跳转到中断程序中执行,在处理完中断以后,程序返回到发生中断的指令的下一条指令处执行,在进出中断时要保存现场。
ARM体系中异常中断的种类
ARM体系结构所支持的异常及具体含义如表所示。
ARM体系结构所支持的异常
异常类型
具体含义
复位(Reset)
当处理器的复位电平有效时,产生复位异常,程序跳转到复位异常处理程序处执行。复位异常中断通常用在下面两种情况:系统加电和系统复位时。
未定义指令
(undefined instruction)
当ARM处理器或协处理器遇到不能处理的指令时,产生未定义指令异常。可使用该异常机制进行软件仿真。
软件中断
(softwart interrupt SWI)
由用户定义,该异常由执行SWI指令产生,可用于用户模式下的程序调用特权操作指令。在实时操作系统中可使用该异常机制实现系统功能调用。
指令预取中止
(Prefech Abort)
若处理器预取指令的地址不存在,或该地址不允许当前指令访问,存储器会向处理器发出中止信号,但当预取的指令被执行时,才会产生指令预取中止异常。
数据访问中止
(Data Abort)
若处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时,产生数据中止异常。
IRQ(外部中断请求)
当处理器的外部中断请求引脚有效,且CPSR中的I位为0时,产生IRQ异常。系统的外设可通过该异常请求中断服务。
FIQ(快速中断请求)
当处理器的快速中断请求引脚有效,且CPSR中的F位为0时,产生FIQ异常。
当系统进入异常时,转而执行不同向量地址的指令,如下表所示:
异常向量表
地址
异常
进入模式
0x0000,0000
复位
管理模式
0x0000,0004
未定义指令
未定义模式
0x0000,0008
软件中断
管理模式
0x0000,000C
中止(预取指令)
中止模式
0x0000,0010
中止(数据)
中止模式
0x0000,0014
保留
保留
0x0000,0018
IRQ
IRQ
0x0000,001C
FIQ
FIQ
异常优先级
当多个异常同时发生时,系统根据固定的优先级决定异常的处理次序。异常优先级由高到低的排列次序如表所示。
异常优先级
优先级
异 常
1(最高)
复位
2
数据中止
3
FIQ
4
IRQ
5
预取指令中止
6(最低)
未定义指令、SWI
对异常的响应
当一个异常出现以后,ARM微处理器会执行以下几步操作:
1、将下一条指令的地址存入相应连接寄存器LR,以便程序在处理异常返回时能从正确的位置重新开始执行。若异常是从ARM状态进入,LR寄存器中保存的是下一条指令的地址(当前PC+4或PC+8,与异常的类型有关);若异常是从Thumb状态进入,则在LR寄存器中保存当前PC的偏移量,这样,异常处理程序就不需要确定异常是从何种状态进入的。例如:在软件中断异常SWI,指令 MOV PC,R14_svc总是返回到下一条指令,不管SWI是在ARM状态执行,还是在Thumb状态执行。
2、将CPSR复制到相应的SPSR中。
3、根据异常类型,强制设置CPSR的运行模式位。
4、强制PC从相关的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处。
还可以设置中断禁止位,以禁止中断发生。
如果异常发生时,处理器处于Thumb状态,则当异常向量地址加载入PC时,处理器自动切换到ARM状态。
ARM微处理器对异常的响应过程用伪码可以描述为:
R14_<Exception_Mode> = Return Link
SPSR_<Exception_Mode> = CPSR
CPSR[4:0] = Exception Mode Number
CPSR[5] = 0 ;当运行于ARM工作状态时
If <Exception_Mode> == Reset or FIQ then
;当响应FIQ异常时,禁止新的FIQ异常
CPSR[6] = 1
CPSR[7] = 1
PC = Exception Vector Address
从异常返回
异常处理完毕之后,ARM微处理器会执行以下几步操作从异常返回:
1、将连接寄存器LR的值减去相应的偏移量后送到PC中。
2、将SPSR复制回CPSR中。
3、若在进入异常处理时设置了中断禁止位,要在此清除。
可以认为应用程序总是从复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。如下表所示,表中总结了进入异常处理时保存在相应R14中的PC值,及在退出异常处理时推荐使用的指令。
表2-4 异常进入/退出
返回指令
以前的状态
注意
ARM R14_x
Thumb R14_x
BL
MOV PC,R14
PC+4
PC+2
1
SWI
MOVS PC,R14_svc
PC+4
PC+2
1
UDEF
MOVS PC,R14_und
PC+4
PC+2
1
FIQ
SUBS PC,R14_fiq,#4
PC+4
PC+4
2
IRQ
SUBS PC,R14_irq,#4
PC+4
PC+4
2
PABT
SUBS PC,R14_abt,#4
PC+4
PC+4
1
DABT
SUBS PC,R14_abt,#8
PC+8
PC+8
3
RESET
NA
-
-
4
注意:
1、在此PC应是具有预取中止的BL/SWI/未定义指令所取的地址。
2、在此PC是从FIQ或IRQ取得不能执行的指令的地址。
3、在此PC是产生数据中止的加载或存储指令的地址。
4、系统复位时,保存在R14_svc中的值是不可预知的。
在应用程序中安装异常中断处理程序:
1)地址0x0处为ROM的情况,当地址0x0处为ROM时,在异常中断向量表中,可以使用数据读取指令LDR直接向程序计数器PC中赋值
INT_Vectors
LDR pc,INT_Table ;0x0000
LDR pc,(INT_Table + 4) ;0x0004
LDR pc,(INT_Table + 8) ;0x0008
LDR pc,(INT_Table + 12) ;0x000C
LDR pc,(INT_Table + 16) ;0x0010
LDR pc,(INT_Table + 20) ;0x0014
LDR pc,(INT_Table + 24) ;0x0018
LDR pc,(INT_Table + 28) ;0x001C
EXPORT INT_Table
INT_Table
INT_Initialize_Addr DCD INT_Initialize
Undef_Instr_Addr DCD Undef_Instr_ISR
SWI_Addr DCD SWI_ISR
Prefetch_Abort_Addr DCD Prefetch_Abort_ISR
Data_Abort_Addr DCD Data_Abort_ISR
Undefined_Addr DCD 0 ; NO LONGER USED
IRQ_Handler_Addr DCD INT_IRQ_Parse
FIQ_Handler_Addr DCD INT_FIQ_Parse
2)地址0x0处为RAM的情况,中断向量表还必须把中断向量表从ROM中复制到RAM的地址0x0开始的存储空间,如以下代码:
MOV v5,#0
ADR v6,INT_Vectors
LDMIA v6!,{a1-v4} ;复制中断向量表(8 words)
STMIA v5!,{a1-v4}
LDMIA v6!,{a1-v4} ;复制保存各中断处理函数地址。(8 words)
STMIA v5!,{a1-v4}
三.多功能ARM开发板PB_ARM926EJ-S上的中断功能
该ARM开发板支持多种功能,PCI接口、以太网口、音频设备、USB接口、LCD接口、外扩内存卡的功能,目前我们现在主要使用的功能是时钟(提供nucleus的系统时钟),UART串口(提供系统的输入与输出),PS/2键盘(提供系统的输入)。
ARM926EJ-S提供了两种中断信号:IRQ和FIQ,其实现的一般机制是,有一个向量中断控制器接收外部设备的中断信息,然后产生IRQ或者是FIQ中断信号,引导软件中断的执行。
开发板上的中断分为两组,主中断控制器和二级中断控制器,该两组没有主次之分,只是触发方式,即当中断发生后通知系统的顺序不一样而已。当有中断发生时,中断控制器状态位相应位置1,该位表示某个中断发生。
开发板上主要的寄存器如下表所示:
ADDRESS
Name
Access
Description
0x10140000
PICIRQStatus
READ
IRQ status register
0x10140010
PICIntEnable
READ/WRITE
Interrupt enable register
0x10140014
PICIntEnClear
WRITE
Interrupt enable clear register
在PICIRQStatus中,常用的中断状态位如下所示(如相应为置1则表示对应中断发生,应该调用相应的中断处理函数):
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
SCI0
UART2
UART1
UART0
SSP
RTC
GPIO3
GPIO2
GPIO1
GPIO0
TIMER23
TIMER01
CommTX
CommRX
SoftWare
WDOG
在当前的系统中,我们用到了时钟中断,串口中断,还有在二级中断中的键盘中断(上表中暂未列出)。
四.Nucleus 系统简述
nucleus系统是实时嵌入式操作系统,具有占先、实时、多任务的内核,其中95%的代码是由C语言组成的,极易移植,广泛的应用在多种处理器当中;同时,nucleus开发包是开放源码的,方便开发工程师的配置,再加上nucleus的快速响应等其他特性,得到了广泛的应用。
4.1.Nucleus系统的初始化过程
1. 最先执行的函数是INT_INITIALIZE,在该函数中负责完成与目标开发板对应的所需要的硬件的初始化,如一些ARM上的控制寄存器,中断向量表,系统堆栈等;该函数一般在INT.S或者是INT_PID.S中;
2. 在INT_INITIALIZE执行完后,系统转入到nucleus上层的初始化中去,将控制权交给上层的函数INC_INITIALIZE,在该函数中完成nucleus各组件的初步的初始化工作,如线程、邮箱、管道、信号量、事件、定时器等,它的初始化只是给一些全局变量赋空值;
3. 在INC_INITIALIZE中,在各组件初始化完之后,会调用一个用户自定义函数Application_Initialize(),在该函数中系统会调用用户真正的应用代码,如内存池的创建、建立任务、建立消息队列等等。总之,Application_Initialize()中的函数是用户真正需要建立的代码;
4. 在执行完Application_Initialize()之后,系统进入调度函数TCT_Schedule(),然后整个nucleus系统就运转起来。
如图所示:
INT_INITIALIZE
INC_INITIALIZE
各组件初始化
Application_Initialize()
TCT_Schedule()
系统执行
4.2 INT_INITIALIZE
针对我们的开发板,由于INT_INITIALIZE是系统运行的第一个函数,因此,在设置中,当系统reset后,此时执行地址为0x0000 0000中的代码,该地址中的代码跳转到函数INT_INITIALIZE()的地址,然后引导系统的运行。
INT_INITIALIZE() 函数主要执行的功能:
1) 将编译出来的已经初始化的数据从ROM中复制到RAM中,同时在RAM中建立ZI数据段,未初始化的数据;
2) 初始化异常中断向量表;
3) 设置ARM处理器对应的各种模式的nucleus的数据堆栈;
4) 设置对应的ARM开发板的硬件设置,在我们的需求中主要是一些中断的设置;
5) 将控制权转移到INC_INITIALIZE;
五.Nucleus在ARM开发板上的实现
Nucleus在我们的ARM开发板上能够运行起来,首先要使nucleus的硬件相关部分能够与开发板相互对应,由于现有的nucleus版本已经在ADS1.2环境下编译通过,所以就不用费力的更改汇编函数,只需要修改涉及到具体ARM板的寄存器参数的设置,其中主要的是操作系统运行所需要的时钟中断的设置。
由第二部分的表格可知,时钟中断在PICIRQStatus中的第四个bit置位,当ARM开发板上的时钟中断发生时,产生IRQ中断,相应位置位。
在具体的设置当中,使用了TIMER0产生的时钟中断,其基地址是0x101e2000,其偏移地址0x08(TimerControl)是时钟控制寄存器,在其中设置相应的模式,如允许时钟运行模式,将时钟设
31:8
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3:2
Bit 1
Bit 0
Reserved
TimerEn
TimerMode
IntEnable
reserved
TimerPre
TimerSize
OneShot
0- Disable
1- En
0- freerun
1- periodic
0- disa
1- IntEn
分频
0- 16bit
1- 32bit
0- wrap
1- oneshot
置成周期性时钟模式,允许时钟中断模式等。完成设置后,运行,当有时钟中断发生时,ARM产生IRQ中断,通过状态位判断后,nucleus调用相应的时钟中断函数进行处理,维持nucleus系统的时钟相关性功能的运行。
六.Nucleus中断机制的实现
在nucleus系统初始化时,可参看文件int.s或者是int_pid.s,首先完成中断向量的配置,在IRQ中断处理过程中,由于IRQ中断有多个中断源,需要处理各种子程序,通过判断PICIRQStatus中断标志位后,确定具体的中断源,在调用相应的中断处理函数。以上是一般的中断处理流程。
Nucleus提供了两种中断机制,管理的中断和非管理的中断。
管理的中断需要向操作系统注册该中断向量,它与下文提到的非管理中断的主要区别是,该种中断的上下文保护由nucleus系统来完成保护;中断产生后通过该中断向量注册的低级中断服务程序(LISR)激活高级的中断服务程序(HISR)。LISR主要完成硬件的中断的处理,及激活HISR。HISR的调度类似于任务,具有优先级,优先级比一般的任务要高,可以使用大多数的nucleus系统调用;
非管理的中断,该中断函数的地址直接的被放置到系统的中断向量表上,上下文的保存和恢复都需要用户自己来做,该种中断一般不能嵌套,否则可能会引起堆栈的出错,而且该种中断函数可以使用的nucleus系统调用比较少。
使用管理的中断的系统函数如下所示:
NU_Register_LISR(INT vector, //中断向量
VOID (*new_lisr)(INT), //低级中断处理函数
VOID (**old_lisr)(INT)); //保存的中断处理函数
NU_Create_HISR(NU_HISR *hisr, CHAR *name, //创建高级中断处理函数
VOID (*hisr_entry)(VOID), OPTION priority,
VOID *stack_address, UNSIGNED stack_size)
NU_Activate_HISR(NU_HISR *hisr) //由低级中断激活高级中断。
TCC_Dispatch_LISR(INT vector) //该函数应用在int.s或者int_pid.s中,负责根据中断向量号,索引到不同的中断函数执行。
举个例子:
VOID (*old_lisr)(INT);
void Lisr_uart0(INT vector_number);
void Hisr_uart0_proc(void);
NU_HISR Hisr_uart0;
NU_Create_HISR(&Hisr_uart0,"HISR_TEST",Hisr_uart0_proc,2,pointer,1000); //高级中断函数
NU_Register_LISR(21,Lisr_uart0,&old_lisr);//登记低级中断函数
void Lisr_uart0(INT vector_number) //登记的低级中断函数
{
unsigned int base;
//////////////////////////////////////////
base = UART0_BASE;
uart_data = HW_REG(base,0x00);
l++;
/////////////////////////////////////////
NU_Activate_HISR(&Hisr_uart0); //激活高级中断函数
}
void Hisr_uart0_proc(void) //高级中断函数
{
……
;
……
}
除了以上常用的函数外,用户还需要自己定义低级中断函数和高级中断函数。
http://blog.csdn.net/lieye_leaves/article/details/7723318
- 基于ARM的nucleus plus的执行
- 基于ARM的nucleus plus的执行
- Nucleus PLUS嵌入式操作系统的简单介绍
- Nucleus PLUS的启动、运行线程和中断处理
- Nucleus PLUS的启动、运行线程和中断处理
- Nucleus PLUS的启动、运行线程和中断处理
- Nucleus PLUS
- 为提高系统Nucleus OS 模块间的独立性,对Nucleus Plus内核模块分析和优化的归纳
- QNX、RTLinux、uC/OS-II、Nucleus Plus、VRTX、VxWorks、eCos的相互比较
- QNX、RTLinux、uC/OS-II、Nucleus Plus、VRTX、VxWorks、eCos的相互比较
- Nucleus PLUS介绍
- Nucleus PLUS任务调度
- Nucleus PLUS简介
- Nucleus PLUS任务调度
- nucleus plus代码学习
- nucleus plus学习总结
- MTK的OS是Nucleus
- MTK的OS是Nucleus
- 自写疯狂猜拳
- 互联网之子–Aaron Swartz
- CentOS编译OpenJDK
- 数据结构实验2——链表
- javascript var
- 基于ARM的nucleus plus的执行
- Print all nodes that are at distance k from a leaf node
- 用python写pintool
- 网络基本功(三):细说VLAN与Trunk
- 《设计模式之禅》笔记16 -- 组合模式
- myeclipse2014关闭html,jsp等页面的可视化编辑器
- Spring Framework源码(八):SpringMVC概览
- 设计模式几点原则
- 遍历可变数组的同时删除元素