历史上的今天

今天是:2024年09月02日(星期一)

正在发生

2021年09月02日 | S3c2440ARM异常与中断体系详解5---_swi异常模示程序示例

发布者:sclibin 来源: eefocus关键字:S3c2440  ARM  异常  中断体系 手机看文章 扫描二维码
随时随地手机看文章

这节我们再来演示swi的处理流程

swi软件中断:


software interrupt


在前面的视频中我们讲过ARMCPU有7中模式(下图为7种模式),除了用户模式以外,其他6种都是特权模式,这些特权模式可以直接修改CPSR进入其他模式

usr用户模式不能修改CPSR进入其他模式

在这里插入图片描述

Linux应用程序一般运行于用户模式


APP运行于usermode,(受限模式,不可访问硬件)


APP想访问硬件,必须切换模式,怎么切换?


通过发生异常中断进入特权模式


发生异常3种模式

1、中断是一种异常

2、und也是

3、 swi + 某个值(使用软中断切换模式)

在这里插入图片描述

由上图可知道,当进入reset时,进入的svc模式,所以复位之后,我们要改变cpsr进入用户模式

现在start.S把要做的事情列出来


/*1

    /* 复位之后, cpu处于svc模式

     * 现在, 切换到usr模式

     * 设置栈

     * 跳转执行

 */


/*2 故意引入一条swi指令*/


/*3 需在_start这里放一条swi指令*/


我们先切换到usr模式下

在这里插入图片描述
在这里插入图片描述

usr模式下的 M0 ~ M4是10000


bl clean_bss


/* 复位之后, cpu处于svc模式

* 现在, 切换到usr模式

*/

 

mrs r0,cpsr     /* 读出cpsr */

bic r0,r0, #0xf /* 修改M4-M0为0b10000, 进入usr模式 */

msr cpsr,r0     /* r0 = 0b10000 */


/* 设置 sp_usr */

ldr sp, =0x33f00000  /*在SDRAM种设置sp*/

ldr pc, =SDRAM


编译运行


发现可以处理und指令


添加 swi异常,仿照未定义指令做



.text

.global _start


_start:

    b reset          /* vector 0 : reset */

    ldr pc, und_addr /* vector 4 : und */

/*1 添加swi指令*/

    ldr pc, swi_addr /* vector 8 : swi */


und_addr:

    .word do_und


/*2 仿照und未定义添加指令*/

swi_addr:

    .word do_swi


do_und:

    /* 执行到这里之前:

     * 1. lr_und保存有被中断模式中的下一条即将执行的指令的地址

     * 2. SPSR_und保存有被中断模式的CPSR

     * 3. CPSR中的M4-M0被设置为11011, 进入到und模式

     * 4. 跳到0x4的地方执行程序 

     */


    /* sp_und未设置, 先设置它 */

    ldr sp, =0x34000000


    /* 在und异常处理函数中有可能会修改r0-r12, 所以先保存 */

    /* lr是异常处理完后的返回地址, 也要保存 */

    stmdb sp!, {r0-r12, lr}  


    /* 保存现场 */

    /* 处理und异常 */

    mrs r0, cpsr

    ldr r1, =und_string

    bl printException


    /* 恢复现场 */

    ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */


und_string:

    .string "undefined instruction exception"


/*3 复制do_und修改为swi */

do_swi:

    /* 执行到这里之前:

     * 3.1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址

     * 3.2. SPSR_svc保存有被中断模式的CPSR

     * 3.3. CPSR中的M4-M0被设置为10011, 进入到svc模式

     * 3.4. 跳到0x08的地方执行程序 

     */


    /* 3.5 sp_svc未设置, 先设置它 */

    ldr sp, =0x33e00000


    /* 3.6 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */

    /* 3.7 lr是异常处理完后的返回地址, 也要保存 */

    stmdb sp!, {r0-r12, lr}  


    /* 3.8 保存现场 */

    /* 3.9 处理swi异常 只是打印 */

    mrs r0, cpsr

    ldr r1, =swi_string

    bl printException


    /*3.10  恢复现场 */

    ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */


/*swi处理函数*/ 

swi_string:

    .string "swi exception"


上传代码实验


烧写 发现没有执行


我们先把下面这些代码注释掉


