分类: 嵌入式
2010-01-11 15:41:28
1. 中断
中断/异常入口基址ebase设置并不在0x80000000,而是其它地址。
中断配制成矢量模式,vector offset配置成0x100。Int0~int7(int0/int1:sw;int2~int7:hw;int7-count/compare)
Ebase:0x
a) 矢量中断入口注册
set_vi_handler(2, mips_int2_handler);
void *set_vi_handler(int n, vi_handler_t addr)
{
return set_vi_srs_handler(n, addr, 0);
}
static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
{
extern char except_vec_vi, except_vec_vi_lui;
extern char except_vec_vi_ori, except_vec_vi_end;
extern char rollback_except_vec_vi;
char *vec_start = (cpu_wait == r4k_wait) ?
&rollback_except_vec_vi : &except_vec_vi;
const int handler_len = &except_vec_vi_end - vec_start;
const int lui_offset = &except_vec_vi_lui - vec_start;
const int ori_offset = &except_vec_vi_ori - vec_start;
if (handler_len > VECTORSPACING) {
/*
* Sigh... panicing won't help as the console
* is probably not configured :(
*/
panic("VECTORSPACING too small");
}
memcpy(b, vec_start, handler_len); //拷贝一段公用的中断处理入口代码片段
w = (u32 *)(b + lui_offset); //修改中断处理函数的地址
*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
w = (u32 *)(b + ori_offset); //修改中断处理函数的地址
*w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
local_flush_icache_range((unsigned long)b,
(unsigned long)(b+handler_len)); //刷icache
}
b) 中断处理服务程序注册
setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
setup_irq(MIPS_CPU_IRQ_BASE + 3, &dma_irqaction);
setup_irq(ASOC_IRQ_BASE + DMA_INT, &cascade_irqaction);
setup_irq(ASOC_IRQ_BASE + PC_INT, &cascade_irqaction);
#define IRQ_TIMER0 (ASOC_IRQ_BASE+10) //对应irq分配策略
request_irq(IRQ_TIMER0, mips_timer_interrupt, 0, "timer", (void *)0);
int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
…
setup_irq(irq, action);
…
}
c) setup_irq的参数irq与irq分配策略有关。
原则上是任意一个硬件中断源可以随意配置到任意一个中断信号上(int0~int7)。每一个中断信号上也都可以挂多个中断源。从实现和效率角度看,将一些优先级高的中断源独立的挂在一个中断信号上,其它都挂载一个公用的中断上是比较合理的。下图是一种分配方式。
d) 中断服务程序执行流程
Int2_handler
except_vec_vi_handler
NESTED(except_vec_vi_handler, 0, sp)
SAVE_TEMP
SAVE_STATIC
CLI
LONG_L s0, TI_REGS($28)
LONG_S sp, TI_REGS($28)
PTR_LA ra, ret_from_irq //中断总出口
jr v0 // mips_int2_handler
END(except_vec_vi_handler)
asmlinkage void mips_int2_handler(void)
{
xxx_irqdispatch();
}
static void xxx_irqdispatch(void)
{
int irq;
u32 intc0_pending = readl(IC0_PD);
u32 intc0_mask = readl(IC0_MASK);
u32 intc0_req0 = intc0_pending & intc0_mask;
u32 intc0_ext_int = 0;
if (!intc0_req0) {
spurious_interrupt();
goto exit;
}
irq = ffs(intc0_req0) - 1;
if (irq != EXTERNAL_INT){
do_IRQ(ASOC_IRQ_BASE + irq); //对应irq分配策略
goto exit;
}
else
{
…
}
exit:
return;
}
2. 异常
a) tlb_refill
b) general_exception
c) 设置异常处理函数入口
void *set_except_vector(int n, void *addr)
set_except_vector(0, rollback ? rollback_handle_int : handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
set_except_vector(4, handle_adel);
set_except_vector(5, handle_ades);
set_except_vector(6, handle_ibe);
set_except_vector(7, handle_dbe);
set_except_vector(8, handle_sys);
set_except_vector(9, handle_bp);
set_except_vector(10, rdhwr_noopt ? handle_ri :(cpu_has_vtag_icache ? handle_ri_rdhwr_vivt : handle_ri_rdhwr));
set_except_vector(11, handle_cpu);
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
set_except_vector(14, handle_mc);
set_except_vector(15, handle_ndc);
set_except_vector(15, handle_fpe);
set_except_vector(22, handle_mdmx);
set_except_vector(24, handle_mcheck);
set_except_vector(25, handle_mt);
set_except_vector(26, handle_dsp);