1. 概述
本篇主要介紹在Zynq平臺編寫中斷相關的驅動程序時,涉及CPU私有中斷的相關綁定辦法。
2. 私有中斷簡介
私有中斷是多核CPU上特有的中斷,私有中斷只能被其所有者核心獲取和響應,不會被其他核發現。常見的私有中斷有全局定時器,私有看門狗定時器,私有定時器等,Zynq平臺上還有來自PL的FIQ\IRQ。
3. 私有中斷的綁定方法
3.1 常規共享中斷綁定
Zynq平臺使用的是GIC通用中斷框架,常規的共享中斷綁定和普通的中斷綁定沒有區別,在SylixOS上直接調用API_InterVectorConnect、API_InterVectorEnable這兩個函數即可綁定,綁定後中斷可由任意一個CPU核心響應。
3.2 私有中斷綁定
私有中斷只能有所有者核心獲取和響應,因此對應的中斷和中斷服務是綁定在相關的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); /* 發送信號啓動綁定線程 */ }