浅析嵌入式系统之uboot详解(4.1)—内部中断

bootloader详解目录—废铁是怎么产生价值的

浅析嵌入式系统之uboot详解(1)—板子上电后uboot做了什么
浅析嵌入式系统之uboot详解(2)—CPU工作模式
浅析嵌入式系统之uboot详解(3)—看门狗
浅析嵌入式系统之uboot详解(4.1)—内部中断
浅析嵌入式系统之uboot详解(4.2)—外部中断(GPIO)
浅析嵌入式系统之uboot详解(4.3)—异常和异常向量
浅析嵌入式系统之uboot详解(5.1)—时钟分频
浅析嵌入式系统之uboot详解(5.2)—省电模式(番外)
浅析嵌入式系统之uboot详解(5.3)—PWM定时器(番外)
浅析嵌入式系统之uboot详解(6)—关闭缓存和mmu
浅析嵌入式系统之uboot详解(7)—初始化SDRAM


uboot详解—内部中断

1. 前言

  中断这个概念相信都不会陌生,它就是一个信号,告诉cpu先将当前的任务放一放,先去处理一下别的紧急事情。比如自己在家里打扫卫生,这时有客人来了,客人就会按一下门铃,然后自己马上放下当前的事情,去给客人开门,然后继续打扫卫生。这个过程就是一个中断处理过程,门铃声就是一个信号,告诉你有更重要的事情发生了,然后你停下做当前的事情,去处理突发的事情,这个处理突发事情的过程叫中断处理过程。

  当然也有可能多个中断信号同时发生的情况,比如门铃响起的时候,热水器也开始报警了,这个时候应该怎么处理呢?这就涉及到优先级的问题了,比如这时需要先拔掉热水器,以免水溢出来漏电,所以这个的优先级,开门的优先级低。

  上面是我们生活中的例子,但是对于计算机来说,却有更严格的中断信号和更规范的中断处理流程。

2. 中断处理流程

  • 请求中断: 当某一中断源需要CPU为其进行中断服务时,就输出中断请求信号,使中断控制系统的中断请求触发器置位,向CPU请求中断。系统要求中断请求信号一直保持到CPU对其进行中断响应为止。
  • 中断响应: CPU对系统内部中断源提出的中断请求必须响应,而且自动取得中断服务子程序的入口地址,执行中断 服务子程序。对于外部中断,CPU在执行当前指令的最后一个时钟周期去查询INT引脚,若查询到中断请求信号有效,同时在系统开中断(即IF=0)的情 况下,CPU向发出中断请求的外设回送一个低电平有效的中断应答信号,作为对中断请求INT的应答,系统自动进入中断响应周期。
  • 关闭中断: CPU响应中断后,输出中断响应信号,自动将状态标志寄存器CPSR保护起来,然后将中断标志位IF与陷阱标志位清零,从而自动关闭外部硬件中断。因为CPU刚进入中断时要保护现场,主要涉及堆栈操作,此时不能再响应中断,否则将造成系统混乱。
  • 保护断点: 保护断点就是将CPSR和PC当前内容保存,以便中断处理完毕后能返回被中断的原程序继续执行,这一过程也是由CPU自动完成。
  • 中断源识别: 当系统中有多个中断源时,一旦有中断请求,CPU必须确定是哪一个中断源提出的中断请求,并由中断控制器给出中断服务子程序的入口地址,装入LR和SPSR两个寄存器。CPU转入相应的中断服务子程序开始执行。
  • 保护现场: 主程序和中断服务子程序都要使用CPU内部寄存器等资源,为使中断处理程序不破坏主程序中寄存器的内容,应先将断点处各寄存器的内容压入堆栈保护起来,再进入的中断处理。现场保护是由用户使用PUSH指令来实现的。
  • 中断服务: 中断服务是执行中断的主体部分,不同的中断请求,有各自不同的中断服务内容,需要根据中断源所要完成的功能,事先编写相应的中断服务子程序存入内存,等待中断请求响应后调用执行。
  • 恢复现场: 当中断处理完毕后,用户通过POP指令将保存在堆栈中的各个寄存器的内容弹出,即恢复主程序断点处寄存器的原值。
  • 中断返回: 在中断服务子程序的最后要安排一条中断返回指令,系统自动将保存的值恢复,从而恢复主程序断点处的地址值,同时还自动恢复标志寄存器的内容,使CPU转到被中断的程序中继续执行。

  在这里首先需要明确的一点是CPSR寄存器中断 I 和 F两个标志位的作用,这两个标志位是IRQ和FIQ的总开关,所以如果要进行后面中断操作,必须先确保这两位是0(没有禁止IRQ和FIQ)
