历史上的今天

今天是:2024年09月03日(星期二)

正在发生

2021年09月03日 | 11.S3C2440 中断实验(一)und和swi实验

发布者:xinyi9008 来源: eefocus关键字:S3C2440  中断实验 手机看文章 扫描二维码
随时随地手机看文章

S3C2440 中断体系结构

ARM的7种工作模式

用户模式(usr):ARM处理器正常的程序执行状态

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

中断模式(irq):用于通用的中断处理

管理模式(svc):操作系统使用的保护模式

数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护

系统模式(sys):运行具有特权的操作系统任务

未定义指令终止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真

在这里插入图片描述

        除了用户模式之外,其他的6种工作模式都属于特权模式。大多数程序运行于用户模式,进入特权模式是为了处理中断、异常或者访问被保护的系统资源。


        当发生各类中断、异常时CPU自动进入相应的模式。当在特权模式时,可以通过软件来进行模式切换。


        ARM的CPU有两种工作状态:ARM状态和Thumb状态。ARM状态下CPU执行32位的字对齐的ARM指令;Thumb状态下CPU执行16位的半字对齐的Thumb指令。CPU上电复位后处于ARM状态。


        目前我们只关心ARM状态下的操作。在ARM状态下,ARM920T有31个通用寄存器和6个程序状态寄存器,这些寄存器都是32位的。这37个寄存器分为7组,如下图所示:

在这里插入图片描述

        图中的Banked register,即备份寄存器,专属于相应的工作模式。不同的工作模式下都有自己的副本,当切换到另一个工作模式时,那个工作模式的寄存器副本就将被使用。


        ARM状态下,每种工作模式都有16个通用寄存器和1~2个程序状态寄存器。除了R15寄存器之外,R0~R14都是通用寄存器,这些寄存器既可以用于保存数据,也可以用于保存地址。R15又叫PC,就是我们所熟知的程序计数器。需要指出,通常R13~R15都有特殊用途。其中,R13又被称为栈指针寄存器,通常被用于保存栈指针,简记为sp。R14又被称为程序连接寄存器(link register),当执行BL指令调用子程序时,R14中得到跳转前要执行的下一条指令的地址。当发生中断或异常时,对应的相应模式R14中保存返回值。

        快速中断模式中有7个备份寄存器R8~R14,这使得进入快速中断模式执行时,不需要保存R8~R14寄存器。其他特权模式只有两个备份寄存器R13、R14。

        CPSR(Current Program Status Register,程序状态寄存器)是一个很重要的寄存器,具体如下图所示:

在这里插入图片描述

各比特位的含义如下所示:

第0到第4比特位 M[4:0]:表明CPU当前处于什么工作模式,设置后使CPU进入指定的工作模式。除了sys模式之外,其他特权模式下都有SPSR寄存器(Saved Program Status Registers,程序状态保存寄存器)。当切换到这些工作模式时,在SPSR中保存前一个工作模式的CPSR值。当返回到之前的工作模式时,可以将SPSR的值恢复到CPSR中。

在这里插入图片描述

第5比特位T位:置1时表明CPU处于Thumb状态,置0时表示处于ARM状态。

第6比特位F位、第7比特位I位:这两比特位都属于中断禁止位。当置1时,对应的FIQ中断和IRQ中断分别被禁止。

发生异常或中断

当发生异常或中断时,ARM920T CPU核将自动完成以下工作:


在该特权模式的lr寄存器中保存之前工作模式的将要执行的下一条指令的地址。对于ARM状态,这个值可能是PC值+4或者+8。具体情况如下表所示:

在这里插入图片描述

将CPSR的值复制到对应的特权模式的SPSR中;

将CPSR的工作模式位设置为新的特权模式对应的值;

令PC等于该异常或中断对应的异常向量表中的地址。异常向量表和对应的工作模式如下图所示:

在这里插入图片描述

退出异常工作模式

在特权模式下,将lr减去一个适当的值,之后赋给PC

在这里插入图片描述

将SPSR的值赋值给CPSR

S3C2440中断控制器

CPU在运行过程中,对于如何检测到各类外设发生的随机事件,主要有以下两种方法:


查询方式: 程序循环地查询各设备的状态。这样做效率太低,不适合并发。

中断方式:当某事件发生时,硬件会设置某个寄存器。CPU在每执行完一条指令后,都会区检测这个寄存器,如果发生了事件,则CPU中断当前流程,跳转到一个固定的地址去处理该事件,之后返回原来被中断的程序继续执行。


