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
本文名稱:SylixOS中GIC通用中斷控制器(二)——GIC實現
網站鏈接:http://www.js-pz168.com/article38/iecgpp.html
成都網站建設公司_創新互聯,為您提供服務器托管、網站設計公司、響應式網站、App設計、網頁設計公司、外貿網站建設
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