/*3 复制do_und 修改为swi */


    /* 执行到这里之前:

     * 3.1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址

     * 3.2. SPSR_svc保存有被中断模式的CPSR

     * 3.3. CPSR中的M4-M0被设置为10011, 进入到svc模式

     * 3.4. 跳到0x08的地方执行程序 

     */


    /* 3.5 sp_svc未设置, 先设置它 */

    ldr sp, =0x33e00000


    /* 3.6 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */

    /* 3.7 lr是异常处理完后的返回地址, 也要保存 */

    stmdb sp!, {r0-r12, lr}  


    /* 3.8 保存现场 */

    /* 3.9 处理swi异常 只是打印 */

    mrs r0, cpsr

    ldr r1, =swi_string

    bl printException


    /*3.10  恢复现场 */

    ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */


/* swi处理函数 */   

swi_string:

    .string "swi exception"


上传编译


烧写执行 可以正常运行


循环打印

swi 0x123 /* 执行此命令, 触发SWI异常, 进入0x8执行 */


执行后继续执行

ldr pc, swi_addr /* vector 8 : swi */


表明问题出现在 do_swi:函数中


先把下面这句话注释掉


.string "swi exception"


编译烧写运行


程序可以正常运行


显然程序问题出现在.string “swi exception” 这句话,为什么加上这句话程序就无法执行,查看一下反汇编:


30000064 : //这里地址是64

30000064:   20697773    rsbcs   r7, r9, r3, ror r7