无论是何种CPU,中断的处理过程是相似的。

在这里插入图片描述

首先由中断控制器汇集 各类外设发出的中断信号,之后通知CPU;

CPU保存当前程序的运行上下文,然后调用中断服务程序ISR(Interrupt Service Routine)来处理这些中断;

在ISR中通过读取中断控制器、外设相关寄存器来识别中断并进行相应的处理;

清除中断

恢复被中断程序的运行上下文,然后继续执行。

我们通过S3C2440的用户手册可以得到其中断控制器的结构如下图所示:

在这里插入图片描述

如上图所示,SUBSRCPND和SRCPND寄存器表明有哪些中断被触发了,正在等待处理。而SUBMASK和MASK寄存器则起到开关的作用,用于屏蔽某些中断。


当Request sources(without sub-register)中的中断源被触发之后,SUBSRCPND寄存器中相应位被置1,如果此中断没有被SUBMASK寄存器屏蔽的话,它在SRCPND寄存器中的相应位也会被置1,之后处理过程和2一样;

当Request sources(without sub-register)中的中断源被触发后,SRCPND寄存器中相应位被置1,如果此中断没有被INTMASK寄存器屏蔽的话,或者此中断是FIQ,那么它将被路由至下一步。

如果被触发的中断是FIQ,那么CPU进入快速中断处理模式;如果是一般中断IRQ,那么可能同时有几个中断被触发,未被屏蔽的中断会全部进入到优先级比较器,优先级最高的中断胜出,并将INTPND寄存器中相应的位置1,然后CPU进入IRQ中断模式进行处理。中断服务程序会结合INTOFFSET和INTPND寄存器来确定中断源。

中断源和子中断源

对于某些中断来说,比如INT_UART0中断源,其需要细分为三个子中断源:INT_ERR0、INT_TXD0、INT_RXD0,用以分别表示UART0的出错中断、发送中断和接收中断。


S3C2440的中断源和子中断源如下图所示:

中断源:

在这里插入图片描述

子中断源:

在这里插入图片描述

相关寄存器

与中断控制器相关的寄存器有8个。其中,SUBSRCPND和INTSUBMSK这两个寄存器中相同的位对应相同的中断;SRCPND、INTMSK、INTMOD、INTPND这四个寄存器相同的位对应相同的中断。


SUBSRCPND寄存器

在这里插入图片描述

SUBSRCPND用来标志INT_RXD0、INT_TXD0等中断是否已经发生。在S3C2440中,这类子中断共有15个。每位对应一个中断。当中断发生时,对应位被置1,之后如果INTSUBMSK中对应的位没有被置1屏蔽,那么它们中的若干位将汇集到SRCPND寄存器中的某一位上。如SUBSRCPND寄存器中的INT_ERR0、INT_TXD0和INT_RXD0这3个中断,只要有一个子中断发生且没有被屏蔽,那么SRCPND寄存器中的INT_UART0位将被置1。SUBSRCPND寄存器中具体哪几位对应SRCPND寄存器中的一位,如下图所示:

在这里插入图片描述

对于SUBSRCPND寄存器,往其中某一位写1,则即可将该为清零,写0无效果,寄存器中原数据保持不变。


INTSUBMSK寄存器

INTSUBMSK寄存器被用来屏蔽SUBSRCPND寄存器中所标志的中断。置1表示屏蔽对应位上的中断。

在这里插入图片描述

SRCPND寄存器

在这里插入图片描述

SRCPND寄存器中每一位被用来表示一个或者一类中断是否已经发生。“一类中断”自然指的是那些对应有SUBSRCPND的中断。

和SUBSRCPND类似,想要清除SRCPND寄存器中的某一位,往此位写1即可。

INTMSK寄存器

INTMSK寄存器被用来屏蔽SRCPND寄存器中所标志的中断。置1屏蔽。需要说明的是,INTMSK寄存器只能屏蔽被设置为IRQ的中断,而不能屏蔽被设置为FIQ的中断。怎么将中断设置为FIQ,详见下面的INTMOD寄存器。

在这里插入图片描述

INTMOD寄存器

当INTMOD寄存器中的某一位被设置为1时,它对应的中断被设置为FIQ。之后,若此发生此中断,那么CPU将进入快速中断模式,这通常用来处理特别紧急的中断。

需要说明的是,在同一时刻,INTMOD寄存器中只能有一位被设置为1。

在这里插入图片描述

PRIORITY寄存器

