SylixOS中GIC通用中断控制器(二)——GIC实现

1、概述

本篇文档主要介绍IMX6UL平台上基于SylixOS集成开发环境中GIC通用中断控制器的实现流程和方法。

2、GIC控制器基地址获取

GIC控制器基地址通过调用armPrivatePeriphBaseGet函数获得。如图 2.1所示,Ctrl+h局搜索armPrivatePeriphBaseGet函数,搜索结果如图 2.2所示。

图 2.1全局搜索armPrivatePeriphBaseGet函数

图 2.2 armPrivatePeriphBaseGet函数搜索结果

参考DDI0464F_cortex_a7_mpcore_r0p5_trm.pdf手册,该指令将协处理器 P15 的寄存器中的数据传送到 ARM处理器寄存器R0中,最终通过armPrivatePeriphBaseGet函数获取。如图 2.3和图 2.4所示。

图 2.3 CP15协处理器操作码

图 2.4 CP15读取基地址指令

:MRC指令的格式为:

MRC{条件}协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2。

MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,目的寄存器为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。

指令示例:

MRC P3, 3, R0, C4, C5, 6;该指令将协处理器 P3的寄存器中的数据传送到 ARM处理器寄存器中。

3、GIC控制器结构体说明

GIC控制器中分发器端寄存器结构体定义如图 3.1所示,CPU接口端结构体定义如图 3.2所示。

图 3.1分发器端寄存器结构体定义

图 3.2 CPU接口端结构体定义

4、GIC相关函数实现

4.1 GIC控制器初始化

4.1.1分发器初始化

对distributor结构体中成员进行操作,关闭所有pending中断并禁能所有中断,同时将所有中断设置为安全模式。具体实现如程序清单 4.1所示。

程序清单 4.1分发器初始化

VOID armGicInit (VOID)
{
    REGISTER     GIC_DISTRIBUTOR_REG *pDistributor = armGicIntDistributorGet();
    REGISTER INT iCnt;
 
    armGicEnable(LW_FALSE);                                       /* First disable the distributor */
 
    for (iCnt = 0; iCnt < GIC_INT_NUM; iCnt++) {                  /* Clear all pending interrupts  */
        write32(~0, (addr_t)&pDistributor->uiICPENDRn[iCnt]);
    }
 
    for (iCnt = 0; iCnt < GIC_INT_NUM; iCnt++) {                  /* Disable all interrupts.       */
        write32(~0, (addr_t)&pDistributor->uiICENABLERn[iCnt]);
    }
 
    for (iCnt = 0; iCnt < GIC_INT_GRP_NUM; iCnt++) {              /* Set all interrupts to secure  */
        write32(0, (addr_t)&pDistributor->uiIGROUPRn[iCnt]);
    }
 
    armGicEnable(LW_TRUE);                                        /* Now enable the distributor    */
}

4.1.2 CPU 接口初始化

对cpu interface端结构体成员进行操作,设置当前 CPU的优先级掩码255,禁止中断抢占,并使能当前 CPU到 GIC的接口。具体实现如程序清单 4.2所示。

程序清单 4.2 CPU接口初始化

VOID armGicCpuInit (BOOL  bPreemption, UINT32  uiPriority)
{
    REGISTER  GIC_CPU_INTERFACE_REGS *pInterface = armGicCpuInterfaceGet();
 
    armGicCpuPriorityMaskSet(uiPriority);                                  /* Init the GIC CPU interface */
 
    if (bPreemption) {
    /*
     * Enable preemption.
     */
    write32(GIC_CPU_INTERFACE_PREEM_EN, (addr_t)&pInterface->uiBPR);
    } else {
    /*
     * Disable preemption.
     */    
    write32(GIC_CPU_INTERFACE_PREEM_DISEN, (addr_t)&pInterface->uiBPR);
    }
 
    armGicCpuEnable(LW_TRUE);                                              /* Enable signaling the CPU */
}

4.2 中断向量基地址设置

如图 4.1和图 4.2所示,Ctrl+h全局搜索armVectorBaseAddrSet函数。

图 4.1全局搜索armVectorBaseAddrSet函数

图 4.2 armVectorBaseAddrSet函数搜索结果

参照DDI0464F_cortex_a7_mpcore_r0p5_trm.pdf手册,如图 4.3所示。

图 4.3中断向量基地址介绍

根据提示,再参照DDI0406C_C_arm_architecture_reference_manual.pdf手册如下图 4.4所示。

图 4.4中断向量基地址说明

