从硬件架构图中可以看出以下特点:
local timer 的 clocksource 相关的配置信息:
static struct clocksource clocksource_counter = {
.name = "arch_sys_counter",
.rating = 400,
.read = arch_counter_read,
.mask = CLOCKSOURCE_MASK(56),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
local timer 的 clock_event_device 相关的配置信息:
static void __arch_timer_setup(unsigned type,
struct clock_event_device *clk)
{
clk->features = CLOCK_EVT_FEAT_ONESHOT;
if (type == ARCH_TIMER_TYPE_CP15) {
if (arch_timer_c3stop)
clk->features |= CLOCK_EVT_FEAT_C3STOP;
clk->name = "arch_sys_timer";
clk->rating = 450;
clk->cpumask = cpumask_of(smp_processor_id());
clk->irq = arch_timer_ppi[arch_timer_uses_ppi];
switch (arch_timer_uses_ppi) {
......
case ARCH_TIMER_PHYS_NONSECURE_PPI:
case ARCH_TIMER_HYP_PPI:
clk->set_state_shutdown = arch_timer_shutdown_phys;
clk->set_state_oneshot_stopped = arch_timer_shutdown_phys;
clk->set_next_event = arch_timer_set_next_event_phys;
break;
default:
BUG();
}
}
system counter 的 clock_event_device 相关的配置信息如下所示,充当硬件timer,当CPU进入idle后用来唤醒CPU。
static struct clock_event_device clockevent_sysctr = {
.name = "i.MX system counter timer",
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ,
.set_state_oneshot = sysctr_set_state_oneshot,
.set_next_event = sysctr_set_next_event,
.set_state_shutdown = sysctr_set_state_shutdown,
.rating = 200,
};
struct tick_device {
struct clock_event_device *evtdev;
enum tick_device_mode mode;
};
tick device的工作模式定义如下:
enum tick_device_mode {
TICKDEV_MODE_PERIODIC,
TICKDEV_MODE_ONESHOT,
};
static struct tick_device tick_broadcast_device;
当没有进程调度到该 CPU 上执行的时候,swapper进程会将该 CPU 推入到 idle 状态。当 CPU 睡的时候,有可能会关闭 local timer 硬件。这就会导致 local timer 将无法唤醒 CPU。
为了在 CPU 进入 idle 后还能被唤醒,有两种方案,一种是通过hrtimer的软件方案,还有一种是硬件方案。这里只讲述硬件方案,一般采用 alway-on 的硬件 timer 作为唤醒源,它不属于任何 CPU,使用 SPI 类型的中断来唤醒 CPU,处理软件 timer。
5T技术资源大放送!包括但不限于:C/C++,Arm, Linux,Android,人工智能,单片机,树莓派,等等。在上面的【人人都是极客】公众号内回复「peter」,即可免费获取!!
记得点击分享、赞和在看,给我充点儿电吧