在这里插入图片描述
下面是s3c2440的外部中断和内部中断的概图,从图中可以看出,外部中断和内部中断从SRCPND开始,后面的过程都是相同的。后面在仲裁部分举的例子就可以不用区分外部中断和内部中断了。
在这里插入图片描述
下图对内部中断的处理过程进行了简化:
在这里插入图片描述
从上面这张图中可以看出以下几点:

  1. 中断源有两种(如下图),一种是单一中断源,一种是复合中断源,复合中断源是子中断源的复合信号。比如实时时钟中断、看门狗中断,该硬件只会产生一种中断,它是单一中断源,它直接将其中断信号线连接到中断源寄存器上。对于复合信号,以UART串口为例进行说明,UART串口可以产生3种中断:接受数据中断INT_RXDn,数据错误中断INT_ERRn,发送数据中断INT_TXDn。这3个子中断信号在中断源寄存器复合为一个中断信号INT_UARTn,3种子中断源任何一个产生都会将中断信号传递给对应的中断源INT_UARTn,然后通过中断线传递给ARM内核。
    在这里插入图片描述
    从datasheet中我们可以看到以下中断源:
    在这里插入图片描述 在这里插入图片描述
    前面我们将中断信号分了单一中断和复合中断,我们也可以根据硬件的连接方式将中断源分为外部中断内部中断,从上面的图可以看到,EINT0~EINT23可以连接外部中断,其他5个是内部中断,如果包含了子中断表示该中断也是复合中断,如果没有包含子中断,表示该中断是单一中断。内部中断的连接方式我们是不可以修改的,但是我们可以修改外部中断,通过编程或者连线将外设的中断线连接到cpu对应的中断引脚上,然后通过编程就可以处理外设的中断请求了。

  2. SUBSRCPND:子中断源暂存寄存器,该寄存器用来标示保存子中断源信号,当某个子中断信号产生后,SUBSRCPND对应位被自动置1,该位会一直保存被置,直到中断处理程序将其清除为止,需要注意一下,清除中断是向对应位写入1来清除,而不是写入0,写入0无效,“The SRCPND and INTPND registers can be read and written, so the service routine must clear the pending condition by writing a 1 to the corresponding bit in the SRCPND register first and then clear the pending condition in the INTPND registers by using the same method.”
    该寄存器的位被设置和优先级没有关系,如果有多个复合中断源同时到达,那么对应的子中断位都被设为1

    下表是SUBSRCPND寄存器的datasheet:
    在这里插入图片描述
    当没有中断请求的时候,对应位是0,当中断请求到达的时候,对应中断位置1,中断请求处理完成的时候,需要将1初始化为0
    在这里插入图片描述
    Map To SRCPND说明存放在子中断暂存寄存器中的中断最终的复合中断是哪个,比如INT_RXD0最终的复合中断是INT_UART0

  3. INTSUBMSK:子中断源屏蔽寄存器,该寄存器用来屏蔽子中断源信号,默认值为全部子中断都被屏蔽,所以当一个子中断信号到达时,SUBSRCPND对应子中断位会被置1,如果对应子中断的掩码位为0,则该子中断信号将送往SRCPND寄存器,如果对应的子中断的掩码位为1,则该子中断信号将被block,并初始化SUBSRCPND的对应子中断位为0(通过写1),因此想要处理某个中断,必须要打开中断屏蔽位,通过写入0来取消屏蔽中断,如下图,内部子中断默认都是屏蔽的。
    在这里插入图片描述

  4. SRCPND:中断源暂存寄存器,该寄存器用来保存中断源信号,当某个中断信号产生之后,SRCPND对应位被自动置1,该位会一直保存被置位,直到中断处理程序将其清除为止,需要注意一下,清除中断是通过向对应位写入1来清除,而不是写入0,写入0无效。

    不管是外部中断信号还是内部中断信号,最终都汇集在SRCPND寄存器中进行标示,所以后面对两种中断的处理过程都是一样的。
    在这里插入图片描述
    在这里插入图片描述

  5. INTMSK:中断屏蔽寄存器,这个寄存器是和子中断屏蔽寄存器相对应的,功能和子中断屏蔽寄存器类似,如果一个中断使SRCPND中断标示位置1,那么INTMSK寄存器就会根据设置是否屏蔽这个中断。
    在这里插入图片描述
    在这里插入图片描述

  6. INTMODE:中断模式寄存器,这个寄存器是用来指定中断信号的对应中断模式的,如果是对应位设置为0表示一般中断模式,对应位设置为1表示快速中断模式,如果是一般中断模式,那么中断信号将通过优先级仲裁,如果指定为快速中断,那么中断信号直接送给ARM内核产生中断,需要注意的是,FIQ快速中断没有优先级仲裁,所以INTMODE只能指定一个中断源为FIQ,以免产生竞争,而且被指定为快速中断的中断信号不会影响INTPND和INTOFFSET寄存器。我们一般讨论一般默认的是 一般中断模式。
    在这里插入图片描述
    在这里插入图片描述

  7. PRIORITY:中断优先级控制寄存器,或者说是仲裁寄存器,通过设置仲裁组n优先级排序方式位,设置每个仲裁组内中断信号的优先级顺序,比如ARB_SEL5分组时包含4个中断信号:REQ1 INT_UART0, REQ2 INT_SPI1, REQ3 INT_RTC, REQ4 INT_ADC,然而ARB_SEL5位采用默认值:00,所以当INT_UART0和INT_RTC中断信号同时产生时,INT_UART0排在前面,它会被选中,通过编程方式可以改变优先级排序方式来改变中断信号的优先级。

    ARB_MODE0~ARB_MODE6为每个仲裁分组的优先级轮转设置位,采用默认值1时,当前中断信号被选择处理之后,再次产生中断请求时,它的优先级自动轮转到该组最低,这样可以保证优先级低的中断信号可以被及时处理,不至于出现优先级高且中断请求频繁的中断每次都被优先处理,而优先级低的被“饿死”的情况,这种方式更民主,实时性更佳。
    在这里插入图片描述
    上面这张图是ARM s3c2440中断请求的连接方式,一共有6个中断仲裁器(ARBITER0~ARBITER5)和一个总中断仲裁器(ARBITER6),每一个中断仲裁器都可以连接最多6个中断源。
    在这里插入图片描述
    上面这张图是中断优先级控制寄存器的DATASHEET,主要由两组配置项构成:ARB_SEL(仲裁选择)和ARB_MODE(仲裁模式),我们可以看到有7个仲裁选择器,相应的也有7个仲裁模式设置位,每一个仲裁选择器对应两位,每一个仲裁模式对应一位。

    每一个仲裁选择器可以连接6个中断信号源,虽然ARB_SEL0连接了4个中断源,但是其他几个都接了6个中断源,通过设置仲裁选择器的两位可以改变它们的优先级顺序,如表格所示:REQ0总是优先级最高的,而REQ5总是优先级最低的,REQ1~REQ4共4个中断源可以通过设置PRIORITY的对应两位改变它们的优先级顺序。

    ARB_MODE是用来设置仲裁选择器的轮转优先级的,比如默认情况下ARB_SEL0~ARB_SEL5对应的ARB_MODE默认值都是1,一开始ARB_SEL0的优先级是最高的,一次递减,这时所有的仲裁选择器都会进行优先级轮转,比如有三个信号同时到达:ARB_SEL0 ~ EINT0, ARB_SEL0 ~ EINT1, ARB_SEL1 ~ INT_WDT,也就是说ARB_SEL0上有两个中断请求信号,ARB_SEL1上有一个中断请求信号,因为刚开始ARB_SEL0的优先级最高,而且EINT0的优先级比EINT1的优先级高,那么会先处理EINT0请求,然后处理EINT1请求,这时ARB_SEL0仲裁选择器的请求都处理完了,根据ARM_MODE0=1,就会将ARB_SEL0的优先级进行轮转,把ARB_SEL0优先级设为最低,排到ARB_SEL5的后面,这时ARB_SEL1的优先级就最高了,接着cpu就处理ARB_SEL1上的INT_WDT请求了。

    如果ARB_MODE0~ARB_MODE5全部设为0,那么他们就不进行轮转,一直保持ARB_SEL0的优先级最高,ARB_SEL5的优先级最低,这样就可能发生一种情况,如果ARB_SEL0上有连续的中断请求需要处理,那么ARB_SEL5上的中断请求就可能等很长时间才能够处理。这里需要了解一点,中断请求虽然有先后处理之分,但是中断处理过程一般是不可中断的,也就是说,正常情况下cpu在处理EINT0中断请求的时候,如果产生了EINT1请求是不会打断EINT0的处理过程的,需要等EINT0处理完成后再处理EINT1,这个叫排队。

    如果ARB_MODE0,ARB_MODE2,ARB_MODE5设置为0,其他都设置为1,那么对应的三个ARB_SEL0,ARB_SEL2,ARB_SEL5会参与轮转,经过几个周期后ARB_SEL1,ARB_SEL3,ARB_SEL4优先级将排在前面,0,2,5进行轮转

  8. INTPND:最高优先级暂存寄存器,这个寄存器保存的是经过仲裁器后的最终结果,它是当前中断请求里面优先级最高的中断,因此该寄存器里面的值最多有1位,通常中断处理程序会通过读取该寄存器的值来获得当前正在处理的中断请求,中断处理完成后,通过写入1来清除中断。
    在这里插入图片描述 在这里插入图片描述

  9. INTOFFSET:中断号偏移量寄存器,该寄存器存放的是经过优先仲裁出的中断信号对应的中断号,是一个0~31之间的整数,其实他就是INTPND里对应的位号,比如:INT_UART0产生了中断,INTPND里的第28位就被置1,INTOFFSET里保存的整数就是28,多处理啊这个寄存器的目的主要是方便中断处理程序查询中断源,清除中断源。
    在这里插入图片描述