优先级寄存器我们接下来用一节专门讲解。这里强调一点,优先级比较只针对于IRQ中断。因为有之前的框图也可知,FIQ直接到达CPU了。我们把IRQ中断叫做普通中断,简称中断。

INTPND寄存器

经过中断优先级仲裁器选出的优先级最高的中断,将被设置进INTPND寄存器。即INTPND寄存器中对应的位被置1。此后CPU将进入中断模式处理它。显然,同一时刻,INTPND寄存器只能有一位被置1。在ISR中,我们可以根据这一位来断定是哪一个中断发生了。

同样,写1清零。

在这里插入图片描述

INTOFFSET寄存器

INTOFFSET寄存器被用来表示INTPND寄存器中哪一位被置1了,即当INTPND寄存器中位[x]被置1了,那么此时INTOFFSET寄存器的值就是x。x的取值范围是闭区间[0, 31]。

当清除SRCPND、INTPND寄存器时,INTOFFSET寄存器被自动清零。

在这里插入图片描述

优先级比较器

S3C2440将不同的中断分为几组,每一组内先进行比较,之后每一组的胜出者再进行比较,最终决出优先级最高的一个中断,如下图所示:

在这里插入图片描述

关于优先级设置,我们先看一下优先级设置寄存器:

在这里插入图片描述

每一个仲裁器都含有6个输入引脚,PRIORITY寄存器使用三位来控制其行为,一位是ARB_MODE,用于选择工作模式;另外两位是ARB_SEL,被用于控制输入信号的优先级。

由于ARB_SEL是两位,所以其优先级设置有四种方式:

在这里插入图片描述

我们可以看到,无论ARB_SEL设置为任何值,REQ0的优先级始终是最高的,REQ5的优先级始终是最低的。

当我们将工作模式位ARB_MODE设置为0时,对应的ARB_SEL位是不会自动变化的,也就是说该仲裁器的6个输入引脚的优先级是固定不变的。当ARB_MODE位被置1时,ARB_SEL会随着已经被服务过的REQ自动变化,服务过谁,那么就设置为谁优先级最低,如下图所示:

在这里插入图片描述

异常实验

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

如上图所示,我们先实现异常向量表,并进行reset、und和swi异常的实验。当系统复位或上电时,我们打印出booting;当执行未定义机器指令时,打印出Undefiend instruction;当进行软中断调用时,我们打印出调用号。


我们知道,SVC、Und、Abt、IRQ、FIQ模式都有自己的堆栈,而Usr和Sys模式共用一个堆栈。所以我们在它们各自的处理过程中首先就要初始化栈指针。由之前的博客介绍可以知道,JZ2440开发板外接了两片EM63A165TS-6G,每片大小为32MB,所以JZ2440外接内存大小一共为64MB。由于ARM的堆栈是满减栈,所以我们将各个模式的堆栈指针依次设置在内存最高地址处。SDRAM接在BANK6,对应的基址是0x30000000,故最高内存地址为0x34000000。设置每个栈大小为4KB。所以:


sp_svc = 0x34000000

sp_und = 0x‭33FFF000‬

sp_abt = 0x‭33FFE000‬

sp_irq = 0x‭33FFD000‬

sp_fiq = 0x33FFC000

sp_usr_sys = 0x33FFB000


如下所示,我们先构造中断向量表:


.text 

.global _start

_start:

b reset //SVC

b undEXP //Und

b swiEXP //SVC

b AbortPrefetch //Abort

b AbortData //Abort

b reset

b IRQINT //IRQ

b FIQINT //FIQ


其中reset标号对应的就是以前正常启动的代码,而其他标号则对应各个异常的处理程序。需要特别注意的是,这里的跳转指令需要使用位置无关跳转,同时不能使用bl指令,因为它会修改lr寄存器,使得异常处理之后需要返回的地址被覆盖掉。


下面我们分别来介绍各个异常处理过程。


未定义指令异常

我们将und模式下的栈指针设置为0x‭33FFF000‬。

当pc指向的地址中存储的是一条非法指令时,cpu将其取指到指令寄存器中,执行时就会产生未定义指令异常。由上面的异常退出表可知,此时lr寄存器中保存的就是待返回的用户程序指令地址。所以我们直接将r0~r12寄存器,还有lr_und保存到栈中。之后直接调用C函数进行相应的异常处理即可。


