zoukankan      html  css  js  c++  java
  • S5PV210中断体系结构分析

    我们按照Tiny210官方的裸板程序来梳理S5PV210的中断体系。

    关于 S5PV210 的中断体系结构

    S5PV210 的中断控制器是由 4 个向量中断控制器(VIC)、 ARM PrimeCell PL192 和 4 个
    TrustZone Interrupt Controller (TZIC)共同组成。
    S5PV210 共支持 93 个中断源(具体见官方手册)。

    首先看 Start.S

    .global _start
    .global IRQ_handle
    
    _start:
    	@ 关闭看门狗
    	ldr	r0, =0xE2700000			
    	mov	r1, #0
    	str	r1, [r0]
    
    	@ 设置栈,以便调用c函数
    	ldr	sp, =0x40000000		
    
    	@ 开中断
    	mov r0, #0x53			
    	msr CPSR_cxsf, r0	
    
    	@ 汇编初始化时钟		
    	bl clock_init	
    
    	@ 调用main函数
    	bl main	
    
    IRQ_handle:
    
    	@ 设置中断模式的栈
    	ldr sp, =0xD0037F80
    	
    	@ 保存现场
    	sub lr, lr, #4				
    	stmfd sp!, {r0-r12, lr}
    	
    	@ 跳转到中断处理函数
    	bl	irq_handler		
    	
    	@ 恢复现场
    	ldmfd sp!, {r0-r12, pc}^
    

    设置 CPSR = #0x53,进入SVC模式,开IRQ中断。

    接着在main函数中会调用 system_initexception 函数:

    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
        VIC0ADDR = 0;
        VIC1ADDR = 0;
        VIC2ADDR = 0;
        VIC3ADDR = 0;
    }
    

    然后设置 VICINTENABLE 使能中断。

    我们只关心这条就可以:

    pExceptionIRQ	  =	(unsigned long)IRQ_handle;
    

    头文件中这样定义:

    #define    _Exception_Vector	0xD0037400
    #define    pExceptionIRQ		( *((volatile unsigned long *)(_Exception_Vector + 0x18)) )
    
    而S5PV210 的异常向量表的起始地址是0xD0037400,原因见下图:

    这样,在发生IRQ中断时,PC就会跳转到 pExceptionIRQ 地址处,从而执行了 IRQ_handle 函数,接着又执行了 irq_handler 函数。

    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)();
    }
    

    通过调用 intc_getvicirqstatus 函数返回 VICIRQSTATUS 的值就知道当前VIC中是否有中断请求,有的话就会将isr赋值为 VICADDR 的值,即(服务函数的地址),然后调用服务程序。

    有一点需要说明:

    当有中断发生时,硬件上会将当前中断的中断处理函数从寄存器 VICVECTADDR 自动拷贝到寄存器
    VICADDR 中, 所以我们在 irq_handler()函数里会调用保存在寄存器 VICADDR 里的中断处理函数。假如我们要开启 EXINT0 中断,那么我们只需将中断服务程序的地址赋值给 VIC0VECTADDR0 即可。

  • 相关阅读:
    Android SurfaceView实战 带你玩转flabby bird (上)
    linux释放内存的命令
    Linux上的free命令详解
    app后端设计(14)--LBS的偏移问题
    包床、退床
    oracle学习17
    提示在【办公管理】-->【今日工作】
    oracle学习16
    数据库的表信息
    CodeForces
  • 原文地址:https://www.cnblogs.com/GyForever1004/p/8367272.html
Copyright © 2011-2022 走看看