30000068:   65637865    strvsb  r7, [r3, #-2149]!

3000007c:   6f697470    swivs   0x00697470

30000070:   0000006e    andeq   r0, r0, lr, rrx


30000082 : //我们使用的是ARM指令集,应该是4字节对齐,发现这里并不是,问题就在这里

30000082:   e3a00453    mov r0, #1392508928 ; 0x53000000

30000086:   e3a01000    mov r1, #0  ; 0x0

3000008a:   e5801000    str r1, [r0]

3000008e:   e3a00313    mov r0, #1275068416 ; 0x4c000000

30000092:   e3e01000    mvn r1, #0  ; 0x0


因为这个字符串长度有问题


前面und_string 那里的字符串长度刚刚好


我们不能把问题放在运气上面


添加:


/*******

以4字节对齐

*/

.align 4



do_swi:

    /* 执行到这里之前:

     * 3.1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址

     * 3.2. SPSR_svc保存有被中断模式的CPSR

     * 3.3. CPSR中的M4-M0被设置为10011, 进入到svc模式

     * 3.4. 跳到0x08的地方执行程序 

     */


    /* 3.5 sp_svc未设置, 先设置它 */

    ldr sp, =0x33e00000


    /* 3.6 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */

    /* 3.7 lr是异常处理完后的返回地址, 也要保存 */

    stmdb sp!, {r0-r12, lr}  


    /* 3.8 保存现场 */

    /* 3.9 处理swi异常 只是打印 */

    mrs r0, cpsr

    ldr r1, =swi_string

    bl printException


    /*3.10  恢复现场 */

    ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */

/*****

swi处理函数

*/  

swi_string:

    .string "swi exception"



.align 4

/**************

表明下面的标号要放在4字节对齐的地方

*/


上传代码编译运行查看反汇编:



30000068 :

30000068:   20697773    rsbcs   r7, r9, r3, ror r7

3000006c:   65637865    strvsb  r7, [r3, #-2149]!

30000070:   6f697470    swivs   0x00697470

30000074:   0000006e    andeq   r0, r0, lr, rrx

    ...


30000080 : //现在reset放在4自己对齐的地方

30000080:   e3a00453    mov r0, #1392508928 ; 0x53000000

30000084:   e3a01000    mov r1, #0  ; 0x0

30000088:   e5801000    str r1, [r0]

3000008c:   e3a00313    mov r0, #1275068416 ; 0x4c000000

30000090:   e3e01000    mvn r1, #0  ; 0x0

30000094:   e5801000    str r1, [r0]

30000098:   e59f0084    ldr r0, [pc, #132]  ; 30000124 <.text+0x124>

3000009c:   e3a01005    mov r1, #5  ; 0x5

300000a0:   e5801000    str r1, [r0]

300000a4:   ee110f10    mrc 15, 0, r0, cr1, cr0, {0}

300000a8:   e3700103    orr r0, r0, #-1073741824    ; 0xc0000000

300000ac:   ee010f10    mcr 15, 0, r0, cr1, cr0, {0}

300000b0:   e59f0070    ldr r0, [pc, #112]  ; 30000128 <.text+0x128>

300000b4:   e59f1070    ldr r1, [pc, #112]  ; 3000012c <.text+0x12c>

300000b8:   e5801000    str r1, [r0]

300000bc:   e3a01000    mov r1, #0  ; 0x0

300000c0:   e5910000    ldr r0, [r1]


下载烧写


程序执行完全没有问题


程序备份修改代码


swi可以根据应用程序传入的val来判断为什么调用swi指令,我们的异常处理函数能不能把这个val值读出来


do_swi:

    /* 执行到这里之前:

     * 1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址

     * 2. SPSR_svc保存有被中断模式的CPSR

     * 3. CPSR中的M4-M0被设置为10011, 进入到svc模式

     * 4. 跳到0x08的地方执行程序 

     */


    /* sp_svc未设置, 先设置它 */

    ldr sp, =0x33e00000


    /* 保存现场 */

    /* 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */

    /* lr是异常处理完后的返回地址, 也要保存 */

    stmdb sp!, {r0-r12, lr}  


/* 2

我们要把lr拿出来保存

因为bl printException会破坏lr


mov rX, lr


我把lr保存在那个寄存器


这个函数 bl printException 可能会修改某些寄存器,但是又会恢复这些寄存器,我得知道他会保护那些寄存器


我们之前讲过ATPCS规则

对于 r4 ~ r11在C函数里他都会保存这几个寄存器,如果用到的话就把他保存起来,执行完C函数再把它释放掉

我们把lr 保存在r4寄存器里,r4寄存器不会被C语言破坏

*/

    mov r4, lr


    /* 处理swi异常 */

    mrs r0, cpsr

    ldr r1, =swi_string

    bl printException



/*1

跳转到printSWIVal

如何才能知道swi的值呢?

我们得读出swi 0x123指令,这条指令保存在内存中,我们得找到他的内存地址

执行完0x123指令以后,会发生一次异常,那个异常模式里的lr寄存器会保存下一条指令的地址

我们把lr寄存器的地址减去4就是swi 0x123这条指令的地址

*/


/*3

我再把r4的寄存器赋给r0让后打印

我们得写出打印函数


mov r0, r4


指令地址减4才可以

swi 0x123

下一条指令bl main 减4就是指令本身

*/

    sub r0, r4, #4

    bl printSWIVal


    /* 恢复现场 */

    ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */


swi_string:

.string "swi exception"


```c

在uart.c添加printSWIVal打印函数


void printSWIVal(unsigned int *pSWI)

{


    puts("SWI val = ");

    printHEx(*pSWI & ~0xff000000); //高8位忽略掉  

    puts("nr");


}


我们再来看看这个程序是怎么跳转的


/*1

发生swi异常,他是在sdram中,CPU就会跳到0x8的地方

swi 0x123  /* 执行此命令, 触发SWI异常, 进入0x8执行 */


*/


/* 2


_start:

    b reset          /* vector 0 : reset */

    ldr pc, und_addr /* vector 4 : und */

执行这条读内存指令

    ldr pc, swi_addr /* vector 8 : swi */


读到swi_addr地址跳转到sdram执行代码 do_swi那段代码

swi_addr:

    .word do_swi


*/


/* 3

这段代码被设置栈保存现场 调用处理函数恢复现场,让后就会跳到sdram执行 swi 0x123的下一条指令

do_swi:

    /* 执行到这里之前:

     * 1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址

     * 2. SPSR_svc保存有被中断模式的CPSR

     * 3. CPSR中的M4-M0被设置为10011, 进入到svc模式

     * 4. 跳到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, #4

    bl printSWIVal


    /* 恢复现场 */

    ldmia sp!, {r0-r12, pc}^  /* ^会把spsr的值恢复到cpsr里 */


swi_string:

    .string "swi exception"

*/

关键字:S3c2440  ARM  异常  中断体系 引用地址:S3c2440ARM异常与中断体系详解5---_swi异常模示程序示例

上一篇:ARM之未定义指令异常和SVC异常
下一篇:S3c2440ARM异常与中断体系详解6---按键中断程序示例概述与初始

推荐阅读

数控加工,是指在数控机床上进行零件加工,用数字信息控制零件和刀具位移的一种机械加工方法,是解决零件品种多变、批量小、形状复杂、精度高等问题和实现高效化和自动化加工的有效途径。 数控机床加工与传统机床加工的工艺规程从总体上说是一致的,但由于数控是一次装夹,连续自动加工完成所有车削工序,所以在进行数控机床加工完成后需要注意一些事项。...
近期,佳能官方宣布,将发布“Vision Edition-U”图像处理软件,该软件从2019年10月开始支持生产站点的自动化。Vision Edition是一套使用摄像头的视觉技术。获得优傲机器人平台“UNIVERSAL ROBOTS +”(UR +)认证后,“Vision Edition-U”将专门为UR机器人销售,这是日本第一家获得UR认证的公司。
在编写GPIO模拟i2c时,下面两个初始化有不同 第一种方法: GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(...
广告摘要声明广告【文/潘敏瑶】“重复、机械、枯燥的工作,让我们无暇顾及家庭,拥有真正的生活,为解决这一现状的协作机器人厂商越来越多,但问题仍未解决。其原因在于我们所生产的机器人只是一个半成品,缺少尤为重要的感知能力。”大族机器人总经理王光能如是说。“真正的智能协作机器人,它应该能感知世界,与环境互动,能够让每一个人在任何时候都能...

史海拾趣

问答坊 | AI 解惑

09国赛E题高级讨论群9742194

本帖最后由 paulhyde 于 2014-9-15 09:04 编辑 09国赛E题讨论群9742194 充电器 [ 本帖最后由 bailong39 于 2009-9-2 11:53 编辑 ]  …

查看全部问答∨

MOSFET的发明人--马丁•阿塔拉(Martin M. "John" Atalla)博士

MOSFET宣告了电子技术的统治地位,并且支撑了当今信息社会的基石——大规模集成电路(LSIs)。 ——Wikipedia 马丁•阿塔拉(Martin M. "John" Atalla(1924.08.04 - ))博士在两个截然的领域内同时受人尊敬。他是MOS场效应晶体管(met ...…

查看全部问答∨

wince 的超级终端

WINCE有没有像超级终端那样的串口工具,如果有,是什么,在哪里能够下到,非常感谢?在GOOGLE好像没搜到.…

查看全部问答∨

关于s3c2410串口的问题

我用IAR编写基于s3c2410的串口通信,对UART0和UART1的控制寄存器进行了同样的配置,UART0能实现串口的输入和输出,但是UART1却实现不了串口的输入和输出了?这是怎么一回事情啊?(GPHCON也配置了),是不是UART1还需要额外的端口配置啊?谢谢…

查看全部问答∨

让软件启动了win ce 6.0系统自动启动 程序

怎么样对注册表 编译实现win ce 6.0 系统开机以后显示桌面,桌面 上在显示我要运行的程序 现在有注册表HKEY_LOCAL_MACHINE\\init目录下     我要实现DeviceApplication3.exe开机桌面后启动 现在有注册表HKEY_LOCAL_MACHINE\\init目录 ...…

查看全部问答∨

请问Wince上不能正确显示越南语怎么解决?

是不是有类似Win PC下那种字库安装文件?谢谢各位了!…

查看全部问答∨

自平衡机器人

前一阵做机器人用的是英培特免费发的板子,不过烧了几个PWM管脚(汗),这次想用剩下的电机和SCA60c角度传感器做个双轮自平衡机器人,类似nbot样的。先试试不用陀螺仪怎样,不行的话在上吧。用顺手了不想换单片机了呵呵…

查看全部问答∨

STM32RTC供电引脚对地内阻3K?

                                 发现量产产品总是丢时钟,结果都是电池没电,而后测量关机状态下RTC供电引脚对地电阻,竟然只有3K,也就是用电电流 ...…

查看全部问答∨

单片机串口控制zigbee模块,

单片机和电脑通信,通过串口调试助手成功。&nbsp; zigbee模块与电脑通信,通过串口调试助手成功。问题是单片机和zigbee模块的通信,死活不行,求助各位大神。有谁有遇到这个问题吗,另外zigbee模块是3.3v的,51单片机可以直接和它连接吗?…

查看全部问答∨

【Quarkbot第一季】基于LabVIEW智能小车无线监控系统

基于LabVIEW智能小车无线监控系统 功能简介: ①通过3G路由器(刷过机的)将视频传至上位机(上位机采用LabVIEW编写),上位机 实时监控画面; ②下位机采用stm32F051,采用40KHz占空比可调的4路PWM信号对4路电机进行控制 使用光电对管进行测速 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved