文章目錄
- arch/arm/lib/delay.c
- register_current_timer_delay 注冊當前定時器延遲
- read_current_timer 讀取當前定時器
- drivers/clocksource/timer-stm32.c
- stm32_clocksource_init STM32 平臺上初始化時鐘源

https://github.com/wdfk-prog/linux-study
arch/arm/lib/delay.c
register_current_timer_delay 注冊當前定時器延遲
void __init register_current_timer_delay(const struct delay_timer *timer)
{u32 new_mult, new_shift;u64 res;clocks_calc_mult_shift(&new_mult, &new_shift, timer->freq,NSEC_PER_SEC, 3600);res = cyc_to_ns(1ULL, new_mult, new_shift);if (res > 1000) {pr_err("Ignoring delay timer %ps, which has insufficient resolution of %lluns\n",timer, res);return;}if (!delay_calibrated && (!delay_res || (res < delay_res))) {pr_info("Switching to timer-based delay loop, resolution %lluns\n", res);delay_timer = timer;lpj_fine = timer->freq / HZ;delay_res = res;/* cpufreq 可能會loops_per_jiffy擴展,因此請保留一個私有副本 */arm_delay_ops.ticks_per_jiffy = lpj_fine;arm_delay_ops.delay = __timer_delay;arm_delay_ops.const_udelay = __timer_const_udelay;arm_delay_ops.udelay = __timer_udelay;} else {pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");}
}
read_current_timer 讀取當前定時器
int read_current_timer(unsigned long *timer_val)
{if (!delay_timer)return -ENXIO;*timer_val = delay_timer->read_current_timer();return 0;
}
EXPORT_SYMBOL_GPL(read_current_timer);
drivers/clocksource/timer-stm32.c
stm32_clocksource_init STM32 平臺上初始化時鐘源
static unsigned long stm32_read_delay(void)
{return readl_relaxed(stm32_timer_cnt);
}static int __init stm32_clocksource_init(struct timer_of *to)
{u32 bits = stm32_timer_of_bits_get(to);const char *name = to->np->full_name;/** 此驅動程序允許注冊多個計時器,并依賴于通用時間框架來選擇正確的計時器。* 但是,不允許對 sched_clock 執行相同的作。* 我們對 16 位定時器的 sched_clock 不感興趣,而只對 32 位定時器感興趣,* 因此如果尚未注冊 32 位定時器,我們選擇這個 32 位定時器作為sched_clock。*/if (bits == 32 && !stm32_timer_cnt) {/** 立即啟動計數器,因為我們將在之后立即使用它。*/stm32_timer_start(to);/* 獲取計數器寄存器地址 */stm32_timer_cnt = timer_of_base(to) + TIM_CNT;sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));pr_info("%s: STM32 sched_clock registered\n", name);stm32_timer_delay.read_current_timer = stm32_read_delay;stm32_timer_delay.freq = timer_of_rate(to);register_current_timer_delay(&stm32_timer_delay);pr_info("%s: STM32 delay timer registered\n", name);}return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,timer_of_rate(to), bits == 32 ? 250 : 100,bits, clocksource_mmio_readl_up);
}