swi 指令能用在C语言吗,arm处理器异常处理-swi - zgolee的专栏 - CSDN博客

arm处理器异常处理-swi 收藏

ARM处理器共有7中运行模式:

用户模式(usr)                     --  正常程序执行模式

|--             |--     快速中断模式(fiq)                 --  用于高速数据传输和通道处理

特     |        异    |        外部中断模式(irq)                 --  用于通常的中断处理

权  --|        常  --|        管理员模式(svc)                   --  供操作系统使用的一种保护模式

模     |        模    |        数据访问中止模式(abt)          --  用于虚拟存储及存储保护

式     |        式    |--     未定义指令中止模式(und)       --  用于支持通过软件仿真硬件的协处理器

|--                     系统模式(sys)                       --  用于运行特权级的操作系统任务

特权模式:fiq、irq、svc、abt、und、sys -- 程序可以访问所有的系统资源,也可以任意切换处理器模式

异常模式:fiq、irq、svc、abt、und

ARM异常中断种类及优先级:

优先级                 异常中断名称

高                   复位(reset)

||                    数据访问中止(data abort)

||                    快速中断请求(FIQ)

||                    外部中断请求(IRQ)

\||/                  指令预取中止(prefetch abort)

\/                    软中断(SWI)

低                   未定义指令(undefined instruction)

异常向量表:

地址                           异常中断名称                                         优先级

.                                    .

.                                    .

.                                    .

0x1c                            FIQ                                                         3

0x18                            IRQ                                                        4

0x14                            Reserved                                               X

0x10                            Data Abort                                             2

0x0c                            Prefetch Abort                                        4

0x08                            SWI                                                        5

0x04                            Undefined Instruction                            6

0x00                            Reset                                                     1

Vector Table可以位于0x0或者0xFFFF0000处(ARM720T、ARM9、ARM10..)

优先级为3的FIQ为什么放在地址0x1c处呢?当初这么设计应该是为了更加快速地响应FIQ中断,也就是说不在0x1c地

址放跳转指令,而是直接存放最关键的FIQ处理代码在0x1c开始一段地址区域内。

异常进入及返回:

当异常产生时:

1. 拷贝当前模式的CPSR值到相应异常模式的SPSR_,如:CPSR(usr) --> SPSR_svc(svc)。

2. 设置适当的CPSR位:

改变处理器状态进入ARM状态

改变处理器模式进入相应的异常模式

如果需要可以设置中断禁止位禁止相应中断

3. 保存返回地址(pc-4)到LR_。

4. 设置pc为相应的异常向量。

异常返回时,需要:

1. 从SPSR_恢复CPSR。

2. 从LR_恢复pc

(只能在ARM状态下实现该返回操作)

异常返回的指令分析:

* 使用一数据处理指令实现,该指令带“S”后缀,同时pc作为目的寄存器

* 在特权模式下不仅仅要更新pc,而且还要拷贝SPSR到CPSR

1. 从SWI和Undef异常返回:

movs  pc , lr

这两种异常都会在导致异常的指令执行周期中就进入异常,没有等到下个时钟周期才进入异常,另外这两种异常都是返回到产生异常指令的下一条指令去继续执行。我从前面可以知道lr中保存的就是pc-4(该pc值是产生异常指令的下下一条指令的地址),所以可以直接将lr的值送入pc。

2. 从FIQ、IRQ和Prefect Abort返回:

subs  pc , lr , #4

这三种异常都会等待产生异常的指令执行完才会进入异常,所以此刻的pc已经更新,比如:

...

subs    r3, r3, #1 << 26            @ 0x100

bcs        2b                                    @ 0x104

subs    r1, r1, #1 << 5                @ 0x108

bcs        1b                                    @ 0x10b

...

如果在执行第1行地址为0x100指令时,发生了上面三种异常,此刻的pc值为0x108,等第1行执行完之后,pc更新为0x10b。同时进入异常处理,在异常进入时将lr值保存为pc-4,即0x108。那么在异常返回后,需要接着执行发生异常指令的下一条指令的话就必须将lr的值减去4才能得到正确的地址,lr-4 = 0x108 - 4 = 0x104。

3. 从数据异常(Data Abort)异常返回:

该异常也是会等待产生异常的那条指令执行完才会进入异常,情况类似于第2类的三种异常,但是有一点不同的是:数据异常返回地址不是产生异常的下一条指令,而是产生异常的那条指令,所以,它的返回指令应该是:

subs  pc , lr , #8

按照上面的例子就应该返回到地址0x100处继续执行。为什么会这样,因为数据异常返回后会继续去取数据,想想缺页异常。

4. 如果lr在进入异常后被压栈的话,就需要使用下面的指令来弹出。

LDMFD sp! , {pc}^

(^同时拷贝SPSR到CPSR中,这里的lr在压栈之前已经做了前面3中情况对应的处理了)

SWI异常:

执行SWI软中断指令即可产生软中断异常,进入SWI异常时会做如下动作:

CSPR保存到SPSR_svc。

改变处理器状态进入ARM状态

改变处理器模式进入相应的管理员模式(svc)

看需要禁止中断

保存返回地址(pc-4)到LR_svc

设置pc为0x08或者0xFFFF0008

** 需要注意一点的是:如果在执行SWI指令时系统正处于svc模式时,那么将会覆盖掉原来LR_svc的值。所以

在SWI指令之前应该对LR_svc压栈保存。

SWI异常返回时,做如下动作:

从SPSR_svc恢复CPSR

从LR_svc恢复pc,不需要修正

在c语言中使用关键字“__swi”来定义一个软中断函数:

__swi(0x30) void my_swi(void);

void fun(void)

{

my_swi();

}

-----> 转换成汇编

fun

STMFD sp! , {lr}

swi 0x24

LDMFD sp! , {pc}

swi调用带参和swi处理函数带参:

swi调用带参:

使用swi指令时,通常有两种方法来传递参数:

1. 使用swi号

swi指令的低24bits(ARM指令集)组成或者低8bits(Thumb指令集)来指定软中断号,

其余参数通过寄存器来传递。

2. r0决定软中断号,其余参数使用同样寄存器传递。

** c语言中,关键字“__swi”定义的软中断函数允许最多4个参数,使用r0~r4来传递。

swi处理函数带参:

1. 汇编中,存取调用者设置的寄存器即可

2. 传参给c,通常才用压栈的方法:

将参数压栈,给调用的函数传递一个指向这些参数的指针。

获取SWI号:

ARM core不提供直接传递软中断号到处理程序的机制,SWI处理程序必须定位SWI指令并提取SWI指令中的常数域

1. 检查SPSR_svc的Tbit,可以确定陷入swi异常之前的指令时ARM指令集还是Thumb指令集。

2. 然后通过LR_svc的值确定SWI指令的地址。ARM状态下是LR-4,而Thumb状态下是LR-2的位置。

3. SWI指令格式:

ARM态:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

|    Cond       |1   1   1   1 |                 SWI number                                                               |

Thumb态

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

| 1   1   0   1   1   1  1 1|   SWI number

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值