TQ2440裸机中断(软中断swi)
2021-09-30 来源:eefocus
1. 引出:
一般情况下,比如调用open系统调用,大家会说此时系统陷入了内核态,继而调用内核的sys_open来进行实际的open处理,但是为什么用户态调用了open就会陷入内核态呢?所谓的用户态及内核态究竟是什么呢?
2. S3C2440软中断
ARM9处理器有7种工作模式,软中断,通俗的说就是为了从其他工作模式切换到管理模式(在管理模式,可以使用的资源最多),处理器提供软中断,主要是为了支持操作系统的系统调用功能。
ARM体系 CPU的7种工作模式:
· 用户模式(usr): ARM处理器正常的程序执行状态(对应于LINUX的用户态)
· 快速中断模式(fiq): 用于高速数据传输或通道处理
· 中断模式(irq):用于通用的中断处理
· 管理模式(svc):操作系统使用的保护模式(对应于内核态)
· 数据访问终止模式(abt): 当数据或指令预取时进入该模式,可用于虚拟存储及存储保护
· 系统模式(sys) :运行具有特权操作系统任务
· 未定义指令中止模式(und): 当为定义的指令执行时进入该模式,可用于支持硬件协处理的软件仿真
根据上面列表,可以知道Linux下用户态触发软中断进而进入内核态,对应的ARM工作模式就是从USR模式切换为SVC模式.
Q1.硬件中断和软中断有什么区别?
硬件中断是异步的,由外界触发,无法预知的,而软中断是调用特定函数而触发,是开发人员可以预测的.
回到前面的问题,为何调用open之后,就会陷入内核态,而进入SVC模式呢?其实这就像中断一样,当调用特定的函数之后,就像触发了中断条件,继而转到中断向量表中去执行这个中断,其实软中断大概也就是这样。而ADS中ARM声名一个软中断使用__swi关键字声名.具体看下面代码,和结合Reference[1]应该有个整体的了解.
3. 代码分析
下载地址:
/* forsakening @hdu @2013-6-1儿童节快乐 */
/******************************************************/
/*中断向量表部分*/
/******************************************************/
AREA Init,CODE,READONLY
ENTRY
ResetEntry
b ResetHandler
b HandlerUndef ;handler for Undefined mode
b HandlerSWI ;handler for SWI interrupt /* 当触发软中断时,ARM会自动将PC指向这里 */
b HandlerPabort ;handler for PAbort
b HandlerDabort ;handler for DAbort
b . ;reserved
b HandlerIRQ ;handler for IRQ interrupt
b HandlerFIQ ;handler for FIQ interrupt
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
;HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
/*
* 软中断服务程序:
* a)保存中断前的寄存器状态
* b)跳转到C语言处理软中断函数
*/
HandlerSWI
stmfd sp!,{r0-r3,r12,lr}
ldr r0,[lr,#-4]
bic r0,r0,#0xff000000
bl C_Swi_Handler
ldmfd sp!,{r0-r3,r12,pc}^
/******************************************************/
/* C语言部分 */
/******************************************************/
#include '2440addr.h'
#include 'def.h'
#define Led1_On() {rGPBDAT &= (~(1 << 5));}
#define Led1_Off() {rGPBDAT |= (1 << 5);}
#define Led2_On() {rGPBDAT &= (~(1 << 6));}
#define Led2_Off() {rGPBDAT |= (1 << 6);}
#define Led3_On() {rGPBDAT &= (~(1 << 7));}
#define Led3_Off() {rGPBDAT |= (1 << 7);}
#define Led4_On() {rGPBDAT &= (~(1 << 8));}
#define Led4_Off() {rGPBDAT |= (1 << 8);}
extern void C_Swi_Handler(unsigned num) ;
/*
* __swi关键字声明了软中断,当调用led1()这个函数时候,即会触发软中断
* __swi(0x01)括号中的数字表明了该函数对应的软中断号
*/
__swi(0x01) void led1(void);
__swi(0x02) void led2(void);
__swi(0x03) void led3(void);
__swi(0x04) void led4(void);
void Led_Init(void)
{
rGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) |(3 << 16));
rGPBCON |= ((1<<10) | (1<<12) | (1<<14) | (1<<16)) ;
rGPBUP &= ~((1 << 5) | (1 << 6) | (1 << 7) || (1 << 8) ) ;
rGPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) ;
}
void Delay_1(void)
{
int i;
for (i = 0; i < 100000; i++);
}
int Main()
{
Led_Init() ;
while(1)
{
led1() ;
Delay_1();
Led1_Off();
led2() ;
Delay_1();
Led2_Off();
led3() ;
Delay_1();
Led3_Off();
led4() ;
Delay_1();
Led4_Off();
}
return 0;
}
/*
* 中断向量表中,软中断所跳转的服务函数,num代表了中断号
*/
void C_Swi_Handler(unsigned num)
{
switch(num)
{
case 0x01:
Led1_On() ; break ;
case 0x02:
Led2_On() ; break ;
case 0x03:
Led3_On() ; break ;
case 0x04:
Led4_On() ; break ;
default :
break ;
}
}
/******************************************************/
/* Main的反汇编 */
/******************************************************/
Main
0x00000050: e92d4010 .@-. STMFD r13!,{r4,r14}
0x00000054: ebfffffe .... BL Led_Init ; 0x0
0x00000058: e3a04456 VD.. MOV r4,#0x56000000
0x0000005c: ef000001 .... SWI 0x1 /* 产生软中断,中断号1 */
0x00000060: ebfffffe .... BL Delay_1 ; 0x38
0x00000064: e5940014 .... LDR r0,[r4,#0x14]
0x00000068: e3800020 ... ORR r0,r0,#0x20
0x0000006c: e5840014 .... STR r0,[r4,#0x14]
0x00000070: ef000002 .... SWI 0x2 /* 产生软中断,中断号2 */
0x00000074: ebfffffe .... BL Delay_1 ; 0x38
0x00000078: e5940014 .... LDR r0,[r4,#0x14]
0x0000007c: e3800040 @... ORR r0,r0,#0x40
0x00000080: e5840014 .... STR r0,[r4,#0x14]
0x00000084: ef000003 .... SWI 0x3 /* 产生软中断,中断号3 */
0x00000088: ebfffffe .... BL Delay_1 ; 0x38
0x0000008c: e5940014 .... LDR r0,[r4,#0x14]
0x00000090: e3800080 .... ORR r0,r0,#0x80
0x00000094: e5840014 .... STR r0,[r4,#0x14]
0x00000098: ef000004 .... SWI 0x4 /* 产生软中断,中断号4 */
0x0000009c: ebfffffe .... BL Delay_1 ; 0x38
0x000000a0: e5940014 .... LDR r0,[r4,#0x14]
0x000000a4: e3800f40 @... ORR r0,r0,#0x100
0x000000a8: e5840014 .... STR r0,[r4,#0x14]
0x000000ac: eaffffea .... B {pc} - 0x50 ; 0x5c
4. Reference
[1]http://blog.csdn.net/forsakening/article/details/8940787 ARM Linux下系统调用