豚鼠系列1:xilinx PowerPC 中断1

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 16:18:55

PowerPC内核仅支持两个外部中断源,在处理多中断要求时需要引入“中断控制器(interrupt controller,INTC)”。这是EDK提供的中断处理机制,并提供了三种中断处理的驱动(drivers):OPB_INTC(挂在PLB或OPB总线上的外设)中断处理方式,DCR_INTC(直接连在处理器上的外设)中断处理方式,和PowerPC内核中断处理方式。前两种的驱动相同,仅改变地址名即可,前两种为按总线操作的中断控制器,后一种为PowerPC板级服务包(BSP)。

    中断控制器为系统中多个中断提供了优先级解码调度,这是一种软处理的中断方式,在有限的硬件中断基础上,依靠软件实现了扩展中断的方法。在很多处理器(如ARM、Nios等)中,对中断的软处理都有应用这种方法。原理基本相同,而各处理器又各有差异。本文介绍xilinx的硬核PowerPC的中断实现方法,对相应的函数做说明,对中断控制器的实现原理也做比较详细的介绍。    1、中断控制器INTC    EDK中提供的INTC有两种操作方法:Level“0”和Level“1”。其实现的结果是相同的,区别是操作的复杂度和对硬件的依赖(了解)程度不同。Level“1”中的函数基本都是以合理的方式调用Level“0”中的函数来实现的,也增加了自己的特殊结构,过程容易理解,不用了解更多的硬件知识。而Level“0”可以更灵活的按需使用中断。为了尽量了解INTC的工作方式,本文主要介绍Level“0”函数。Level“1”的信息可在Level“0”的基础上参考“xintc.c”文件(工程中定义好的软件环境下intc文件夹中)。    Level“0”函数包括:XIntc_DeviceInterruptHandler(xintc_l.c文件夹)
XIntc_mMasterEnable (宏)(xintc_l.h文件夹)
XIntc_mEnableIntr (宏)(xintc_l.h文件夹)
XIntc_SetIntrSvcOption(xintc_l.c文件夹)
XIntc_RegisterHandler(xintc_l.c文件夹)    void XIntc_DeviceInterruptHandler(void *DeviceId)
这个函数是主要的中断处理程序。它会判断哪个中断处于使能和激活的状态,并根据优先级调用相应的中断处理函数。可以将它理解为中断的调度机制,需要在内核异常/中断处理处被调用或注册(异常/中断在后面讲解)。    值得注意的是,在这个函数被调用之前,也就是说中断发生之前,中断向量表(interrupt vector table)已经被生成。这个函数原型在xintc_l.c文件中。    XIntc_mMasterEnable(BaseAddress)
这是个用宏定义出来的函数。用于使能所有在Master Enable寄存器中的中断。中断控制器在创建时默认每个外设的中断是禁止的。当然,有使能所有中断的函数也就有禁止所有中断的函数: XIntc_mMasterDisable(BaseAddress) 。这两个函数原型在xintc_l.h文件中。    XIntc_mEnableIntr(BaseAddress, EnableMask)
这是个用宏定义出来的函数。它通过Master Enable寄存器可以根据需要使能某个中断,而屏蔽其它中断。其对应的禁止某个中断的函数为XIntc_mMasterDisable(BaseAddress)。这两个函数的原型在xintc_l.h文件中。 
  
    void XIntc_SetIntrSvcOption(u32 BaseAddress, int Option)
这个函数用于设置中断服务方式,“Option”项设为 XIN_SVC_SGL_ISR_OPTION 时,仅响应一个中断。而设为 XIN_SVC_ALL_ISRS_OPTION 时,所有未被响应的终端均得到响应。在Level“1”中已经默认设为 XIN_SVC_SGL_ISR_OPTION,在Level“0”中可以自行设定。该函数原型在xintc_l.c文件中。    void XIntc_RegisterHandler(u32 BaseAddress, int InterruptId, XInterruptHandler Handler, void *CallBackRef)
这个函数很重要。通过它可以将某个中断(通过中断ID标识,interrupt ID)与其对应的服务函数相关联(即中断被注册)。INTC中的中断向量表(vector table)被更新,新中断服务覆盖原中断服务。    这个函数还可以去掉与当前的中断服务的关联。只需要将新服务指向(第二个参数)改为 XIntc_DefaultHandler(),第三个参数一般为 “(void*)0”。这个函数原型在xintc_l.c文件中。    这个函数的四个参数含义如下:
BaseAddress:中断控制器地址(xparameters.h文件中定义)。通过这个地址使中断向量表得到更新。
InterruptID:外设中断的ID(xparameters.h文件中定义)。用于与终端服务函数相关联。
Handler:终端服务函数的指针,与中断相关联,并跟新到中断向量表中。
CallBackRef:用户定义的可以传到中断服务函数中。一般为(void*)0。    2、PowerPC BSP    PowerPC为裸机(standalone)BSP提供了用于初始化、注册、使能和禁止异常/中断的一组函数。(注意这是为裸机提供的)这里提到了“异常”这个词,因为异常只能发生在处理器的内核中,在总线的中断处理中没有异常这个概念。异常是指处理器有意或无意的停止正常的运行,如意外重启、软件中断等。当发生异常/中断时,系统自动跳转到异常向量表(interrupt-handler table)中。这个列表的基地址存放在EVPR寄存器(Exception Vector Prefix Register)中,这个寄存器是16位宽,所以异常向量表必须定义在64kB的存储空间中。也就是说要使用这种驱动就必须提供在一个大于64kB的物理存储空间(当然可以利用FPGA内部的存储空间)。异常向量(exception vector或interrupt-handler)以适当的偏移量存放(注册)到异常向量表中,对应着相应的中断。   异常向量表将异常/中断与其异常向量关联起来,异常/中断通过异常向量表找到自己的向量。通过异常向量在中断控制器中找到对应的处理程序,这样就与前面所说的总线中断控制器对应起来了。可见,PowerPC BSP过程发生在INTC之前。通过INTC向量最终找到中断处理程序来执行。值的注意的是,中断的现场保护操作发生在这两个步骤之间。    下面介绍相关函数,以下函数在xexception.c和xexception.h文件中:    void XExc_Init(void)
为系统做异常/中断处理的初始化操作,为所有异常或中断统一建立一个异常向量表。异常向量表的基地址在此处被存放到EVPR寄存器中。    void XExc_RegisterHandler(Xuint8 ExceptionId, XExceptionHandler Handler, void *DataPtr)
这是关键函数,用来将异常/中断的ID与其处理程序函数关联起来。    注意:这个函数功能与前面讲的XIntc_RegisterHandler相同,但这两个函数是不可代替的,所处理的内容也不一样。这个函数中处理的异常/中断(参数ExceptionId)是处理器所固有的、最原始的中断源,包括复位、编程、Debug等我们不太关心的异常/中断,前面所说的总线中断处理器中的中断是这里的一部分。其参数ExceptionId在xexception.h文件中有全部定义。而前面所说的XIntc_RegisterHandler函数所处理的是挂在总线上的外设所发出的中断,是处理器固有中断源中的一部分。其参数InterruptID定义在xparameters.h文件中,需要用到中断处理器的地址,并更新中断向量表。    void XExc_RemoveHandler(Xuint8 ExceptionId)
这个函数用来取消指定中断与处理程序的对应关系,也就是说对此中断不做处理,直接返回到正在执行的代码处继续执行。    XExc_mEnableExceptions(EnableMask)
这是用宏定义的函数。用来使能系统异常/中断功能。    XExc_mDisableExceptions(DisableMask)
这是用宏定义的函数。用来禁止系统异常/中断功能。