通过前面分分析,我们现在知道,对于复合中断信号,从发送请求信号到cpu收到信号一共需要经过9个步骤:

  • 外部设备或内部设备产生中断请求,通过改变与cpu连接的中断引脚的电平状态,cpu就能够识别到该引脚上有中断信号产生,比如有一个INT_RXD0信号产生,用来告诉cpu有新的串口数据到来,赶紧接收,从电路图中就可以看到,cpu的RXD0/PGH3的引脚在中断模式下就能够识别到这个信号。当然对于一些GPIO引脚,需要将这个引脚设置成中断模式才能够识别成中断信号,如果是设置的是输入输出模式,就不会将电平的状态识别为中断信号了,要将RXD0/PGH3引脚设置成中断模式,从datasheet中可以看出,只要将GPHCON的第[7:6]位设置成b10就可以了。
    在这里插入图片描述
    在这里插入图片描述

  • cpu的RXD0/PGH3引脚在中断模式时,根据电平的变化,就知道INT_RXD0中断请求发生了,然后SUBSRCPND寄存器的第[0]位就会被置1,接着和SUBSRCMSK寄存器的对应位进行验证

  • 当SUBSRCMSK寄存器的第[0]位被置为0的时候,表示INT_RXD0中断请求是允许通过的,这个请求继续递交给SRCPND。

  • 这个信号到达SRCPND寄存器的时候,SRCPND的第[0]位将会被置1,接着和SRCMSK寄存器的对应位进行验证

  • 当INTMSK寄存器的第[0]位被置为0的时候,表示INT_RXD0中断请求是允许通过的

  • 判断INTMODE该中断请求当作 IRQ 请求还是 FIQ请求, 如果是FIQ请求则直接通知ARM处理器进行处理

  • 这个请求继续递交给仲裁器,如果有多个中断请求同时到达,则进行优先级比较,得出优先级最高的请求

  • 将INTPND的相应位置1,这时INTPND的INT_UART0位([28]位)被置1

  • 将十进制28存入INTOFFSET寄存器中

  前面讲解了一个中断的产生到cpu获取到信号的过程,大概寄存器的变化就是:SRC——》SUBSRCPND对应位置1——SRCPND对应位置1——INTPND对应位置1——》ARM,那么这些位置1以后,应该怎么样清除这些位呢?因为当中断处理程序完成处理过程中,需要关闭中断,处理完成后需要清除这些被置1的位,那么这个过程应该怎么执行呢?
