系统复位的时候,从0地址开始执行,这个时候系统处于svc管理模式。

一般而言,我们的app应用程序是处于用户模式的,但是用户模式不能访问硬件,必须处于特权模式才可以。所以这里我们用swi软中断方式来实验。swi异常会让cpu进入svc模式。

首先,系统复位,执行代码,此刻处于svc模式,然后我们切换模式改变成为用户模式,再使用swi指令,处理软中断。

由于切换了模式,需要重新设置栈,因为我们要调用c函数,而栈我们是在sdram的最高地址往下开辟的。

这里,我们的swi异常发生时,硬件会让程序从地址0x8的地方开始执行,所以我们仿照之前的未定义异常编写软中断处理函数:

do_swi:
/* 执行到这里之前:
* . lr_svc保存有被中断模式中的下一条即将执行的指令的地址
* . SPSR_svc保存有被中断模式的CPSR
* . CPSR中的M4-M0被设置为10011, 进入到svc模式
* . 跳到0x08的地方执行程序
*/ /* sp_svc未设置, 先设置它 */
ldr sp, =0x33e00000 /* 保存现场 */
/* 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */
/* lr是异常处理完后的返回地址, 也要保存 */
stmdb sp!, {r0-r12, lr} //mov r4, lr /* 处理swi异常 */
mrs r0, cpsr
ldr r1, =swi_string
bl printException //sub r0, r4, #
ldr r0,=my_swi
bl printSWIVal /* 恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */ swi_string:
.string "swi exception" .align

韦老大的代码通过swi异常保存lr的方式来达到读取软中断号,这样其实麻烦了,所以我直接在我们的

swi 0x123处加上标签(my_swi:),这样直接就知道swi 0x123这条指令的地址,解引用这个地址,就可以得到0x123这个数值,而不用通过保存lr的值之后,再减去4的方式,可读性更高,代码也更简单呀!

这样,当代码运行到swi 0x123是,就会出现我们软中断异常处理,打印消息如下:

先发生未定义异常,然后发生swi异常。

上图是swi异常的打印函数,为什么取地址解引用之后,还要对0xff000000取反相与呢?

我们看看arm指令格式:

我们忽略cond条件(全为1,上篇随笔也有说到),而且紧跟着的4位也都是1,所以高八位都是1,即ff,所以我们要把高八位清零,剩下的就是我们my_swi标签地址内存中正真的数据了。

再说一下切换成usr用户的时候我们使用了 bic指令。

BIC指令的格式为:
BIC{条件}{S}  目的寄存器,操作数1,操作数2
BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。操作数1应是一个寄存器,
操作数2可以是一个寄存器、被移位的寄存器、或一个立即数。操作数2为32位的掩码,如果在
掩码中置了某一位1,则清除这一位。未设置的掩码位保持不变。
eg:
bic r0,r0,#0x1f
0x1f=11111b
其含义:清除r0的bit[4:0]位。

然后:

msr和mrs很像,不要混淆了。

mrs:(r:寄存器 ,s:状态  英文缩写)

将状态寄存器的内容传送至通用寄存器。

msr:(s:状态 ,r:寄存器)

通用寄存器传送至状态寄存器传送指令

msr和mrs这两个指令从右往左看这三个字母,开头都是m就不管了,sr表示r->s(r到s),rs表示s->r(s到r),就是把什么寄存器传到什么寄存器去。

比如我们上面的msr cpsr, r0:表示把通用寄存器r0传送到状态寄存器cpsr。

