089、Zephyr RTOS驱动开发实战:定时器驱动
Zephyr RTOS驱动开发实战:定时器驱动
从一次产线死锁说起
去年秋天帮客户调试一套工业分拣系统,Zephyr跑在STM32H743上,四个定时器分别驱动步进电机、采集编码器、触发相机和看门狗喂狗。产线跑了三天,突然在凌晨三点死锁——电机停转,相机不触发,看门狗也没复位。远程连上J-Link一看,所有定时器中断都不进了,但系统调度还在跑。查了两天,最后发现是定时器驱动里一个k_sleep()埋的雷。
这个案例让我决定把定时器驱动单独拎出来写一篇。Zephyr的定时器体系其实分三层:硬件定时器驱动、内核定时器API、以及POSIX风格的timer接口。很多新手上来就调k_timer,结果发现精度不够或者中断冲突,就是因为没搞懂底层映射关系。
硬件定时器驱动框架解剖
Zephyr的定时器驱动位于drivers/timer/目录下,每个SoC有自己的实现。以STM32为例,stm32_timer.c里实现了sys_clock_driver_init和sys_clock_announce这两个核心函数。注意,这里有个容易踩坑的设计:Zephyr的系统滴答(SYSTICK)和硬件定时器是解耦的。默认情况下,ARM Cortex-M内核用SYSTICK做系统时钟,但如果你需要更高精度的定时,就得切换到硬件定时器。
我习惯在prj.conf里这样配置: