at91sam9261的AIC学习

At91sam9261AIC学习总结

1. 中断源使能

对于每一个中断源,包括中断源0中的FIQ,可以通过命令寄存器AIC_IECR(中断使能命令寄存器)AIC_IDCR(中断禁用命令寄存器)被使能和禁止.

中断的屏蔽状态可以在AIC_IMR寄存器来读取。一个被禁用的中断不影响其它的中断服务。

上面这二段话的意思是:被AIC_IECRAIC_IDCR使能和禁止的中断,它们的状态可以在AIC_IMR寄存器中读取,而不是在AIC_ISR(中断状态寄存器)中读取。而读取AIC_ISR返回的是当前中断源的序号

2. 中断的置位与清零

所有编程为边沿触发的中断源(包括中断源0FIQ)都可以通过写AIC_ISCR(中断设置命令寄存器)AIC_ICCR(中断清除命令寄存器)相应的位来分别置位或清零。置位或清零对编程为电平有效模式中的中断源无影响(对于电平模式下的中断源的清除,可以在中断处理程序中读取AIC_IVR来执行,这样在整个IRQ中断的过程,就有可能二次读取AIC_IVR,第一次是把保存在AIC_SVR保存的地址装载到PC,第二次是在中断处理程序中,清除电平模式下的中断源)

AICAIC_IVR(中断向量寄存器)被读取时执行一个当前中断的自动清零操作。仅中断源被AIC检测到并作为当前中断时其才会被此操作影响。注意如果中断源的快速强制特性被使能,自动清零操作会被禁用,因为它会被认为是一个FIQ

外延:从上面的二段话中可以得出清中断源的操作:

当编程为边沿触发的中断源,可以通过AIC_ICCR来清除中断;但如果不是为边沿触发的中断源,也可以通过读取AIC_IVR来清除中断(在中断处理函数中读取)。但如果中断源的快速强制功能,则读取AIC_IVR的自动清除中断会被禁用。

所以在编程过程中,如果是边沿模式的中断源,在中断服务函数中读取AIC_IVR(装载AIC_SVR的地址到PC)可以清除中断源;如果是电平模式的中断源,在中断处理函数中读取AIC_IVR来清除中断。注:中断处理函数,就是用户编的需要中断需要执行的程序代码。

3. 中断的状态

对于AIC的每一个操作,取决于AIC_IPR(中断待定寄存器)AIC_IMR(中断屏蔽寄存器)。其中AIC_IPR的值反映的是中断源的实际活动情况,而无论其被使能或禁止。

读取AIC_ISR(中断状态寄存器)返回的中当前中断源号码。

4. 正常中断

a. 优先级控制

每个中断源有一个从70级的可编程优先级,并可通过写对应的AIC_SMR(中断源模式寄存器)中的PRIOR域由用户定义。其中第7级是最高级,第0级是最低级。

只要有一个中断条件产生,此条件是由AIC_SMR中的SRCTYPE域定义,nIRQ口线被激活。 当nIRQ被激活之后,一个新的中断条件可能在其它的中断源上产生,但当优先级控制器在读取IRQ_IVR之后决定当前的中断,也就是说先处理哪一个中断。AIC_IVF的读取是中断处理的入口点,此入口点使得AIC认为有软件来处理此中断。

如果同等优先级的若干中断源被使能且都处于中断状态。当AIC_IVR被读取时,具有最低中断源号码的的中断首先被服务。

仅仅当一个中断条件发生在一个更高的优先级的中断源时,nIRQ线才会被激活。当在中断处理期间一个中断条件发生,它将被延时到软件写AIC_EOICR寄存器(指示给AIC当前中断服务的结束)才会被处理。AIC_EOICR是中断处理函数的出口点。(注意:这是在没有中断嵌套的情况下,高优先级的中断源才不会被处理,直等到软件写AIC_EOICR来表示前一个中断处理完成)

b. 中断嵌套

优先级控制器利用中断嵌套使高优先级中断在低优先级中断服务期间被处理。这需要低优先级中断的中断服务例程在处理器级别重新使能中断。

外延:上段中有一个“在处理器级别重新使能中断”,应该这样理解:ARM的使能中断的地方有很多,第一个是内核级别的,在CPSR中有IF位,当IF位置位为0时,内核使能IRQFIQ中断,当IF置位为1时,内核禁止IRQFIQ中断。第二个是每一个ARM芯片中,都有一个先进的中断控制器,在中断控制器中禁止或使能中断,这是在处理器级别的操作。第三个是在具体的每一个外设中,也有中断禁止或使能命令,这是在外设级别的操作。所以本处的“处理器级别”使能中断,是要在先进的中断控制器中使能其它所有中断源的中断。

当在处理中断服务例程期间发生一个高优先级的中断,则nIRQ口线重新激活有效。如果中断在内核级别被使能,当前中断服务被中断并且新的中断服务例程读取AIC_IVR。此时,当前中断号和优先级被放入到一个嵌入式的硬件堆栈中。因此当高级优先级的中断服务被完成并且AIC_EOICR被写时他们被取回以完成被中断的处理。

AIC有一个8级深度的硬件堆栈以按照8个优先级来支持多达8级中断嵌套。

外延:从上面的几段中,可以得出如果要实现中断嵌套这个功能,首先要在中断服务函数中,在内核级别使能中断即在CPSR中的控制位IF置位为零,其它还要在处理器级别的AIC_IECR寄存器中使能相应的中断,缺一不可。如果只是在内核级别禁止了中断,而在处理器级别使能了中断,在中断处理服务期间不会产生中断嵌套,但新产生的中断会一直等到内核级别使能时,才会被服务。所以在编程的时候,要十分注意。

c. 向量化中断

每一个中断源的中断处理程序的地址可被存储到寄存器AIC_SVR1AIC_SVR31。当处理器读取AIC_IVR时,将返回当前中断写入到对应的AIC_SVR的值。

此功能提供了单条指令转移到中断处理程序的一个办法,因为AIC_IVR被映射在绝对地址处0xFFFF F100,因此可以把ARM中断向量地址0x0000 0018处放置下条指令:

LDR PC,[PC,# -&F20]   (0x18+0x18-0xF20 = 0xFFFF F100)

当处理器执行此条指令时,则读取AIC_IVR并装载在AIC_SVR中的值给PC,以此方式跳转到当前中断处理程序上执行。

d. 普通中断处理程序

下面将详细说明at91sam9261的中断处理过程:

首先,要正确的设置中断,把中断处理函数的地址写入AIC_SVR中,在AIC_IECR中使能对应的中断源,在内核级别也把I位清零,其次在外设级别也要使能中断。

其次,在ARM中断异常向量地址处0x18放置如下指令:   LDR PC[PC#-&F20]

nIRQ线被激活时,将按下面的顺序执行:

1). CPSR保存在SPSR_irq中;CPSR中的I被置位1PC的值被装载进入异常模式下的LRPC0x18值装载.

外延:at91sam9261中,这四个操作是ARM自动完成的,不知在其它处理器中也是自动完成的。

2).ARM内核进入中断模式

3) 当装载在地址0x18处的指令被执行,PC用被从AIC_IVR中读取的的值装载。

读取AIC_IVR会产生以下效果:首先,设置正在等待(AIC_IPR)并且优先级最高的中断源为当前中断;其次,在处理器级别重新激活nIRQ口线。如果中断向量并没有被使用,AIC_IVR也必须要读以激活nIRQ口线;第三,如果中断源编程为边沿触发方式,则中断自动清除;第四,把当前中断优先级(正在处理的优先级最高的优先级)和中断源号码(正在处理的优先级最高的中断源号码)压入堆栈中;第四,返回当前中断源写入寄存器AIC_SVR的值给PC

1)   前面第三步的结果,是转移到中断服务例程中,那么在中断服务例程中应该做什么呢?首先应该保存LR_irq(因为它是中断执行完后,程序的返回地址)SPSR_irq(因为它保存了程序在中断前的处理器的状态和模式)。此时还应转到中断前的处理器模式下,保存好工作状态寄存器R0~R12到中断前处理器模式下的堆栈中,也还应该保存SPSR_irq给中断前处理器模式下的堆栈并且把LR_irq的值赋给中断前处理器模式下的PC。如果LR_irq在中断结束前被直接加载进PC,那么LR_irq应该在被保存前减4(为什么要减4,这是因为ARM的流水线结构决定的)

2) 在保存了程序的中断入口点的寄存器之后,如果想要实现中断嵌套,这里可以清除CPSR的“I”位使能内核级别IRQ中断,如果当前有一个优先级比当前正在处理的中断的优先级高,中断嵌套就会产生。

3) 在执行中断处理函数(注意区别中断处理函数与上面一步讲的中断服务函数)之前,应该再把处理器模式从IRQ模式切换到程序运行的处理器模式下,如果中断源为电平方式,在此阶段必须清除中断源,如果想要进行中断嵌套,则应当在处理器模式下打开所有的中断(即操作寄存器AIC_IER),如果在中断处理函数过程中,有更高优先级的中断发生,则会发生中断嵌套,此时处理器将会跳转到第一步去执行。

4) 在执行完中断处理函数之后,在中断服务函数中,必须写中断结束命令寄存器(AIC_EOICR),以指示AIC当前中断已完成。这将导致当前级从堆栈弹出(AIC的硬件堆栈),如果栈前还有一个中断,那它将被恢复。如果还有一个中断正在等待,但它的优先级却比刚刚被恢复的中断的优先级要高,那么nIRQ口线将会重新激活,如果CPSR中的"I"位被置1,该新的最高优先级中断并不会马上被处理,但如果CPSR中的"I"位被清除,则新的高优先级中断会被马上处理,此时处理器将会跳转到第一步去执行。

5) 如果CPSR中的"I"位被置1,那么写AIC_EOICR并不会产生中断处理,此时在中断服务函数中应该恢复中断前程序的寄存器以回到程序中去执行。为了防止恢复中断前工作寄存器不会再被其它的中断再次中断,此时CPSR中的"I"位应置位,以确保中断正确地完成。

6) 外延:IRQ的整个中断处理过程,可以查看at91sam9261ucos-ii的中断移植函数,它完全是按照此过程来写的,我学得其中最要注意的地方是处理器模式之间的切换和CPSR中的"I"的置位与清零。

5.快速中断

a. 快速中断源

除非快强制被使用,中断源0是唯一可以引起一个快速中断请求到处理器中断源。中断源0一般连接于产品的一个FIQ引脚(直接相连或通过一个PIO控制器)

b. 快速中断控制(IRQ中断控制一样,可参看9261数据手册)

c. 快速中断向量化(IRQ中断控制一样,可参看9261数据手册)

d. 快速中断处理程序(比较简单,具体查看9261的数据手册)

e. 伪中断

伪中断定义为中断源激活了足够长的时间,使得AIC激活了nIRQ,但当AIC_IVR被读取时中断源却不存在。这在下列情况中容易发生:

外部中断源编程为电平敏感模式并且电平仅持续了一个较短的时间

内部中断源编程为电平敏感模式并且对就的嵌入式外设输出信号仅持续一个短的时间。

软件开始屏蔽中断前几个周期产生的中断,因此导致中断源上的一个脉冲。

当无使能的中断源等待,AICAIC_IVR被读取时检测到伪中断。当检测到伪中断,AIC返回到被编程者存储在AIC_SPU(伪向量寄存器)中的值。编程者必须把伪中断处理程序的地址存储在AIC_SPU中作为程序的一部分,使尽可能地返回到正常执行流程。此处理程序写入AIC_EOICR并执行一个中断返回。

外延:在编程的过程中,要注意伪中断的处理。最简单的办法是在伪中断处理程序中什么也不做。

20111113

QQ:717046727   欢迎交流         

你可能感兴趣的:(at91sam9261的AIC学习)