功能号放在一个寄存器。在通用的 SWI 异常中断处理程序读取该寄存器值,决
定需要执行的操作,但有些 SWI 处理程序需要 SWI 指令的 24位立即数,因而上
述两种方法常常组合使用。
在操作系统中通常使用一个 SWI 功能号和一个寄存器来提供很多的 SWI 功能调
用。这样可以将其他的 SWI 功能号留给用户使用。在 DOS 系统中,DOS 提供功能
调用是 INT 21H ,这时通过指定寄存器 AX 的值,可以实现很多不同的功能调用。
ARM 体系中semihost 的实现也是一个例子。ARM 程序使用 SWI 0x123456 来实现
semilhost 功能调用;Thunb 程序使用SWI 0xAB 来实现 semihost 功能调用。在
下面的例子中,将子程序 WRITEC (unsigned op,char *c)映射到 semihost
功能调用,具体 semihost SWI 的子功能号通过参数 op 传递。
程序 6.3 从应用程序中动态调用 SWI 功能
#ifdef_thumb
#else
#define semiSWI 0x123456
#endif
__swi (semiSWI) void semibosting (unsigned op,char *c);
Void write_a_character (int ch)
{
char tempth=ch;
writec (&tempch);
}
2.FIQ 和IRQ 异常中断处理程序
ARM 提供的FIQ和 IRQ 异常中断用于外部设备向 CPU 请求中断服务。这两个异常中断的引脚
都是低电平有效的。当前程序状态寄存器 CPSR 的 1 控制位可以屏蔽这两个异常中断请求;
当程序状态寄存器 CPSR由 1 控制位位 0 时,CPU正常响应 FIQ 和IRQ 异常中断请求。
FIQ 异常中断为快速异常中断,它比 IRQ 异常中断优先级高,这主要表现在下面的两个方
面:
● 当 FIQ 和IRQ 异常中断同时产生时,CPU 先处理 FIQ 异常中断。
● 在 FIQ 异常中断处理程序中 IRQ 异常中断被禁止。
由于 FIQ 异常中断通常用于系统对于响应时间要求比较苛刻的任务,ARM 体系在设计上有
一些特别的安排,以尽量减少 FIQ 异常中断响应时间。FIQ 异常中断的中断向量为 0x1c,位
于中断向量表的最后。这样 FIQ 异常中断处理程序可以直接放在地址 0x1c 开始的存储单元,
这种安排省掉了中断向量表的跳转指令,从而也就节省了中断响应时间。当系统中存在
cache 时,可以把 FIQ 异常中断向量以及处理程序一起锁在 cache 中,从而大大地提高了
FIQ 异常中断响应时间。除此之外,与其他的异常模式相比,FIQ 异常中断还有额外的 5 个
物理寄存器,这样在进入 FIQ 处理程序时可以保存这 5 个寄存器,从而也提高了 FIQ 异常中
断的执行速度。
在有些 IRQ/FIQ 异常中断处理程序中,允许新的 IRQ/FIQ 异常中断,这时将需要一些特
别的操作保证“老的”异常中断的寄存器不会“新的”异常中断破坏,这种 IRQ/FIQ 异常中
断处理程序称为可重入的异常中断处理程序。否则称为不可重入的异常中断处理程序。
① 不可重入的 IRQ/FIQ 异常中断处理程序
对于 C 语言不可重入的 IRQ/FIQ 异常中断处理程序可以使用关键词_irq来说明。关键词
_irq 可以实现下面的操作:
● 保存 APCS 规定的被破坏的寄存器。
● 保存其他中断处理程序中用到的寄存器。
● 同时将(LD-4)赋予程序计数器 pc 实现中断处理程序的返回,并且恢复 CPSR 寄
存器的内容。
当 IRQ/FIQ异常中断处理程序调用了子程序时,关键词_irq可以使 IRQ/FIQ 异常中断
处理程序返回时从其数据栈中读取 LR_irq 值,并通过 SUBS PC,LR,#4 实现返回。程序
6.4 说明的关键词_irq 的作用,其中列出了 C 语言程序及其对应的汇编程序,两个 C
语言程序中,第 1 个使用关键词_irq 声明,第2个没有使用关键词_irq声明。
程序 6.4 关键词_irq 的作用
;第1 个程序使用关键词_irq 声明
_irq void IRQHandler (void)
{
Volatile unsigned int *base=(unsigned int *)0x8000000;
If (*base 1)
{
//调用相应的 C 语言处理程序
C_int_Handler ();
}
//清除中断标志
*(base=1)=0;
}
;第1 个C 语言程序对应的汇编程序
IRQHandler PROC
STMFD sp!,(r0-r4,r12,lr)
MOV r4,#0x8000000
LDR r0,(r4,#0)
SUB sp,sp,#4
CMP r0,#1
BLEQ Q_int_handler
MOV r0,#0