s3c2440——swi异常的更多相关文章

  1. s3c2440裸机-异常中断(一. 异常、中断的原理与流程)

    1.异常中断概述 在arm架构的处理器中,cpu有7中工作模式,2中工作状态. 1.CPU模式(Mode): 7种Mode: 除了usr/sys,其他5种都是异常模式.我们知道中断属于异常的2中,中断 ...

  2. S3C2440中断

    韦东山老师一期中断课程学习: 总结: 程序启动后工作流程,程序从0地址开始执行Reset  --> 重定位  -->ldr pc,=main [绝对跳转到SDRAM中执行main()函数] ...

  3. 应用调试(四)系统调用SWI

    目录 应用调试(四)系统调用SWI 系统调用 SWI代码片段分析 分析sys_write 构造sys_hello 应用程序调用SWI 嵌入汇编语法 测试APP 参考 title: 应用调试(四)系统调 ...

  4. s3c2440——按键中断

    s3c2440的异常向量表: IRQ中断地址是0x18.所以,根据之前的异常处理方式,我们编写启动文件: 为什么需要lr减4,可以参考这篇文章:http://blog.csdn.net/zzsfqiu ...

  5. 常用ARM汇编指令

    常用ARM汇编指令 [日期:2012-07-14] 来源:Linux社区  作者:xuyuanfan77 [字体:大 中 小]     在嵌入式开发中,汇编程序常常用于非常关键的地方,比如系统启动时初 ...

  6. Linux中断处理体系结构分析

    Linux中断处理体系结构分析(一) 异常,就是可以打断CPU正常运行流程的一些事情,比如外部中断.未定义指令.试图修改只读的数据.执行swi指令(Software Interrupt Instruc ...

  7. linux驱动之中断处理过程汇编部分

    linux系统下驱动中,中断异常的处理过程,与裸机开发中断处理过程非常类似.通过简单的回顾裸机开发中断处理部分,来参考学习linux系统下中断处理流程. 一.ARM裸机开发中断处理过程 以S3C244 ...

  8. 嵌入式Linux驱动学习之路(九)Linux系统调用、驱动程序框架

    应用程序通过open  read  write close 等函数来操作计算机硬件.类似是一个接口. 当应用程序调用这些接口程序时,计算机是如何进入内核的呢?这是经过了系统调用. 实际上当调用接口函数 ...

  9. ARM指令集(下)

    A.2.5   ARM 协处理器指令         ARM 支持协处理器操作,协处理器的控制要通过协处理器命令实现.表A-7给出全部的ARM协处理器指令. 表A-7  ARM 协处理器指令 CDP ...

随机推荐

  1. 进阶之路(中级篇) - 015 串口控RGB三色灯

    本文由博主原创,如有不对之处请指明,转载请说明出处. /********************************* 代码功能:串口控RGB三色灯 使用函数: Serial.flush(); / ...

  2. OpenCV 学习笔记 02 处理文件、摄像头和图形用户界面

    在处理文件前需要引入OpenCV库,同时也引入unmpy库 import cv2 import numpy as np 1 基本的读写操作 1.1 图像文件的读写操作 1.1.1 图像文件的读取操作 ...

  3. 虚拟化—Docker解决方案

    What is Docker? Docker is an open-source project to easily create lightweight, portable, self-suffic ...

  4. cron执行service

    在Cron的环境下,是没有定义路径的,所以,service xxx start等等要使用绝对路径 => /sbin/service xxx start service的路径可以用whereis ...

  5. 异步加载js文件的方法总结

    方法一,jQuery.getScript HTML 代码: 代码如下 复制代码 <button id="go">Run</button><div cl ...

  6. AndroidStudio创建项目时一直处于building“project name”gradle project info的解决办法

    AndroidStudio创建项目,最后一步finish后,一直长时间处于building“project name”gradle project info,界面就一直停留在如图所示: 谷歌自家的产品 ...

  7. 如何使你的Android应用记住曾经使用过的账户信息

    原文:http://android.eoe.cn/topic/android_sdk 当您记住他们的名字时,每个人都会很喜欢.最简单的一个例子,您能够做的,让您的应用更加受人喜爱的,最有效的方法是记住 ...

  8. 【SSH】Hibernate关联映射

    一对一关联映射 一对一主键关联映射    一句话:不加字段.主键既是主键又是外键. 一对一单向主键关联映射 配置: <span style="font-family:KaiTi_GB2 ...

  9. csc.exe已退出,代码为-532462766

    我的surface pro4爆屏了 打电话给微软客服,那边说3,4天内给我回复 只能转移源码等资料到老电脑上,老电脑是神舟 精盾K480N I7D2,装的是WIN10预览版build 1625.rs2 ...

  10. 深入理解Linux内核-内存寻址

    1.逻辑地址怎么转换为线性地址的: 逻辑地址 = 段选择符(16bit)+偏移量(32bit) 段选择符又三部分组成:index(索引序号).T1(表指示器).RPL(request privileg ...