您的位置:首页 > 其它

ARM中断系统详述3

2016-08-26 02:36 239 查看
第三步是void system_init_exception(void);

这个函数的作用是初始化中断控制器

寄存器在上一章已经声明过了,接下来我们只写程序。

void system_init_exception(void)

{
//绑定异常向量表(这些函数名地址转换成四个字节的地址)
//如果有异常产生时,CPU就会从异常向量表中找到处理程序的地址,转而去执行异常处理程序
(*(volatile unsigned int *)exception_reset)    = (unsigned int)reset_exception;
(*(volatile unsigned int *)exception_undef)    = (unsigned int)undef_exception;
(*(volatile unsigned int *)exception_sotf_int) = (unsigned int)sotf_int_exception;
(*(volatile unsigned int *)exception_prefetch) = (unsigned int)prefetch_exception;
(*(volatile unsigned int *)exception_data)     = (unsigned int)data_exception;
(*(volatile unsigned int *)exception_irq)      = (unsigned int)IRQ_handle;
(*(volatile unsigned int *)exception_fiq)      = (unsigned int)IRQ_handle;

// 初始化中断控制器的基本寄存器
// 不用的中断一定要关掉,否则则程序很可能跑飞(硬件置1则进去执行,如果里面的代码是乱码那就跑飞了)
// 先全部关掉,然后再逐一打开需要的中断。一旦打开就必须给这个中断提供相应的isr并绑定好。

    VIC0INTENCLEAR = 0xffffffff;

    VIC1INTENCLEAR = 0xffffffff;

    VIC2INTENCLEAR = 0xffffffff;

    VIC3INTENCLEAR = 0xffffffff;

    // 选择中断类型为IRQ

    VIC0INTSELECT = 0x0;

    VIC1INTSELECT = 0x0;

    VIC2INTSELECT = 0x0;

    VIC3INTSELECT = 0x0;

    // 清VICxADDR

    // VICxADDR:当前正在处理的中断的中断处理函数的地址
//每个中断源都有一个VECTADDR寄存器,用来存放这个中断对应的函数的地址(程序员自己存)
//中断产生的时候,硬件自动找到中断源的中断编号,并把则中断对应的函数的地址推入
//VICnADDR寄存器,我们直接读出来就可以使用了。

    VIC0ADDR = 0;

    VIC1ADDR = 0;

    VIC2ADDR = 0;

    VIC3ADDR = 0;

}

第四步:绑定isr函数的地址到中断控制器硬件

等发生相应中断的时候,我们直接到相应的VICnADDR中去取isr地址即可。

VIC0VECTADDR定义为VIC0VECTADDR0寄存器的地址,就相当于是VIC0VECTADDR0~31这个函数指针数组的首地址,

然后具体计算每一个中断的时候只需要首地址+偏移量即可

这两个参数中,intnum是int.h定义的物理中断号,handle是isr函数的指针

void intc_setvectaddr(unsigned long intnum, void (*handler)(void))

{

    //VIC0

    if(intnum<32)

    {

        *( (volatile unsigned long *)(VIC0VECTADDR + 4*(intnum-0)) ) = (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;

}

第五步是使能中断

通过intnum(物理中断号)来使能某个具体的中断源

void intc_enable(unsigned long intnum)

{

    unsigned long temp;
// 确定intnum在哪个寄存器的哪一位

    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;

    }

    //这个机制可以一次打开所有中断源

    else

    {

        VIC0INTENABLE = 0xFFFFFFFF;

        VIC1INTENABLE = 0xFFFFFFFF;

        VIC2INTENABLE = 0xFFFFFFFF;

        VIC3INTENABLE = 0xFFFFFFFF;

    }

}

S5PV210的好处就是,往VICnINTENABLE里面写1的时候,不管VICnINTENABLE里面是啥,都会使写1的那一位对应的中断使能,

往VICnINTENABLE里面写1的时候,不管VICnINTENABLE里面是啥,都会使写1的那一位对应的中断禁止。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: