xilinx PowerPC 中断

来源:互联网 发布:mac os ei capitan 编辑:程序博客网 时间:2024/06/06 18:28


URL: http://hi.baidu.com/firstm25/item/b8343ef87a255810fe3582b6

    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)以适当的偏移量存放(注册)到异常向量表中,对应着相应的中断。

    读到这里会觉得有点乱吧,那么看一下下面的图。



    图1 PowerPC 中断流程

    从图中可以看出,异常向量表将异常/中断与其异常向量关联起来,异常/中断通过异常向量表找到自己的向量。通过异常向量在中断控制器中找到对应的处理程序,这样就与前面所说的总线中断控制器对应起来了。可见,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)
这是用宏定义的函数。用来禁止系统异常/中断功能。

    -----------------

    好像写的有点罗嗦,下面挑重点的总结几句。

    PowerPC中的硬件中断只有两个,critical和non-critical。为了扩展中断数量,xilinx引入了中断控制器的概念,即用软件来人为的区分中断并统一管理。但这种人为的区分已经随工程的生成而生成了,只需要调用其API函数即可。而实际的硬件中断还是两种,也是调用相应的API函数来完成,这个函数是BSD自动生成的函数。

    中断的顺序是这样的:中断源产生中断信号(任意中断源) -> 硬件中断响应并跳转到相应处理函数(或中断控制器函数 -> 中断控制器继续分析中断源并继续跳转到相应的处理函数) -> 中断处理完成后返回。

    这样,可以理解为,中断控制器是可有可无的,当中断源只有一个,那么就不需要中断控制器了。但中断源比较多,就需要中断控制器。

//---------------------------------------------------

    中断程序书写过程:

    Xexc_Init(); //初始化硬件中断

    XExc_RegisterHandler(); //在硬件中断中注册对应的处理函数(如果用到中断控制器,则需要注册“XIntc_DeviceInterruptHandler”为non_critical的硬件处理函数

    XIntc_RegisterHandler(); //在中断控制器中注册对应的处理函数(如果用到中断控制器)

    XIntc_mMasterEnalbe(); //使能中断控制器(如果用到中断控制器)

    //设置外设功能

    XIntc_mEnableIntr(); //在中断控制器中使能对应的外设中断(如果用到中断控制器)

    //在外设中使能外设中断,并启动外设

    XExc_mEnableExceptions(); //使能硬件中断(中断控制器用到的硬件中断是non-critical)

//---------------------------------------------------

    这样就完成了中断的初始化操作。当然,在这之前要先写好自己的中断处理函数。蓝色字体为使用中断控制器所必须的步骤。

参考文档:

《Embedded System Tools Reference Manual》

文件名est_rm.pdf,EDK安装目录doc文件夹下

《Using and Creating Interrupt-Based Systems》

文件名xapp778.pdf,下载地址 http://www.xilinx.com/support/documentation/application_notes/xapp778.pdf

全文完

0 0
原创粉丝点击