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分发器初始化
VOIDarmGicInit(VOID){REGISTERGIC_DISTRIBUTOR_REG*pDistributor=armGicIntDistributorGet();REGISTERINTiCnt;armGicEnable(LW_FALSE);/*Firstdisablethedistributor*/for(iCnt=0;iCnt<GIC_INT_NUM;iCnt++){/*Clearallpendinginterrupts*/write32(~0,(addr_t)&pDistributor->uiICPENDRn[iCnt]);}for(iCnt=0;iCnt<GIC_INT_NUM;iCnt++){/*Disableallinterrupts.*/write32(~0,(addr_t)&pDistributor->uiICENABLERn[iCnt]);}for(iCnt=0;iCnt<GIC_INT_GRP_NUM;iCnt++){/*Setallinterruptstosecure*/write32(0,(addr_t)&pDistributor->uiIGROUPRn[iCnt]);}armGicEnable(LW_TRUE);/*Nowenablethedistributor*/}
4.1.2 CPU 接口初始化
对cpu interface端结构体成员进行操作,设置当前 CPU的优先级掩码255,禁止中断抢占,并使能当前 CPU到 GIC的接口。具体实现如程序清单 4.2所示。
程序清单 4.2 CPU接口初始化
VOIDarmGicCpuInit(BOOLbPreemption,UINT32uiPriority){REGISTERGIC_CPU_INTERFACE_REGS*pInterface=armGicCpuInterfaceGet();armGicCpuPriorityMaskSet(uiPriority);/*InittheGICCPUinterface*/if(bPreemption){/**Enablepreemption.*/write32(GIC_CPU_INTERFACE_PREEM_EN,(addr_t)&pInterface->uiBPR);}else{/**Disablepreemption.*/write32(GIC_CPU_INTERFACE_PREEM_DISEN,(addr_t)&pInterface->uiBPR);}armGicCpuEnable(LW_TRUE);/*EnablesignalingtheCPU*/}
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获取中断号
UINT32armGicIrqReadAck(VOID){REGISTERGIC_CPU_INTERFACE_REGS*pInterface=armGicCpuInterfaceGet();return(read32((addr_t)&pInterface->uiIAR));}
4.4.2向GICC_EOIR写入中断号,通知GIC该中断处理完成,如程序清单 4.4所示。
程序清单 4.4通知GIC该中断处理完成
VOIDarmGicIrqWriteDone(UINT32uiIrqID){REGISTERGIC_CPU_INTERFACE_REGS*pInterface=armGicCpuInterfaceGet();write32(uiIrqID,(addr_t)&pInterface->uiEOIR);}
4.5使能指定中断
通过设置硬件寄存器,使能指定的中断向量。具体实现如程序清单 4.5所示。
程序清单 4.5使能指定中断
VOIDarmGicIntVecterEnable(ULONGulVector,BOOLbSecurity,ULONGulPriority,ULONGuiCpuMask){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禁能指定中断
VOIDarmGicIntVecterDisable(ULONGulVector){armGicIrqEnable(ulVector,LW_FALSE);armGicIrqTargetSet(ulVector,GIC_CPU_MASK,LW_FALSE);}
4.7判断中断是否使能
通过读取硬件寄存器,检查指定的中断向量是否使能。具体实现如程序清单 4.7所示。
程序清单 4.7判断指定中断向量是否使能
BOOLarmGicIrqIsEnable(UINT32uiIrqID){REGISTERGIC_DISTRIBUTOR_REG*pDistributor=armGicIntDistributorGet();REGISTERUINT32uiReg=armGicIntRegOffsGet(uiIrqID);REGISTERUINT32uiMask=armGicIntBitMaskGet(uiIrqID);return((read32((addr_t)&pDistributor->uiICENABLERn[uiReg])&uiMask)?LW_TRUE:LW_FALSE);}
4.8获取/设置中断优先级
该项由工程默认生成,未实现,如程序清单 4.8所示。
程序清单 4.8获取/设置中断优先级
ULONGbspIntVectorSetPriority(ULONGulVector,UINTuiPrio){return(ERROR_NONE);}ULONGbspIntVectorGetPriority(ULONGulVector,UINT*puiPrio){*puiPrio=0;return(ERROR_NONE);}
4.9获取/设置中断目标CPU
由于imx6ul为单核处理器,虽然用到了GIC通用中断控制器,但默认给其选择CPU0。
在bsplib.c中具体实现如程序清单 4.9所示。
程序清单 4.9获取/设置中断目标CPU
ULONGbspIntVectorSetTarget(ULONGulVector,size_tstSize,constPLW_CLASS_CPUSETpcpuset){return(ERROR_NONE);}ULONGbspIntVectorGetTarget(ULONGulVector,size_tstSize,PLW_CLASS_CPUSETpcpuset){LW_CPU_ZERO(pcpuset);LW_CPU_SET(0,pcpuset);return(ERROR_NONE);}
5、填充bsplib.c中断相关内容
将对应的函数功能添加到bspLib.c中,如程序清单 5.1所示。
程序清单 5.1 bspLib.c中断相关填充
/*********************************************************************************************************中断相关*********************************************************************************************************/VOIDbspIntInit(VOID){armGicInit();/**能够传递到当前CPU的中断的最低优先级(255表示所有中断)*/armGicCpuInit(LW_FALSE,255);armVectorBaseAddrSet(BSP_CFG_RAM_BASE);}
VOIDbspIntHandle(VOID){REGISTERUINT32uiAck=armGicIrqReadAck();REGISTERUINT32uiSourceCpu=(uiAck>>10)&0x7;REGISTERUINT32uiVector=uiAck&0x1FF;(VOID)uiSourceCpu;archIntHandle((ULONG)uiVector,LW_FALSE);armGicIrqWriteDone(uiAck);}
VOIDbspIntVectorEnable(ULONGulVector){/**1<<0:目标CPU为CPU0*/armGicIntVecterEnable(ulVector,LW_FALSE,ARM_DEFAULT_INT_PRIORITY,1<<0);}
VOIDbspIntVectorDisable(ULONGulVector){armGicIntVecterDisable(ulVector);}
BOOLbspIntVectorIsEnable(ULONGulVector){return(armGicIrqIsEnable(ulVector)?LW_TRUE:LW_FALSE);}
ULONGbspIntVectorSetPriority(ULONGulVector,UINTuiPrio){return(ERROR_NONE);}
ULONGbspIntVectorGetPriority(ULONGulVector,UINT*puiPrio){*puiPrio=0;return(ERROR_NONE);}
ULONGbspIntVectorSetTarget(ULONGulVector,size_tstSize,constPLW_CLASS_CPUSETpcpuset){return(ERROR_NONE);}
ULONGbspIntVectorGetTarget(ULONGulVector,size_tstSize,PLW_CLASS_CPUSETpcpuset){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
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。