本篇主要介绍在Zynq平台编写中断相关的驱动程序时,涉及CPU私有中断的相关绑定办法。
全州网站制作公司哪家好,找成都创新互联!从网页设计、网站建设、微信开发、APP开发、响应式网站开发等网站项目制作,到程序开发,运营维护。成都创新互联2013年至今到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联。
私有中断是多核CPU上特有的中断,私有中断只能被其所有者核心获取和响应,不会被其他核发现。常见的私有中断有全局定时器,私有看门狗定时器,私有定时器等,Zynq平台上还有来自PL的FIQ\IRQ。
Zynq平台使用的是GIC通用中断框架,常规的共享中断绑定和普通的中断绑定没有区别,在SylixOS上直接调用API_InterVectorConnect、API_InterVectorEnable这两个函数即可绑定,绑定后中断可由任意一个CPU核心响应。
私有中断只能有所有者核心获取和响应,因此对应的中断和中断服务是绑定在相关的CPU核心上。在SylixOS下绑定私有中断需要让常规共享中断的绑定流程在对应CPU核心上完成才能成功绑定。即在驱动绑定私有中断的时候创建一个绑定在对应CPU核心上的绑定线程,然后由这个绑定线程去完成私有中断绑定。绑定流程如图 3.1示。
图 3.1私有中断绑定流程
Zynq平台31号私有定时器中断绑定框架如程序清单 3.1所示。
程序清单 3.1 Zynq平台31号私有定时器中断绑定框架
#define ZYNQ_VECTOR_NIRQ 31 /* 31号私有中断 */ static LW_HANDLE _G_bindthread = LW_OBJECT_HANDLE_INVALID; static LW_HANDLE _G_syncSignal = LW_OBJECT_HANDLE_INVALID; /*************************************************************************** ** 函数名称: __nIrqIsr ** 功能描述: 中断服务程序 ** 输 入 : pvArg ** 输 出 : NONE ** 返 回 : LW_NULL ***************************************************************************/ static irqreturn_t __nIrqIsr (PVOID pvArg) { return LW_IRQ_HANDLED; } /*************************************************************************** ** 函数名称: __bindThread ** 功能描述: 私有中断绑定线程 ** 输 入 : pvArg ** 输 出 : NONE ** 返 回 : LW_NULL ***************************************************************************/ static PVOID __bindThread (PVOID pvArg) { API_SemaphoreBPend(_G_syncSignal, LW_OPTION_WAIT_INFINITE); /* 等待同步信号量 */ API_InterVectorConnect(ZYNQ_VECTOR_NIRQ, /* 连接中断服务程序 */ (PINT_SVR_ROUTINE)__nIrqIsr, (PVOID)NULL, "nIrq"); API_InterVectorEnable(ZYNQ_VECTOR_NIRQ); /* 使能中断 */ } /*************************************************************************** ** 函数名称: __nIrqInit ** 功能描述: 中断服务初始化 ** 输 入 : NONE ** 输 出 : NONE ** 返 回 : 成功返回ERROR_NONE,失败返回PX_ERROR ***************************************************************************/ INT __nIrqInit (VOID) { LW_CLASS_CPUSET cpuset; _G_syncSignal = API_SemaphoreBCreate("SYNCSEM", /* 创建同步等待信号 */ 0, LW_OPTION_OBJECT_GLOBAL, LW_NULL); if (_G_syncSignal == LW_OBJECT_HANDLE_INVALID) { /*判断信号量创建是否成功*/ printk ("BIND signal init failed !\r\n"); return PX_ERROR; } /* * 设置线程CPU绑定属性 */ LW_CPU_ZERO(&cpuset); LW_CPU_SET(0, &cpuset); _G_bindthread = API_ThreadCreate("bindThread", /* 创建绑定线程 */ __bindThread, LW_NULL, LW_NULL); if (_G_bindthread == LW_OBJECT_HANDLE_INVALID) { /*判断绑定线程是否创建成功*/ printk ("BIND thread init failed !\r\n"); return PX_ERROR; } API_ThreadSetAffinity(_G_bindthread, /* 将绑定线程设置到CPU0上*/ sizeof(cpuset), &cpuset); API_SemaphoreBPost(_G_syncSignal); /* 发送信号启动绑定线程 */ }