由于此时lr寄存器中保存的是用户程序中的下一条指令的地址。所以导致未定义指令异常的指令就是之前地址的内容。故lr_und - 4就是未定义指令的地址。我们将该地址作为实参传递给异常处理函数,方便其进行异常处理。


在C处理函数返回之后,我们弹栈并恢复CPSR寄存器即可。代码如下所示:


undEXP:

ldr sp, =0x33FFF000

/*因为lr是异常处理后的返回地址,所以不用修正lr */

/* 保存r0-r12以及lr*/

//使用满减栈

stmdb sp!, {r0-r12, lr} 

//lr减4,即为导致异常的指令地址

sub r0, lr, #4

bl undExpHandler

/* 恢复现场 */

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


void undExpHandler(unsigned int* undAddr) {

printf("Undefined Instruction(0x%08x) at address(0x%08x) is found!nr",

*undAddr, undAddr);

}


软件中断异常

由于swi模式对应的是SVC管理员模式,所以我们将swi模式下的栈指针设置为0x34000000。

同样在开头需要将r0~r12以及lr寄存器压栈。

当我们调用swi xx的时候,则会进入管理员模式,此时通常是为了调用一个特殊的管理员模式下的功能函数。由于此时lr保存的也是程序要返回的地址,所以lr_svc - 4就是swi指令所在的地址。我们取出swi指令的二进制值,同时结合swi指令格式:

在这里插入图片描述

我们可知swi指令中的数字序号就存放在低24位中,故我们可以取出该软件中断号,并传给C处理函数。

在C处理函数返回之后,我们弹栈并恢复CPSR寄存器即可。代码如下所示:


swiEXP:

ldr sp, =0x34000000

/*因为lr是异常处理后的返回地址,所以不用修正lr */

/* 保存r0-r12以及lr*/

//使用满减栈

stmdb sp!, {r0-r12,lr} 

//lr减4,即为导致异常的指令地址

ldr r0, [lr, #-4]

//只保留低24位的软件号

bic r0, r0, #0xFF000000

bl swiExpHandler

/* 恢复现场 */

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


void swiExpHandler(unsigned int swiNum) {

printf("Software Exception is Checked with Number %d(0x%x)nr", swiNum, swiNum);

}


指令预取异常和数据预取异常

这两个异常对应的模式都是abt模式,所以我们设置其栈指针为0x‭33FFE000。和前两个处理流程几乎一样,需要特别注意的是,数据预取异常需要在开头修正lr,令lr = lr - 8;指令预取异常修正lr = lr - 4。其他的没有什么区别。这两个异常的处理代码如下所示:


AbortPrefetch:

ldr sp, =0x33FFE000

subs lr, lr, #4

//使用满减栈

stmdb sp!, {r0-r12, lr} 

sub r0, lr, #4

bl abortPrefetchExpHandler

/* 恢复现场 */

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

AbortData:

ldr sp, =0x33FFE000

subs lr, lr, #8

//使用满减栈

stmdb sp!, {r0-r12, lr} 

mov r0, lr

bl abortDataExpHandler

/* 恢复现场 */

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


void abortPrefetchExpHandler(unsigned int* abtPrefetchAddr) {

printf("Fetch instruction from address(0x%08x) failed.nr", abtPrefetchAddr);

}


void abortDataExpHandler(unsigned int* abtDataAddr) {

printf("Fetch data failed at address(0x%08x).nr", 

abtDataAddr);

}


IRQ中断和FIQ中断

按照我们之前的设定,我们将IRQ的栈指针初始化为0x‭33FFD000,我们将FIQ的栈指针初始化为0x33FFC000。同时还要将二者的lr寄存器进行修正, lr = lr - 4才是程序真正应该返回的地址。在本文中,对于irq普通中断和fiq快速中断,我们调用C处理函数,并处理中断返回工作。在C函数中只先简单打印一行提示。具体任务将在下一篇文章中详述,下一篇文章将进行按键中断点灯和按键fiq快速中断点灯,同时采用串口中断进行收发数据。


IRQINT:

ldr sp, =0x33FFD000

subs lr, lr, #4

//使用满减栈

stmdb sp!, {r0-r12, lr} 

bl irqExpHandler

/* 恢复现场 */

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

FIQINT:

ldr sp, =0x33FFC000

subs lr, lr, #4

//使用满减栈

stmdb sp!, {r0-r12, lr} 

bl fiqExpHandler

/* 恢复现场 */

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


void irqExpHandler(void) {

printf("IRQ is Enter!nr");

}


void fiqExpHandler(void) {

printf("FIQ is Enter!nr");

}


添加触发代码

为了在实验中触发未定义指令异常和软件中断异常,我们在代码拷贝到内存之后添加未定义指令0xdeadC0de和swi软件中断调用,如下所示:


ldr r0, =bootMsg

bl uart0_puts


swi 0x2020

.word 0xdeadC0de


ldr lr, =halt

ldr pc, =main //这才是真正跳转到内存中开始运行


实验结果如下图所示:

在这里插入图片描述

关键字:S3C2440  中断实验 引用地址:11.S3C2440 中断实验(一)und和swi实验

上一篇:11.S3C2440 中断实验(五)定时器中断实验
下一篇:S3C2440 开发板实战(4):外部中断

推荐阅读

随着社会的进步和经济的发展,电销行业已渗透到了房地产、金融投资等生活中的方方面面。电销人员需要沟通的客户,往往有着不同的经历和性格,从事着不同的行业,有着自己的喜与怒。 对于时常需要处理客户投诉、安抚客户情绪的企业来说,电销人员在沟通的过程中,难免会遭遇客户的刁难,甚至是嘲讽和谩骂。不管是在现代企业的售后中,还是在售前沟通中...
选取DMA1选取通道2SPI1USART3根据上面这些配置初始化,参考32例程。下面是我配置的SPI中断,我把它直接放在SPI初始化函数后面先中断初始化然后建立外设之间的连接void SPI1_IRQHandler(void)USART3->DR=SPI1->DR;再直接进行地址映射,把SPI1外设直接映射到USART3。使能SPI的DMA发送请求PI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx|SPI_I2S_DMAReq_Rx, ENABLE); 就会启动DMA主函数
开发环境单片机:PIC18F45K80IDE: MPLAB X IDE未知异常char * str 与 char str[] 差异导致?//输出正常int strcmp_new(unsigned char *src){ putch(*(src)); putch(*(src+1)); putch(*(src+2)); putch(*(src+3)); } char arr[4]=[0x31,0x32,0x33,0x34]; char* rxdata=arr; strcmp_new(rxdata); //...
具体实现功能具体仿真功能为:货物种类一共设有8种,这8种商品通过选择按键进行选择确认,通过数量选择按键确定购买数量,价格规定为1-8元不等;货币识别器能够识别1元硬币、1元纸币、5元纸币、10元纸币、20元纸币50元纸币以及100元纸币。在规定的时间内,投了几次货币后,货币能够实现自动累加功能,这样设计会把投入的所有货币总额数目数据传递到中央控...

