循序渐进,学习开发一个RISC-V 上的操作系统

第 12 章 硬件定时器

RISC-V 定时器中断

 RISC-V CLINT 介绍

 软件中断和定时器中断都由芯片自带的设备CLINT控制触发。

CLINT编程接口-寄存器

 mtimecmp需要手动设置初始值,上述代码初始化时,调用time_load()函数,并传入时间间隔参数TIMER_INTERVAL 来设置mtimecmp的初值。

当mtime >= mtimecmp时,CLINT会产生一个timer中断。如果要使能该中断需要保证全局中断打开mstatus.mIE = 1并且mie.MTIE标志位置1

当timer中断发生时,hart会设置mip.MTIP,程序可以在mtimecmp中写入新的值,清除mip.MTIP

当cause最高位为1且casue_code为7时,说明当前触发了定时器中断,调用timer_handler,首先hart自动进行设置,然后调用timer_load()函数,让mtimecmp += TIMER_INTERVAL 即再过TIMER_INTERVAL时间间隔会再次触发定时器中断,实现了周期性定时器

CLINT总体框架流程:

硬件定时器的应用

时间管理

实现操作系统的时间管理。

时钟节拍(Tick)

  • 操作系统中最小的时间单位。
  • Tick 的单位(周期)由硬件定时器的周期决定 (通常为 1 ~ 100ms)。
  • Tick 周期越小,系统的精度越高,但开销越大。

系统时钟 

  • 操作系统维护的一个整型计数值,记录着系统启动直到当前发生的 Tick 总数。
  • 可用于维护系统的墙上时间,所以也称为系统时钟。

代码运行

1、先手动设置对应hart下的MTIMECMP

2、分别打开machine模式下的定时器中断使能和全局中断使能

3、发生定时器中断时,进入timer_handler处理函数,打印当前tick值,并更新MTIMECMP,实现周期定时器。

/* load timer interval(in ticks) for next timer interrupt.*/
void timer_load(int interval)
{
	/* each CPU has a separate source of timer interrupts. */
	int id = r_mhartid();
	
	*(uint64_t*)CLINT_MTIMECMP(id) = *(uint64_t*)CLINT_MTIME + interval;
}

void timer_init()
{
	/*
	 * On reset, mtime is cleared to zero, but the mtimecmp registers 
	 * are not reset. So we have to init the mtimecmp manually.
	 */
	timer_load(TIMER_INTERVAL);

	/* enable machine-mode timer interrupts. */
	w_mie(r_mie() | MIE_MTIE);

	/* enable machine-mode global interrupts. */
	w_mstatus(r_mstatus() | MSTATUS_MIE);
}

void timer_handler() 
{
	_tick++;
	printf("%d\n", _tick);
	timer_load(TIMER_INTERVAL);
}

运行效果如下:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值