6、RISC-V架构下的定时器中断

        本章涉及到CLINT寄存器。如何通过该寄存器的值控制定时器实现中断。

一、CLINT寄存器

        CLINT(基地址:0x02000000)是用于处理器本地中断的控制器,它主要管理定时器中断和软件中断,并将这些中断分发到RISC-V处理器内核。

        关于定时器中断主要涉及两个寄存器,mtime(偏移地址:0xBFF8)和mtimecmp(偏移地址:0x4000)。其中mtime用于存储自开机以来经过的时钟数。  mtimecmp中的值用来和mtime中的值进行对比,若mtimecmp中的值小于等于mtime中的值则会触发定时器中断。

        同样的,想要使能定时器中断,需要把mie寄存器中的第7位MTIE值置为1。

void timer_load(int interval)
{
    int id = 0;
    *(uint64_t *)CLINT_MTIMECMP(id) = *(uint64_t *)CLINT_MTIME + interval;
}

void timer_init()
{
    timer_load(TIMER_INTERVAL);
    w_mie(MIE_MTIE);
}

二、处理定时器中断 

        可以通过mcause的值来区分是不是定时器中断。想要实现循环中断,只需要在中断处理时,更新mtimecmp的值位mtime的值加上一个固定间隔的数即可。

void timer_load(int interval)
{
    int id = 0;
    *(uint64_t *)CLINT_MTIMECMP(id) = *(uint64_t *)CLINT_MTIME + interval;
}
void timer_handler() 
{
	_tick++;
	printf("tick: %d\n", _tick);

	timer_load(TIMER_INTERVAL);
}
reg_t trap_handler(reg_t epc,reg_t cause){
    reg_t return_pc = epc;
    reg_t cause_code = cause & MCAUSE_MASK_ECODE;
	Uart_puts("traps!\n");
    if(cause & MCAUSE_MASK_INTERRUPT){
        switch (cause_code)
        {
        case 3:
            Uart_puts("software interruption!\n");
            break;
        
        case 7:
			Uart_puts("timer interruption!\n");
			timer_handler();
			break;
		case 11:
			Uart_puts("external interruption!\n");
			external_interrupt_handler();
			break;
		default:
			printf("Unknown async exception! Code = %ld\n", cause_code);
			break;
        }
    }else {
		/* Synchronous trap - exception */
		printf("Sync exceptions! Code = %ld\n", cause_code);
		panic("OOPS! What can I do!");
		return_pc += 4;
	}
    return return_pc;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值