`
jinghuainfo
  • 浏览: 1526064 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

系统调用与软件中断SWI的实现

 
阅读更多

++++++++++++++++++++++++++++++++++++++++++

本文系本站原创,欢迎转载! 转载请注明出处:

http://blog.csdn.net/mr_raptor/article/details/6556451

++++++++++++++++++++++++++++++++++++++++++

1 系统调用

操作系统的主要功能是为应用程序的运行创建良好的环境,保障每个程序都可以最大化利用硬件资源,防止非法程序破坏其它应用程序执行环境,为了达到这个目的,操作系统会将硬件的操作权限交给内核来管理,用户程序不能随意使用硬件,使用硬件(对硬件寄存器进行读写)时要先向操作系统发出请求,操作系统内核帮助用户程序实现其操作,也就是说用户程序不会直接操作硬件,而是提供给用户程序一些具备预定功能的内核函数,通过一组称为系统调用的(system call)的接口呈现给用户,系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,将处理结果返回给应用程序。这好比我们去银行取款,用户自己的银行帐户不可能随意操作,必须要有一个安全的操作流程和规范,银行里的布局通常被分成两部分,中间用透明玻璃分隔开,只留一个小窗口,面向用户的是用户服务区,工作人员所在区域为内部业务操作区,取款时,将银行卡或存折通过小窗口交给业务员,并且告诉他要取多少钱,具体取钱的操作你是不会直接接触的,业务员会将银行帐户里减掉取款金额,将现金给你。上述操作流程可以很好保护银行系统,银行系统的操作全部由业务员来实现,用户只能向业务员提出自己的服务请求。银行里的小窗口就类似与操作系统的系统调用接口,是将用户请求传递给内核的接口。

3-16系统调用接口示意图

操作系统里将用户程序运行在用户模式下,并且为其分配可以使用内存空间,其它内存空间不能访问,内核态运行在特权模式下,对系统所有硬件进行统一管理和控制。从前面所学知识可以了解到,用户模式下没有权限进行模式切换,这也就意味着用户程序不可能直接通过切换模式去访问硬件寄存器,如果用户程序试图访问没有权限的硬件,会产生异常。这样用户程序被限制起来,如果用户程序想要使用硬件时怎么办呢?用户程序使用硬件时,必须调用操作系统提供的API接口才可以,而操作系统API接口通过软件中断方式切换到管理模式下,实现从用户模式下进入特权模式。

2 软件中断

软中断是利用硬件中断的概念,用软件方式进行模拟,实现从用户模式切换到特权模式并执行特权程序的机制。

硬件中断是由电平的物理特性决定,在电平变化时引发中断操作,而软中断是通过一条具体指令SWI,引发中断操作,也就是说用户程序里可以通过写入SWI指令来切换到特权模式,当CPU执行到SWI指令时会从用户模式切换到管理模式下,执行软件中断处理。由于SWI指令由操作系统提供的API封装起来,并且软件中断处理程序也是操作系统编写者提前写好的,因此用户程序调用API时就是将操作权限交给了操作系统,所以用户程序还是不能随意访问硬件。

先来了解下SWI指令。

SWI 软中断号immed_24

软中断指令相对比较简单,只有一个操作数:immed_24,SWI指令编码格式如图3-17所示。

3-17 SWI指令编码格式

SWI指令编码中immed_2424位任意有效立即数(范围0~2^24-1),当该指令被执行时系统产生软中断异常,切换到管理模式下。用户程序切换到管理模式下后,进入到软中断处理程序,通常软中断异常处理程序都是系统开发人员提前写好的,SWI切换到了特权模式,执行的是系统开发人员写好的异常处理程序,只要该处理程序没有问题,那么用户程序还是不能为所欲为的。

SWI指令后面的24立即数是干什么用的呢?用户程序通过SWI指令切换到特权模式,进入软中断处理程序,但是软中断处理程序不知道用户程序到底想要做什么?SWI指令后面的24位用来做用户程序和软中断处理程序之间的接头暗号。通过该软中断立即数来区分用户不同操作,执行不同内核函数。如果用户程序调用系统调用时传递参数,根据ATPCSC语言与汇编混合编程规则将参数放入R0~R4即可。下面的例子通过系统调用函数int led_on(int led_no)实现点亮第led_no LED灯,由于C语言里没有SWI 指令对应的语句,因此这儿要用到C语言与汇编混合编程,led_on函数里将参数led_no的值传递给R0,通过软中断SWI指令切换到软中断管理模式,同时R0 软中断方式点亮LED灯,用户通过SWI #1指令可以点灯,具体点亮哪个灯,通过R0保存参数传递,如果亮灯成功返回对应LED号。

系统调用接口函数led_on

#define __led_on_swi_no 1 // 软中断号1调用管理模式下的do_led_on函数

int led_on(int led_no){

int ret; // 返回值

__asm{ // 由于C程序中没有SWI对应表达式,所以使用混合编程

mov r0, led_no // 根据ATPCS规则,r0存放第一个参数

swi __led_on_swi_no // 产生SWI软中断,中断号为__led_on_swi_no

mov ret, r0 // 软中断处理结束,取得中断处理返回值,传递给ret变量

}

return ret; // ret返回给调用led_on的语句

}

3 软中断处理

CPU执行到swi xxx执行后,产生软件中断,由异常处理部分知识可知,软中断产生后CPU将强制将PC的值置为异常向量表地址0x08,在异常向量表0x08处安放跳转指令b HandleSWI,这样CPU就跳往我们自己定义的HandleSWI处执行。

首先,软中断处理中通过STMFD SP!, {R0-R12, LR} 要保存程序执行现场,将R0~R12通用寄存器数据保存在管理模式下SP栈内,LR由硬件自动保存软中断指令下一条指令的地址(后面利用LR的地址取得SWI指令编码),该寄存器值也保存在SP栈内,将来处理完毕之后返回。由SWI指令编码知识可知, SWI指令低24位保存有软中断号,通过LDR R4, [LR, #-4]指令,取得SWI指令编码(LR为硬件自动保存SWI xxx指令的下一条指令地址,LR – 4就是SWI指令地址),将其保存在R4寄存器中。通过BIC R4, R4, #0xFF000000指令将SWI指令高8位清除掉,只保留低24位立即数,再根据24位立即数中的软中断号判断用户程序的请求操作。如果24位立即数为1,表示led_on系统调用产生的软中断,则在管理模式下调用对应的亮灯操作do_led_on。如果24位立即数为2,表示led_off系统调用产生的软中断,则调用灭灯操作do_led_on,根据ATPCS调用规则,R0~R3做为参数传递寄存器,在软中断处理中没有使用这4个寄存器,而是使用R4作为操作寄存器的。执行完系统调用操作之后,返回到swi_return(在调用对应系统操作时,通过LDREQ LR, =swi_return设置了返回地址),执行返回处理,通过LDMIA SP!, {R0-R12, PC}^ 指令将用户寄存器数据恢复到R0~R12,将进入软中断处理时保存的返回地址LR的值恢复给PC,实现程序返回,同时还恢复了状态寄存器。切换回用户模式下程序中继续执行。

; 异常向量表开始

; 0x00: 复位Reset异常

b Reset

; 0x04: 未定义异常(未处理)

HandleUndef

b HandleUndef

; 0x08: 软件中断异常,跳往软件中断处理函数HandleSWI

b HandleSWI

… …

; 省略其它异常向量和对应处理

… …

;***********************************************************************

; 软中断处理

;***********************************************************************

IMPORT do_led_on

IMPORT do_led_off

HandleSWI

STMFD SP!, {R0-R12, LR} ; 保存程序执行现场

LDR R4, [LR, #-4] ; LR - 4 为指令" swi xxx" 的地址,低24位是软件中断号

BIC R4, R4, #0xFF000000 ; 取得ARM指令24位立即数

CMP R4, #1 ; 判断24位立即数,如果为1,调用do_led_on系统调用

LDREQ LR, =swi_return ; 软中断处理返回地址

LDREQ PC, = do_led_on ; 软中断号1对应系统调用处理

CMP R4, #2 ; 判断24位立即数,如果为2,调用do_led_off系统调用

LDREQ LR, =swi_return ; 软中断处理返回地址

LDREQ PC, = do_led_off ; 软中断号2对应系统调用处理

MOVNE R0, #-1 ; 没有该软中断号对应函数,出错返回-1

swi_return

LDMIA SP!, {R0-R12, PC}^ ; 中断返回, ^表示将spsr的值复制到cpsr

1.1.4 led系统调用实验

本实验通过Led跑马灯效果来模拟系统调用,本程序提供了两个系统调用接口led_onled_off,用户程序main.c通过引入头文件led.h使用系统调用接口,用户调用led_onled_off时通过软中断指令切换到管理模式,在管理模式下调用内核led操作系统do_led_ondo_led_off,实现Led的亮灭。实验源码适用于QQ2440TQ2440MINI2440开发板。

head.s

本程序文件主要用于安装异常向量表,Reset异常处理,软中断处理和必要硬件初始化。

;**********************************************************************

; 系统调用实验(QQ2440, MINI2440,TQ2440

;**********************************************************************

GPBCON EQU 0x56000010

GPBDAT EQU 0x56000014

SYS_STACK_BASE EQU 0x33000000

EXPORT SWI_LED

AREA SWI_LED ,CODE,READONLY

ENTRY

;**********************************************************************

; 设置中断向量,ResetHandleSWI外,其它异常都没有使用(如果不幸发生了,

; 将导致死机)

;**********************************************************************

; 0x00: 复位Reset异常

b Reset

; 0x04: 未定义异常未处理

HandleUndef

b HandleUndef

; 0x08: 软件中断异常,跳往软件中断处理函数HandleSWI

b HandleSWI

; 0x0c: 指令预取异常未处理

HandlePrefetchAbt

b HandlePrefetchAbt

; 0x10: 数据访问中止异常未处理

HandleDataAbt

b HandleDataAbt

; 0x14: 未使用异常未处理

HandleNotUsed

b HandleNotUsed

; 0x18: 一般中断异常未处理

HandleIRQ

b HandleIRQ

; 0x1c: 快速中断异常未处理

HandleFIQ

b HandleFIQ

Reset ; 复位异常处理入口

; 关闭看门狗

ldr r0, = 0x53000000

mov r1, #0

str r1, [r0]

bl initmem

ldr sp, =0x32000000 ; 设置管理模式栈指针

; LED灯初始化

ldr r0, =GPBCON ; LEDGPIO接口配置寄存器

ldr r1, =0x00015400 ; GPIO配置数据

str r1, [r0] ; 设置GPIO

ldr r0, =GPBDAT ; Led数据寄存器

ldr r1, =0x1e0 ; 熄灭所有Led

str r1, [r0]

msr cpsr_c, #0xdf

ldr sp, =SYS_STACK_BASE

msr cpsr_c, #0x50 ; 开启系统中断,进入用户模式,该指令执行完

; 就进入用户空间,执行用户程序xmain

ldr lr, =halt_loop ; 设置管理模式下返回地址

IMPORT xmain

ldr pc, =xmain ; 跳入主函数main里执行

halt_loop

b halt_loop

;***********************************************************************

; 软中断处理

;***********************************************************************

IMPORT do_led_on

IMPORT do_led_off

HandleSWI

STMFD SP!, {R0-R12, LR} ; 保存程序执行现场

LDR R4, [LR, #-4] ; LR - 4 为指令" swi xxx" 的地址指令低24位软件中断号

BIC R4, R4, #0xFF000000 ; 取得ARM指令24位立即数

CMP R4, #1 ; 判断24位立即数的值如果为1调用do_led_on系统调用

LDREQ LR, =swi_return ; 软中断处理返回地址

LDREQ PC, = do_led_on ; 软中断号1对应系统调用处理

CMP R4, #2 ; 判断24位立即数的值如果为2调用do_led_off系统调用

LDREQ LR, =swi_return ; 软中断处理返回地址

LDREQ PC, = do_led_off ; 软中断号2对应系统调用处理

MOVNE R0, #-1 ; 没有该软中断号对应函数出错返回-1

swi_return

LDMIA SP!, {R0-R12, PC}^ ; 中断返回, ^表示将spsr的值复制到cpsr

initmem

ldr r0, =0x48000000 ; 内存控制寄存器起始地址

ldr r1, =0x48000034 ; 内存控制寄存器结束地址

adr r2, memdata ; 加载寄存器设置数据区首地址

initmemloop

ldr r3, [r2], #4

str r3, [r0], #4

teq r0, r1

bne initmemloop ; 循环设置每一个寄存器

mov pc, lr

memdata

DCD 0x22000000 ;BWSCON

DCD 0x00000700 ;BANKCON0

DCD 0x00000700 ;BANKCON1

DCD 0x00000700 ;BANKCON2

DCD 0x00000700 ;BANKCON3

DCD 0x00000700 ;BANKCON4

DCD 0x00000700 ;BANKCON5

DCD 0x00018005 ;BANKCON6

DCD 0x00018005 ;BANKCON7

DCD 0x008e07a3 ;REFRESH

DCD 0x000000b1 ;BANKSIZE

DCD 0x00000030 ;MRSRB6

DCD 0x00000030 ;MRSRB7

END ; 代码结束

main.c:

本程序文件是用户程序xmain主要实现跑马灯效果通过使用系统调用led_onled_off实现Led控制。

#include "led.h"

/* 亮灯延时 */

void delay(int msec)

{

int i, j;

for(i = 1000; i > 0; i--)

for(j = msec*10; j > 0; j--)

/* do nothing */;

}

/* 主函数跑马灯效果 */

int xmain()

{

while(1)

{

led_on(1);

delay(5); //delay

led_on(2);

delay(5); //delay

led_on(3);

delay(5); //delay

led_on(4);

delay(5); //delay

led_off(1);

delay(5); //delay

led_off(2);

delay(5); //delay

led_off(3);

delay(5); //delay

led_off(4);

delay(5); //delay

}

return 0;

}

led_lib.c

本程序文件是系统调用函数led_on, led_off的具体实现,通过swi软中断提交硬件访问请求,将具体请求以软中断号的方式通过参数传递给内核空间。

#include "led.h"

#define __led_on_swi_no 1 // 软中断号1,调用管理模式下的do_led_on函数

#define __led_off_swi_no 2 // 软中断号2,调用管理模式下的do_led_off函数

int led_on(int led_no){

int ret; // 返回值

__asm{ // 由于C程序中没有SWI对应表达式,所以使用混合编程

mov r0, led_no // 根据ATPCS规则,r0存放第一个参数

swi __led_on_swi_no // 产生SWI软中断,中断号为__led_on_swi_no

mov ret, r0 // 软中断处理结束,取得中断处理返回值,传递给ret变量

}

return ret; // ret返回给调用led_on的语句

}

int led_off(int led_no){

int ret; // 返回值

__asm{ // 由于C程序中没有SWI对应表达式,所以使用混合编程

mov r0, led_no // 根据ATPCS规则,r0存放第一个参数

swi __led_off_swi_no // 产生SWI软中断,中断号为__led_off_swi_no

mov ret, r0 // 软中断处理结束,取得中断处理返回值,传递给ret变量

}

return ret; // ret返回给调用led_off的语句

}

led.h

Led系统调用头文件。

extern int led_on(int num);

extern int led_off(int num);

sys_call.c

本程序文件主要是系统调用接口内核空间do_led_ondo_led_off函数的实现。

#include "register.h"

/* Led1~Led4初始化 */

#define LED1 (1<<5) //LED1 GPBDAT[5]

#define LED2 (1<<6) //LED2 GPBDAT[6]

#define LED3 (1<<7) //LED3 GPBDAT[7]

#define LED4 (1<<8) //LED4 GPBDAT[8]

/* 点亮对应numLed */

extern int do_led_on (int num)

{

switch(num)

{

case 1:

GPBDAT = GPBDAT & ~LED1; break;

case 2:

GPBDAT = GPBDAT & ~LED2; break;

case 3:

GPBDAT = GPBDAT & ~LED3; break;

case 4:

GPBDAT = GPBDAT & ~LED4; break;

default:

return 0;

}

return num;

}

/* 关闭对应numLed */

extern int do_led_off(int num)

{

switch(num)

{

case 1:

GPBDAT = GPBDAT | LED1; break;

case 2:

GPBDAT = GPBDAT | LED2; break;

case 3:

GPBDAT = GPBDAT | LED3; break;

case 4:

GPBDAT = GPBDAT | LED4; break;

default:

return 0;

}

return num;

}

++++++++++++++++++++++++++++++++++++++++++

本文系本站原创,欢迎转载! 转载请注明出处:

http://blog.csdn.net/mr_raptor/article/details/6556451

++++++++++++++++++++++++++++++++++++++++++

分享到:
评论

相关推荐

    ARM处理器的SWI异常中断响应过程

    通过SWI异常中断指令,在用户模式下应用程序可以调用系统模式下的代码,在操作系统中表现为系统调用,那这个过程又是如何实现的呢?带着疑问让我们来学习吧!

    arm汇编swi中断调用c函数

    汇编语言里设置软中断,来调用c语言函数。实现系统调用的模拟。

    swi.rar_ arm swi handler_arm_arm 中断_swi_swi handler

    ARM处理器软中断处理。a_swi.s文件是最开始处理的SWI句柄,用ARM汇编指令编写。c_swi.c文件是在执行a_swi.s文件之后调用执行的C语言SWI句柄。

    SWI.rar_ARM SWI_ARM汇编_arm swi_汇编中断_软中断

    ARM汇编实现软中断,用ADS编写。先调用Init装中断,再跳转到SWIhandler,SWIhandler为中断服务程序

    Arm Linux操作系统调用流程详细解析

    系统调用是os操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。本文详细介绍了Arm Linux操作系统调用流程。

    嵌入式系统/ARM技术中的ARM linux系统调用的实现原理

     系统调用是os操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。  at91rm9200处理器对应的linux2.4.19内核系统调用对应...

    什么是异常中断产生指令

    软件中断指令SWI用于产生SWI异常中断,用来实现在用户模式下对操作系统中特权模式的程序调用;断点中断指令BKPI主要用于产生软件断点,供调试程序用。

    DSP BIOS API调用详解

    包括时钟管理CLK,周期函数PRD,软件中断管理SWI,信息输出管理LOG,存储器管理MEM,C6000专用模块C64x,统计模块STS,统计类模块TRC,TSK任务管理模块,DSP/BIOS后台管理 IDL模块等API函数调用说明。

    基于s3c2410软中断服务的uC/OS-II任务切换

    1.关于软中断指令 软件中断指令(SWI)可以产生一个软件中断异常,这为应用程序调用系统例程提供了一种机制。 语法: SWI {} SWI_number SWI执行后的寄存器变化:  lr_svc = SWI指令后面的指令地址 spsr_svc = ...

    详解ARM体系结构支持的异常包括复位、中断、未定义指令等.pdf

    可使用该异常机制实现系统功能调用(异常向量:0x0000,0008);   4、指令预取中止(优先级5) 若处理器的预取指令的地址不存在,或该地址不允许当前指令访问,存储器会向处理器发出中止信号,当预取...

    开源一STM32项目,CAN,UART,Input检测 原创相对高效性能与代码重用平衡思路,可直接做工程模板

    CAN1_SWI_Handler (void) 实现CAN接收中断触发的内部软件中断,处理内存FIFO接收的CAN数据(实际编译函数名为:EXTI4_IRQHandler())。 处理过程优化:通过定义顺序的code码,查表调用处理函数列表指针可实现比较...

    八股总结1

    1. 通过 __swi(中断号) function 给中断函数指定中断号(一般在C代码中撰写) 2. 调用function时,相当于执行了 SWI 中断号 指令

    ARM 汇编器对C的扩展

    __swi void ledtest(); //:声明 edtest 是个软中断。 __asm 内嵌汇编 //:通常在C程序里面需要嵌入汇编代码,这是就可以用__asm关键字来指示编译器下面的代码是用汇编语言来写的, __inline 定义内联函数 //:就...

    uboott移植实验手册及技术文档

    其调用与 CFG_NAND_LEGACY 宏有 关,如果没有定义这个宏,系统调用 drivers/nand/nand.c 中的 nand_init();否则调用自己在 本文件中的 nand_init()函数,本例使用后者。fs2410.c代码如下: #if defined(CONFIG_CMD...

    arm指令集-中文 (ARM微控制器基础)

    前言...............................................................................................................................................................i 目录..................................

    ARM指令集 肯定可以下载

    前言...............................................................................................................................................................i 目录..................................

    学习ARM汇编的经典参考资料

    学习ARM汇编指令的经典资料。 对ARM的各种汇编指令进行了深入全面的讲解,并给出了各种示例和详细注解,并且还对一些值得注意的点或是容易犯错误的地方进行了总结。 目录 前言......................................

Global site tag (gtag.js) - Google Analytics