可知该寄存器保存的是中断向量表基址参照bspMap.h文件,中断向量表物理地址即为BSP_CFG_RAM_BASE(0x80000000)。

4.3实现系统中断控制器

系统上电的过程中需要初始化中断处理器,否则后续使用到中断的程序都不能正常运行。

从startup.S中可以看到如图 4.5所示,系统只响应了irq中断,对fiq中断不做处理。

图 4.5 irq中断入口地址

关于中断需实现函数如图 4.6所示。

图 4.6函数列表

4.4中断服务程序

通过读取硬件寄存器,得到当前产生的中断向量号,调用系统接口archIntHandle进行处理,处理完成后,通知GIC中断已经处理完成。

4.4.1读取寄存器GICC_IAR获取中断号,如程序清单 4.3所示。

程序清单 4.3获取中断号

UINT32 armGicIrqReadAck (VOID)
{
    REGISTER GIC_CPU_INTERFACE_REGS *pInterface = armGicCpuInterfaceGet();
    return (read32((addr_t)&pInterface->uiIAR));
}

4.4.2向GICC_EOIR写入中断号,通知GIC该中断处理完成,如程序清单 4.4所示。

程序清单 4.4通知GIC该中断处理完成

VOID armGicIrqWriteDone (UINT32  uiIrqID)
{
    REGISTER GIC_CPU_INTERFACE_REGS *pInterface = armGicCpuInterfaceGet();
    write32(uiIrqID, (addr_t)&pInterface->uiEOIR);
}

4.5使能指定中断

通过设置硬件寄存器,使能指定的中断向量。具体实现如程序清单 4.5所示。

程序清单 4.5使能指定中断

VOID armGicIntVecterEnable (ULONG  ulVector, BOOL  bSecurity, ULONG  ulPriority, ULONG  uiCpuMask)
{
    armGicIrqEnable(ulVector, LW_FALSE);
    armGicIrqSecuritySet(ulVector, bSecurity);
    armGicIrqPrioritySet(ulVector, ulPriority);
    armGicIrqTargetSet(ulVector, GIC_CPU_MASK, LW_FALSE);
    armGicIrqTargetSet(ulVector, uiCpuMask, LW_TRUE);
    armGicIrqEnable(ulVector, LW_TRUE);
}

:由于imx6ul是单核处理器,理论上是不需要进行目标CPU选择的,但由于使用了GIC中断控制器,所以需给其目标寄存器组配置为0,即默认选择CPU0。

4.6禁能指定中断

通过设置硬件寄存器,禁能指定中断。具体实现如程序清单 4.6所示。

程序清单 4.6禁能指定中断

VOID armGicIntVecterDisable (ULONG  ulVector)
{
    armGicIrqEnable(ulVector, LW_FALSE);
    armGicIrqTargetSet(ulVector, GIC_CPU_MASK, LW_FALSE);
}

4.7判断中断是否使能

通过读取硬件寄存器,检查指定的中断向量是否使能。具体实现如程序清单 4.7所示。

程序清单 4.7判断指定中断向量是否使能

BOOL armGicIrqIsEnable (UINT32  uiIrqID)
{
    REGISTER GIC_DISTRIBUTOR_REG *pDistributor = armGicIntDistributorGet();
    REGISTER UINT32              uiReg         = armGicIntRegOffsGet(uiIrqID);
    REGISTER UINT32              uiMask        = armGicIntBitMaskGet(uiIrqID);
 
    return ((read32((addr_t)&pDistributor->uiICENABLERn[uiReg]) & uiMask) ? LW_TRUE : LW_FALSE);
}

4.8获取/设置中断优先级

该项由工程默认生成,未实现,如程序清单 4.8所示。

程序清单 4.8获取/设置中断优先级

ULONG bspIntVectorSetPriority (ULONG  ulVector, UINT  uiPrio)
{
    return (ERROR_NONE);
}
ULONG bspIntVectorGetPriority (ULONG  ulVector, UINT *puiPrio)
{
    *puiPrio = 0;
    return (ERROR_NONE);
}

4.9获取/设置中断目标CPU

由于imx6ul为单核处理器,虽然用到了GIC通用中断控制器,但默认给其选择CPU0。

在bsplib.c中具体实现如程序清单 4.9所示。

程序清单 4.9获取/设置中断目标CPU