史海拾趣

问答坊 | AI 解惑

基于GPRS&CDMA网络的环保监控系统

引言环境监测部门作为国家环境保护系统的技术部门,是环境管理工作的重要基础。随着市民环境意识的增强,越来越多的人开始关心所处环境质量的好坏,要求环境保护工作透明化;上级主管部门也需要数量大、种类多、更新快的信息。所有这一切,给环境监 ...…

查看全部问答∨

如何才能满足I1>>IB

在分压式偏置电路中,如何才能满足I1>>IB?(看的是绿色的那本教材童诗白的第2.4.2节上)…

查看全部问答∨

无线路由怎么配

我有一54M无线宽带路由器,配置以后开始的时候迅雷下载有30k左右,接的是铁通的2m的网,重启后,过了一会就变得很慢,只有1k,再调也很慢!请高手解决一下,有什么优化手段!?…

查看全部问答∨

怎么将硬件的如考勤机上的数据在电视上某一区域显示出来。

怎么将硬件的如考勤机上的数据在电视上某一区域显示出来。 有一个考勤机,刷卡后能够在电视上显示出来,怎么做呀?没有做过的。…

查看全部问答∨

如何生成。MAP文件

用PB编译WINCE下面的BSP包时,能否生成相应驱动的.map文件呀?因为想看看.map来分析错误的地方?谢谢 !…

查看全部问答∨

手机电池充放电保护电路

请问那位仁兄有手机电池充放电保护电路,小弟现在急需,望仁兄帮帮忙,谢谢!!…

查看全部问答∨

金刚狼 MSP430FRAM Wolverine

还记得“金刚狼”(Wolverine)吗?这个在电影《金刚狼》中具有超强自愈能力的不死英雄,如今,又回来了!日前,德州仪器(TI)推出了号称“全球最低功耗”的微控制器平台—“金刚狼”,直接将应用目标锁定在便携式医疗、智能感知与计量、能量收集、消 ...…

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

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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