標籤:
1. OVERVIEW OF VECTORED INTERRUPT CONTROLLER(概述向量中斷控制器)
主要有4個VIC,4個TZIC還有一個很特殊的ARM PrimeCell PL192。主要的VIC和TZIC可以支援93個中斷源。其中TZIC是為TrustZone技術所準備的,ARM TrustZone® 技術是系統範圍的安全方法,針對高效能運算平台上的大量應用,包括安全支付、數位版權管理 (DRM)、企業服務和基於 Web 的服務(援引官方的介紹)。TZIC提供了安全控制的nFIQ中斷並且使該這類中斷從傳統的不安全中斷VIC中屏蔽掉,從而達到應用在資料轉送時的安全性和保密性。
2,KEY FEATURES OF VECTORED INTERRUPT CONTROLLER
• Supports 93 vectored IRQ interrupts
• Fixed hardware interrupts priority levels (固定硬體中斷優先順序)
• Programmable interrupt priority levels (可程式化中斷優先順序)
• Supports Hardware interrupt priority level masking (支援硬體中斷優先順序的屏蔽)
• Programmable interrupt priority level masking
• Generates IRQ and FIQ (產生IRQ和FIQ)
• Generates Software interrupt
• Test registers
• Raw interrupt status (原中斷狀態,就是設定使能,屏蔽寄存器之前的各中斷狀態)
• Interrupt request status
• Supports Privileged mode for restricted access(支援限制存取權限模式)
3. When user clears interrupt pending, user must write 0 to all the VICADDRESS registers (VIC0ADDRESS,
VIC1ADDRESS, VIC2ADDRESS, and VIC3ADDRESS).
4.各中斷寄存器請參考s5pv320使用者手冊。
中斷參考程式:
.global _start.global IRQ_handle_start:// 關閉看門狗ldrr0, =0xE2700000movr1, #0strr1, [r0]// 設定棧,以便調用c函數ldrsp, =0x40000000// 開中斷mov r0, #0x53msr CPSR_cxsf, r0// 彙編初始化時鐘bl clock_init// 調用main函數bl mainIRQ_handle:// 設定中斷模式的棧ldr sp, =0xD0037F80// 儲存現場sub lr, lr, #4stmfd sp!, {r0-r12, lr}// 跳轉到中斷處理函數blirq_handler// 恢複現場ldmfd sp!, {r0-r12, pc}^
首先,關閉看門狗,設定棧,開中斷,設定時鐘,,,當一個中斷源(不是一個中斷)發生時執行中斷服務程式IRQ_handle,設定中斷模式的棧, 儲存現場,跳轉到中斷處理函(irq_handler),中斷處理函數首先判斷是哪個中斷組發生中斷,然後進入相應的中斷處理子程式(irq_xxx),在事先我們要設定中斷處理子程式irq_xxx(如irq_key)在地址VICxVECTADDRx中,,,當有中斷髮生時,硬體上會將當前中斷的中斷處理子程式從寄存器 VICxVECTADDxR 自動拷貝到寄存器VICADDR 中,所以我們在 irq_handler()函數裡會調用儲存在寄存器 VICDDR 裡的中斷處理函數即可。
( 一個中斷組有32個中斷源,為什麼我們可以直接運行中斷組的VICxINTADDR指定的函數而無需知道是具體哪個中斷源觸發了中斷呢?這是由於中斷組內的中斷源在觸發中斷後硬體會自動把對應中斷源的處理函數入口地址賦給所屬組的VICADDR,這樣我們就能省去檢索中斷源再跳轉到對應中斷函數入口的時間了,當然,前提是我們要把【按鍵中斷】的服務程式入口地址賦給某個對應的寄存器(假設是VIC0INTADDR12,所屬組是VIC0組,所對應入口是VIC0INTADDR))。
這一段真的有點難懂,需要花點時間
#include "stdio.h"#include "int.h"#define GPH2CON (*(volatile unsigned long *) 0xE0200C40)#define GPH2DAT(*(volatile unsigned long *) 0xE0200C44)#define GPH2_0_EINT16 (0xf<<(0*4))#define GPH2_1_EINT17 (0xf<<(1*4))#define GPH2_2_EINT18 (0xf<<(2*4))#define GPH2_3_EINT19 (0xf<<(3*4))#defineEXT_INT_0_CON ( *((volatile unsigned long *)0xE0200E00) )#defineEXT_INT_1_CON ( *((volatile unsigned long *)0xE0200E04) )#defineEXT_INT_2_CON ( *((volatile unsigned long *)0xE0200E08) )#defineEXT_INT_3_CON ( *((volatile unsigned long *)0xE0200E0C) )#defineEXT_INT_0_MASK ( *((volatile unsigned long *)0xE0200F00) )#defineEXT_INT_1_MASK ( *((volatile unsigned long *)0xE0200F04) )#defineEXT_INT_2_MASK ( *((volatile unsigned long *)0xE0200F08) )#defineEXT_INT_3_MASK ( *((volatile unsigned long *)0xE0200F0C) )#defineEXT_INT_0_PEND ( *((volatile unsigned long *)0xE0200F40) )#defineEXT_INT_1_PEND ( *((volatile unsigned long *)0xE0200F44) )#defineEXT_INT_2_PEND ( *((volatile unsigned long *)0xE0200F48) )#defineEXT_INT_3_PEND ( *((volatile unsigned long *)0xE0200F4C) )void uart_init();// 延時函數void delay(unsigned long count){volatile unsigned long i = count;while (i--);}void isr_key(void){printf("we get company:EINT16_31\r\n");// clear VIC0ADDRintc_clearvectaddr();// clear pending bitEXT_INT_2_PEND |= 1<<0;}int main(void){int c = 0;// 初始化串口uart_init();// 中斷相關初始化system_initexception();printf("**************Int test *************** \r\n");// 外部中斷相關的設定// 1111 = EXT_INT[16] GPH2CON |= 0xF;// 010 = Falling edge triggeredEXT_INT_2_CON |= 1<<1;// unmaskedEXT_INT_2_MASK &= ~(1<<0);// 設定中斷EINT16_31的處理函數intc_setvectaddr(NUM_EINT16_31, isr_key);// 使能中斷EINT16_31intc_enable(NUM_EINT16_31);while (1){ printf("%d\r\n",c++);delay(0x100000);}}
#include "int.h"#include "stdio.h"//// Interrupt#define VIC0_BASE(0xF2000000)#define VIC1_BASE(0xF2100000)#define VIC2_BASE(0xF2200000)#define VIC3_BASE(0xF2300000)// VIC0#defineVIC0IRQSTATUS( *((volatile unsigned long *)(VIC0_BASE + 0x00)) )#defineVIC0FIQSTATUS( *((volatile unsigned long *)(VIC0_BASE + 0x04)) )#defineVIC0RAWINTR( *((volatile unsigned long *)(VIC0_BASE + 0x08)) )#defineVIC0INTSELECT( *((volatile unsigned long *)(VIC0_BASE + 0x0c)) )#defineVIC0INTENABLE( *((volatile unsigned long *)(VIC0_BASE + 0x10)) )#defineVIC0INTENCLEAR( *((volatile unsigned long *)(VIC0_BASE + 0x14)) )#defineVIC0SOFTINT( *((volatile unsigned long *)(VIC0_BASE + 0x18)) )#defineVIC0SOFTINTCLEAR( *((volatile unsigned long *)(VIC0_BASE + 0x1c)) )#defineVIC0PROTECTION( *((volatile unsigned long *)(VIC0_BASE + 0x20)) )#defineVIC0SWPRIORITYMASK( *((volatile unsigned long *)(VIC0_BASE + 0x24)) )#defineVIC0PRIORITYDAISY( *((volatile unsigned long *)(VIC0_BASE + 0x28)) )#define VIC0VECTADDR(VIC0_BASE + 0x100)#define VIC0VECPRIORITY( *((volatile unsigned long *)(VIC0_BASE + 0x200)) )#define VIC0ADDR( *((volatile unsigned long *)(VIC0_BASE + 0xf00)) )#define VIC0PERID0( *((volatile unsigned long *)(VIC0_BASE + 0xfe0)) )#define VIC0PERID1( *((volatile unsigned long *)(VIC0_BASE + 0xfe4)) )#define VIC0PERID2( *((volatile unsigned long *)(VIC0_BASE + 0xfe8)) )#define VIC0PERID3( *((volatile unsigned long *)(VIC0_BASE + 0xfec)) )#define VIC0PCELLID0( *((volatile unsigned long *)(VIC0_BASE + 0xff0)) )#define VIC0PCELLID1( *((volatile unsigned long *)(VIC0_BASE + 0xff4)) )#define VIC0PCELLID2( *((volatile unsigned long *)(VIC0_BASE + 0xff8)) )#define VIC0PCELLID3( *((volatile unsigned long *)(VIC0_BASE + 0xffc)) )// VIC1#defineVIC1IRQSTATUS( *((volatile unsigned long *)(VIC1_BASE + 0x00)) )#defineVIC1FIQSTATUS( *((volatile unsigned long *)(VIC1_BASE + 0x04)) )#defineVIC1RAWINTR( *((volatile unsigned long *)(VIC1_BASE + 0x08)) )#defineVIC1INTSELECT( *((volatile unsigned long *)(VIC1_BASE + 0x0c)) )#defineVIC1INTENABLE( *((volatile unsigned long *)(VIC1_BASE + 0x10)) )#defineVIC1INTENCLEAR( *((volatile unsigned long *)(VIC1_BASE + 0x14)) )#defineVIC1SOFTINT( *((volatile unsigned long *)(VIC1_BASE + 0x18)) )#defineVIC1SOFTINTCLEAR( *((volatile unsigned long *)(VIC1_BASE + 0x1c)) )#defineVIC1PROTECTION( *((volatile unsigned long *)(VIC1_BASE + 0x20)) )#defineVIC1SWPRIORITYMASK( *((volatile unsigned long *)(VIC1_BASE + 0x24)) )#defineVIC1PRIORITYDAISY( *((volatile unsigned long *)(VIC1_BASE + 0x28)) )#define VIC1VECTADDR(VIC1_BASE + 0x100)#define VIC1VECPRIORITY( *((volatile unsigned long *)(VIC1_BASE + 0x200)) )#define VIC1ADDR( *((volatile unsigned long *)(VIC1_BASE + 0xf00)) )#define VIC1PERID0( *((volatile unsigned long *)(VIC1_BASE + 0xfe0)) )#define VIC1PERID1( *((volatile unsigned long *)(VIC1_BASE + 0xfe4)) )#define VIC1PERID2( *((volatile unsigned long *)(VIC1_BASE + 0xfe8)) )#define VIC1PERID3( *((volatile unsigned long *)(VIC1_BASE + 0xfec)) )#define VIC1PCELLID0( *((volatile unsigned long *)(VIC1_BASE + 0xff0)) )#define VIC1PCELLID1( *((volatile unsigned long *)(VIC1_BASE + 0xff4)) )#define VIC1PCELLID2( *((volatile unsigned long *)(VIC1_BASE + 0xff8)) )#define VIC1PCELLID3( *((volatile unsigned long *)(VIC1_BASE + 0xffc)) )// VIC2#defineVIC2IRQSTATUS( *((volatile unsigned long *)(VIC2_BASE + 0x00)) )#defineVIC2FIQSTATUS( *((volatile unsigned long *)(VIC2_BASE + 0x04)) )#defineVIC2RAWINTR( *((volatile unsigned long *)(VIC2_BASE + 0x08)) )#defineVIC2INTSELECT( *((volatile unsigned long *)(VIC2_BASE + 0x0c)) )#defineVIC2INTENABLE( *((volatile unsigned long *)(VIC2_BASE + 0x10)) )#defineVIC2INTENCLEAR( *((volatile unsigned long *)(VIC2_BASE + 0x14)) )#defineVIC2SOFTINT( *((volatile unsigned long *)(VIC2_BASE + 0x18)) )#defineVIC2SOFTINTCLEAR( *((volatile unsigned long *)(VIC2_BASE + 0x1c)) )#defineVIC2PROTECTION( *((volatile unsigned long *)(VIC2_BASE + 0x20)) )#defineVIC2SWPRIORITYMASK( *((volatile unsigned long *)(VIC2_BASE + 0x24)) )#defineVIC2PRIORITYDAISY( *((volatile unsigned long *)(VIC2_BASE + 0x28)) )#define VIC2VECTADDR(VIC2_BASE + 0x100)#define VIC2VECPRIORITY( *((volatile unsigned long *)(VIC2_BASE + 0x200)) )#define VIC2ADDR( *((volatile unsigned long *)(VIC2_BASE + 0xf00)) )#define VIC2PERID0( *((volatile unsigned long *)(VIC2_BASE + 0xfe0)) )#define VIC2PERID1( *((volatile unsigned long *)(VIC2_BASE + 0xfe4)) )#define VIC2PERID2( *((volatile unsigned long *)(VIC2_BASE + 0xfe8)) )#define VIC2PERID3( *((volatile unsigned long *)(VIC2_BASE + 0xfec)) )#define VIC2PCELLID0( *((volatile unsigned long *)(VIC2_BASE + 0xff0)) )#define VIC2PCELLID1( *((volatile unsigned long *)(VIC2_BASE + 0xff4)) )#define VIC2PCELLID2( *((volatile unsigned long *)(VIC2_BASE + 0xff8)) )#define VIC2PCELLID3( *((volatile unsigned long *)(VIC2_BASE + 0xffc)) )// VIC3#defineVIC3IRQSTATUS( *((volatile unsigned long *)(VIC3_BASE + 0x00)) )#define VIC3FIQSTATUS( *((volatile unsigned long *)(VIC3_BASE + 0x04)) )#define VIC3RAWINTR( *((volatile unsigned long *)(VIC3_BASE + 0x08)) )#define VIC3INTSELECT( *((volatile unsigned long *)(VIC3_BASE + 0x0c)) )#define VIC3INTENABLE( *((volatile unsigned long *)(VIC3_BASE + 0x10)) )#define VIC3INTENCLEAR( *((volatile unsigned long *)(VIC3_BASE + 0x14)) )#define VIC3SOFTINT( *((volatile unsigned long *)(VIC3_BASE + 0x18)) )#define VIC3SOFTINTCLEAR( *((volatile unsigned long *)(VIC3_BASE + 0x1c)) )#define VIC3PROTECTION( *((volatile unsigned long *)(VIC3_BASE + 0x20)) )#define VIC3SWPRIORITYMASK( *((volatile unsigned long *)(VIC3_BASE + 0x24)) )#define VIC3PRIORITYDAISY( *((volatile unsigned long *)(VIC3_BASE + 0x28)) )#define VIC3VECTADDR(VIC3_BASE + 0x100)#define VIC3VECPRIORITY( *((volatile unsigned long *)(VIC3_BASE + 0x200)) )#define VIC3ADDR( *((volatile unsigned long *)(VIC3_BASE + 0xf00)) )#define VIC3PERID0( *((volatile unsigned long *)(VIC3_BASE + 0xfe0)) )#define VIC3PERID1( *((volatile unsigned long *)(VIC3_BASE + 0xfe4)) )#define VIC3PERID2( *((volatile unsigned long *)(VIC3_BASE + 0xfe8)) )#define VIC3PERID3( *((volatile unsigned long *)(VIC3_BASE + 0xfec)) )#define VIC3PCELLID0( *((volatile unsigned long *)(VIC3_BASE + 0xff0)) )#define VIC3PCELLID1( *((volatile unsigned long *)(VIC3_BASE + 0xff4)) )#define VIC3PCELLID2( *((volatile unsigned long *)(VIC3_BASE + 0xff8)) )#define VIC3PCELLID3( *((volatile unsigned long *)(VIC3_BASE + 0xffc)) )#define_Exception_Vector0xD0037400#define pExceptionRESET( *((volatile unsigned long *)(_Exception_Vector + 0x0)) )#define pExceptionUNDEF( *((volatile unsigned long *)(_Exception_Vector + 0x4)) )#define pExceptionSWI( *((volatile unsigned long *)(_Exception_Vector + 0x8)) )#define pExceptionPABORT( *((volatile unsigned long *)(_Exception_Vector + 0xc)) )#define pExceptionDABORT( *((volatile unsigned long *)(_Exception_Vector + 0x10)) )#define pExceptionRESERVED( *((volatile unsigned long *)(_Exception_Vector + 0x14)) )#define pExceptionIRQ( *((volatile unsigned long *)(_Exception_Vector + 0x18)) )#define pExceptionFIQ( *((volatile unsigned long *)(_Exception_Vector + 0x1c)) )void exceptionundef(void){ printf("undefined instruction exception.\n"); while(1);}void exceptionswi(void){ printf("swi exception.\n"); while(1);}void exceptionpabort(void){ printf("pabort exception.\n"); while(1);}void exceptiondabort(void){ printf("dabort exception.\n"); while(1);}// 中斷相關初始化void system_initexception( void){ // 設定中斷向量表 pExceptionUNDEF =(unsigned long)exceptionundef; pExceptionSWI =(unsigned long)exceptionswi; pExceptionPABORT =(unsigned long)exceptionpabort; pExceptionDABORT =(unsigned long)exceptiondabort; pExceptionIRQ =(unsigned long)IRQ_handle; pExceptionFIQ =(unsigned long)IRQ_handle; // 初始化中斷控制器 intc_init();}// 初始化中斷控制器void intc_init(void){ // 禁止所有中斷 VIC0INTENCLEAR = 0xffffffff; VIC1INTENCLEAR = 0xffffffff; VIC2INTENCLEAR = 0xffffffff; VIC3INTENCLEAR = 0xffffffff; // 選擇中斷類型為IRQ VIC0INTSELECT = 0x0; VIC1INTSELECT = 0x0; VIC2INTSELECT = 0x0; VIC3INTSELECT = 0x0; // 清VICxADDR intc_clearvectaddr();}// 儲存需要處理的中斷的中斷處理函數的地址void intc_setvectaddr(unsigned long intnum, void (*handler)(void)){ //VIC0 if(intnum<32) { *( (volatile unsigned long *)(VIC0VECTADDR + 4*intnum) ) = (unsigned)handler; } //VIC1 else if(intnum<64) { *( (volatile unsigned long *)(VIC1VECTADDR + 4*(intnum-32)) ) = (unsigned)handler; } //VIC2 else if(intnum<96) { *( (volatile unsigned long *)(VIC2VECTADDR + 4*(intnum-64)) ) = (unsigned)handler; } //VIC3 else { *( (volatile unsigned long *)(VIC3VECTADDR + 4*(intnum-96)) ) = (unsigned)handler; } return;}// 清除需要處理的中斷的中斷處理函數的地址void intc_clearvectaddr(void){ // VICxADDR:當前正在處理的中斷的中斷處理函數的地址 VIC0ADDR = 0; VIC1ADDR = 0; VIC2ADDR = 0; VIC3ADDR = 0;}// 使能中斷void intc_enable(unsigned long intnum){ unsigned long temp; if(intnum<32) { temp = VIC0INTENABLE; temp |= (1<<intnum); VIC0INTENABLE = temp; } else if(intnum<64) { temp = VIC1INTENABLE; temp |= (1<<(intnum-32)); VIC1INTENABLE = temp; } else if(intnum<96) { temp = VIC2INTENABLE; temp |= (1<<(intnum-64)); VIC2INTENABLE = temp; } else if(intnum<NUM_ALL) { temp = VIC3INTENABLE; temp |= (1<<(intnum-96)); VIC3INTENABLE = temp; } // NUM_ALL : enable all interrupt else { VIC0INTENABLE = 0xFFFFFFFF; VIC1INTENABLE = 0xFFFFFFFF; VIC2INTENABLE = 0xFFFFFFFF; VIC3INTENABLE = 0xFFFFFFFF; }}// 禁止中斷void intc_disable(unsigned long intnum){ unsigned long temp; if(intnum<32) { temp = VIC0INTENCLEAR; temp |= (1<<intnum); VIC0INTENCLEAR = temp; } else if(intnum<64) { temp = VIC1INTENCLEAR; temp |= (1<<(intnum-32)); VIC1INTENCLEAR = temp; } else if(intnum<96) { temp = VIC2INTENCLEAR; temp |= (1<<(intnum-64)); VIC2INTENCLEAR = temp; } else if(intnum<NUM_ALL) { temp = VIC3INTENCLEAR; temp |= (1<<(intnum-96)); VIC3INTENCLEAR = temp; } // NUM_ALL : disable all interrupt else { VIC0INTENCLEAR = 0xFFFFFFFF; VIC1INTENCLEAR = 0xFFFFFFFF; VIC2INTENCLEAR = 0xFFFFFFFF; VIC3INTENCLEAR = 0xFFFFFFFF; } return;}// 讀中斷狀態unsigned long intc_getvicirqstatus(unsigned long ucontroller){ if(ucontroller == 0) returnVIC0IRQSTATUS; else if(ucontroller == 1) return VIC1IRQSTATUS; else if(ucontroller == 2) return VIC2IRQSTATUS; else if(ucontroller == 3) return VIC3IRQSTATUS; else {} return 0;}// 通用中斷處理函數void irq_handler(void){ unsigned long vicaddr[4] = {VIC0ADDR,VIC1ADDR,VIC2ADDR,VIC3ADDR}; int i=0; void (*isr)(void) = NULL; for(; i<4; i++) { if(intc_getvicirqstatus(i) != 0) { isr = (void (*)(void)) vicaddr[i]; break; } } (*isr)();}
Smart210學習記錄-----中斷