ULONG bspIntVectorSetTarget (ULONG  ulVector, size_t  stSize, const PLW_CLASS_CPUSET  pcpuset)
{
    return (ERROR_NONE);
}
ULONG bspIntVectorGetTarget (ULONG  ulVector, size_t  stSize, PLW_CLASS_CPUSET  pcpuset)
{
    LW_CPU_ZERO(pcpuset);
    LW_CPU_SET(0, pcpuset);
 
    return (ERROR_NONE);
}

5、填充bsplib.c中断相关内容

将对应的函数功能添加到bspLib.c中,如程序清单 5.1所示。

程序清单 5.1 bspLib.c中断相关填充

/*********************************************************************************************************
中断相关
*********************************************************************************************************/
VOID bspIntInit (VOID)
{
    armGicInit();
    /*
     * 能够传递到当前 CPU 的中断的最低优先级(255 表示所有中断)
     */
    armGicCpuInit(LW_FALSE, 255);
    armVectorBaseAddrSet(BSP_CFG_RAM_BASE);
}
VOID bspIntHandle (VOID)
{
    REGISTER UINT32 uiAck       = armGicIrqReadAck();
    REGISTER UINT32 uiSourceCpu = (uiAck >> 10) & 0x7;
    REGISTER UINT32 uiVector    = uiAck & 0x1FF;
 
    (VOID)uiSourceCpu;
 
    archIntHandle((ULONG)uiVector, LW_FALSE);
 
    armGicIrqWriteDone(uiAck);
}
VOID bspIntVectorEnable (ULONG  ulVector)
{
    /*
     * 1 << 0 : 目标CPU为CPU0
     */
    armGicIntVecterEnable(ulVector, LW_FALSE, ARM_DEFAULT_INT_PRIORITY, 1 << 0);
}
VOID bspIntVectorDisable (ULONG  ulVector)
{
    armGicIntVecterDisable(ulVector);
}
BOOL bspIntVectorIsEnable (ULONG  ulVector)
{
    return (armGicIrqIsEnable(ulVector) ? LW_TRUE : LW_FALSE);
}
ULONG bspIntVectorSetPriority (ULONG  ulVector, UINT  uiPrio)
{
    return (ERROR_NONE);
}
ULONG bspIntVectorGetPriority (ULONG  ulVector, UINT *puiPrio)
{
    *puiPrio = 0;
    return (ERROR_NONE);
}
ULONG bspIntVectorSetTarget (ULONG  ulVector, size_t  stSize, const PLW_CLASS_CPUSET  pcpuset)
{
    return (ERROR_NONE);
}
ULONG bspIntVectorGetTarget (ULONG  ulVector, size_t  stSize, PLW_CLASS_CPUSET  pcpuset)
{
    LW_CPU_ZERO(pcpuset);
    LW_CPU_SET(0, pcpuset);
    return (ERROR_NONE);
}

至此,与中断控制器相关的内容填充完毕,之后在驱动中使用API_InterVectorConnect连接中断服务程序和中断号,使用API_InterVectorEnable使能中断等操作时就可以正常产生中断,并进入驱动对应的中断服务程序中了。

6、参考资料

文档类:

1. gic_architecture_specification.pdf

2. DDI0471B_gic400_r0p1_trm.pdf

3. IHI 0048B, ARM Generic Interrupt Controller Architecture Specification, Ver 2.0.pdf

网址链接:

1.http://www.wowotech.NET/linux_kenrel/gic_driver.html

2. http://blog.csdn.Net/velanjun/article/details/8757862

3. http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html

时间: 2024-08-03 21:36:12

SylixOS中GIC通用中断控制器(二)——GIC实现的相关文章

SylixOS中GIC通用中断控制器(一)——GIC简介

