嵌入式技术william hill官网
直播中

王艳

7年用户 1276经验值
私信 关注
[经验]

在RT-Thread中的时钟管理与HWTIME设备两者实现定时器有什么不同

问题
在rt编程手册中的时钟管理与HWtiME设备
两者都实现定时器有什么不同???如何合理使用两者呢???
不同点
时钟管理的HARDTIME模式是通过使用定时器的时钟,一般的就是硬件systick,控制rt_tick,实现计时。rt_tick是系统的时间节拍。超时回调函数在中断处理程序中进行调用。而使用软件定时器,回调函数则会在timer线程中。软件定时器模式,受限于系统节拍。
由于系统节拍是OS运行的基础,所以就要兼顾高低速的设备及应用,这个值一般是MS级别。ns级别太快,会导到系统不停的切换任务,造成效率不高。
此部的应用场景,就是跟随rt-tick级别的定时需求。若是要更快级别的定时器,还要使用真正的硬件定时器。
hwtim是把硬件定时器当成是设备来处理的。也是实现定时。但可以实现更快或更慢的定时。也不再受rt-tick的局限。同时,还是随时读取定时器当前值。
使用步骤:
使用CubxMX配置一下定时器,生成相应的代码,使之启用HAL库的time组件。
board文件夹下,修改kconfig文件,添加TIM开启选项代码如下所示:
menuconfig BSP_USING_TIM
        bool "Enable timer"
        default n
        select RT_USING_HWTIMER
        if BSP_USING_TIM
            config BSP_USING_TIM1
                bool "Enable TIM1"
                default n
            config BSP_USING_TIM2
                bool "Enable TIM2"
                default n
            config BSP_USING_TIM15
                bool "Enable TIM15"
                default n
        endif
使用ENV工具配置,开启TIM.如下图所示:

重新生成一下工程。
4. 在tim_config.h文件(路径为:…librariesHAL_Driversconfigl4)中添加tim1的配置。这步一定要根据在CUBmx配置写。如下图所示:

中断入口名一定要填对,可通过startup_STM32l431xx.s验证。一般的路径为:…librariesSTM32L4xx_HALCMSISDeviceSTSTM32L4xxSourceTemplatesarmstartup_stm32l431xx.s
或是stm32l4xx_hal.c文件路径为:…librariesSTM32L4xx_HALSTM32L4xx_HAL_DriverSrcstm32l4xx_hal.c
当然最简单的办法是看一下,CUBMX自动生成的中断it文件。
5. 编译整体的工程,成功后可以看到shell能成功打印出time1的设备。接下来就可以操作time1了。如下图所示:

可以将官方给出的例子程序执行一下,如下图所示:5s后打印当前定时器的值

总结
基本按照官方给出的例子,走了一遍流程!官方给出的只是一个最简单的定时例子,关于定时器的其他功能,还要自己研究和开发。
rt定时器设备框架
这个基本没变,延用就是linux风格的rt管理框架,如下图所示:

基本的处理流程
初始化
drv_hwtimer.c 中static int stm32_hwtimer_init(void)完成定时器初始化,并完成自动注册INIT_BOARD_EXPORT(stm32_hwtimer_init);
stm32_hwtimer_init完成了两件事。
stm32_hwtimer_obj.time_device.info = &_info;//定时器最大、最小频率、上升模式信息
stm32_hwtimer_obj.time_device.ops = &_ops;//定时时间的控制、开始、停止、定时器当前值的获取回调函数地址
rt_device_hwtimer_register(&stm32_hwtimer_obj.time_device, stm32_hwtimer_obj.name, &stm32_hwtimer_obj.tim_handle) //完成了注册
注册到OS的设备管理层
上步最终通过rt_device_register(),注册到了OS设备管理层,注册只是注册了名称,主要是名称,还有一些特有如中断类型,这个压根就没定义,因此也为void *.
当应用层执行rt_device_open()时会初始化,调用rt_hwtimer_init()(位于hwtimer.c文件中),这是默认的初始化函数。又调用驱动层的timer->ops->init(timer, 1);也就是static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)函数(位于drv_hwtimer.c文件中)。
这个函数,可以来说相当重要,这就是普通硬件配置time,完成分频、中断优先级等配置。并调用了HAL_TIM_Base_Init(tim)(位于stm32l4xx_hal_tim.c中)间接调用了HAL_TIM_Base_MspInit()函数(位于stm32l4xx_hal_msp.c,这个就是由cubemx自动生成的tims时钟配置)启动time时钟。从而完成了底层的初始化的调用。
控制
应用层执行rt_device_control()(此文件位于kernel文件夹中的device.c文件中)函数时,会调用设备管理层里的device_control(dev, cmd, arg);//实际上为一个指针,指向驱动框架层的控制函数
跳到设备驱动框架层的hwtimer.c文件中函数rt_hwtimer_control()中,根据相关的控制命令,会执行驱动层的rt_err_t timer_ctrl()(位于drv_hwtimer.c文件中)函数,从而实现控制设置。
总结
不多说,其他的相关操作,也是通过这个思路,一层层往下调用。

原作者:
guangod

回帖(2)

杨杰

2022-5-10 11:10:12
举报

岳臻俊

2022-5-10 11:10:27
举报

更多回帖

发帖
×
20
完善资料,
赚取积分