为什么需要中断清楚呢?因为我们逻辑电路里使用高低电平来描述我们的逻辑1或0的,那我们比如一个按钮作为中断源用下降沿触发,我们按下去,松开得过程,就是高电平降到低电平的过程,产生了下降沿,相应的中断控制寄存器里的位就会记录1。按下去之后,那个高电平中断信号就在寄存器里面记录着,如果我们没有人为地改动,它能改变吗?显然是不能的,那么就需要程序员来人为地消除,否则就会一直发送中断的信号,ARM一直接收和处理这个中断信号显然不是我们想要的。

  如何清除,那也是要用到中断信号标志的寄存器如SRCPND、SUBSRCPND、INTPND等。这里就有个问题,我们是从中断信号的源头开始清除呢还是从靠近ARM的地方开始清除呢?首先看看从靠近ARM的地方开始行不行,我们举例EINT4(这是属于外部中断,下一级是一级中断)的清除。我们的思路是,INTPND设置为0,然后SRCPND(一级中断)相应位设置为0,最后把EINTPEND设置为0对吧?这里就会有问题,INTPND的值是从SRCPND传过来的,那么我们把INTPND清0,但是SRCPND还是没有改变状态,还是为1,那么SRCPND还是会把INTPND设置为1,这样就说明,我们从靠近ARM的那边开始清除是不行的。

好的,我们从源头开始清除,下面是三种中断的处理思路:

  • 一级中断:SRCPND–>INTPND

  • 二级中断:SUBSRCPND–>SRCPND–>INTPND

  • 外部中断:EINTPEND–>SRCPND–>INTPND

  我们按顺序把他们清0即可。但是这里要注意!Datasheet里说明,我们把相应位置1即可,它就会自动把它清零,而我们直接赋值置0是无效的。

  我们知道,开机的时候需要对中断进行初始化, 当然包括内部中断和外部中断的初始化,因为这两个中断的初始化有重复的部分,这里就不进行举例了。

3. 总结

  这篇文章主要介绍了内部中断相关的寄存器,从内部中断源的产生到触发cpu处理的过程都有详细的分析,后面将介绍外部中断,异常处理向量,中断处理程序等内容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ʚ兔子的先森ɞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值