1. GIC简介 操作系统中,中断是很重要的组成部分.有了中断系统才可以不用一直轮询(polling)是否有事件发生,系统效率才得以提高.一般在系统中,中断控制分为三个部分:模块.中断控制器和处理器.其中模块通常由寄存器控制是否使能中断和中断触发条件等:中断控制器可以管理中断的优先级等,而处理器则由寄存器设置用来响应中断. 1.1 GIC结构 作为 ARM 系统中通用中断控制器的是 GIC(Generic Interrupt Controller),目前有四个版本,V1-V4(V2最多支持8个A

.Net Core中的通用主机(二)——托管服务

前文介绍了.Net core的通用主机的配置,在基础配置完成后,下一步就是注册我们的后台任务了..net core提供了一个通用的后台服务接口IHostedService,称为托管服务.一个注册托管服务的示例如下: hostBuilder.ConfigureServices((hostContext, services) =>{    services.AddHostedService<LifetimeEventsHostedService>();    services.AddHost

SylixOS Zynq平台私有中断绑定

1. 概述 本篇主要介绍在Zynq平台编写中断相关的驱动程序时,涉及CPU私有中断的相关绑定办法. 2. 私有中断简介 私有中断是多核CPU上特有的中断,私有中断只能被其所有者核心获取和响应,不会被其他核发现.常见的私有中断有全局定时器,私有看门狗定时器,私有定时器等,Zynq平台上还有来自PL的FIQ\IRQ. 3. 私有中断的绑定方法 3.1      常规共享中断绑定 Zynq平台使用的是GIC通用中断框架,常规的共享中断绑定和普通的中断绑定没有区别,在SylixOS上直接调用API_In

五、中断控制器

5.1 中断体系 ARM 体系的CPU 有 7 种工作模式 用户模式(usr):ARM 处理器正常的程序执行状态 快速中断模式(fiq):用于高速数据传输或通道处理 中断模式(irq):用户通用的中断处理 管理模式(svc):操作系统使用的保护模式 数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护 系统模式(sys):运行具有特权的操作系统任务 未定义指令中止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真 可通过软件来进行模

OR1200处理器的可编程中断控制器PIC分析

以下内容摘自<步步惊芯--软核处理器内部设计分析>一书 16.3可编程中断控制器PIC分析 16.3.1 PIC介绍 可编程中断控制器Programmable Interrupt Controller(PIC)用来响应各种中断事件,如:键盘事件.串口数据到达等,PIC收集所有的中断,并通知CPU中断到达,后者转入到中断处理例程进行处理.OR1200最多支持32个中断.其功能实现主要依靠两个特殊寄存器:中断屏蔽寄存器PICMR.中断状态寄存器PICSR.通过PICMR可以设置是否屏蔽某些中断,通

中断中需要面对的问题(二)

中断中有些问题需要面对. 隔离变化 不知道您有没有意识到,中断处理前面这部分的设计是何等的简单优美.人是高度智能化的,能够对遇到的各种意外情况做有针对性的处理,计算机相比就差距甚远了,它只能根据预定的程序进行操作.对于计算机来说,硬件支持的,只能是中断这种电信号传播的方式和CPU对这种信号的接收方法,而具体如何处理这个中断,必须得靠操作系统实现.操作系统支持所有事先能够预料到的中断信号,理论上都不存在太大的挑战,但在操作系统安装到计算机设备上以后,肯定会时常有新的外围设备被加入系统,这可能会带来

关于ck中断控制器

一.中断控制器 中断控制器模块包括 其使能寄存器,状态寄存器等. 中断使能寄存器为32bit,每一个bit 对应一个中断源,具体对应到硬件上线的连接 二.cpu怎样调用到中断 (1). 前置工作 首先是cpu关于start.S汇编文件中关于中断控制器的几个要求 : 1. 定义中断处理函数要在对应的位置 我的工程中放在text段后128字节,后面每一个函数对应一个中断源 2. psr状态寄存器的配置 IC-中断控制位: 当 IC 为 0 时,中断只能在指令之间被响应;当 IC 为 1 时,表明中断

STM32 USB转串口驱动移植到SylixOS中遇到的问题总结

1. 简介         由于客户项目需求,需要在STM32的硬件平台上实现USB转串口的功能,由于ST公司基于STM32硬件平台实现了相应的USB库以方便开发者进行开发,因此,在SylixOS下实现USB转串口功能时对该USB库进行了移植.由于该USB库的实现是基于STM32的裸机代码实现,因此在移植的过程中,不需要做过多的修改.         下面章节主要介绍在移植STM32的USB转串口驱动到SylixOS下遇到的问题以及对应的解决方法.对于其中的有些解决方法在移植STM32其他外设驱

LCD实验学习笔记(八):中断控制器

s3c2440有60个中断源(其中15个为子中断源). 程序状态寄存器(PSR)的F位设为1,禁用快速中断(FRQ). 程序状态寄存器(PSR)的I位设为1,禁用普通中断(IRQ). 相反,PSR寄存器F位为0开FRQ中断,I位为0开IRQ中断. s3c2440中断控制器中有五个控制寄存器:中断源等待寄存器(SRCPND),中断模式寄存器(INTMOD),屏蔽寄存器(INTMSK),优先级寄存器(PRIORITY),中断等待寄存器(INTPND). SRCPND寄存器各位对应不同的中断,其中外部