Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
定时器
HWTIMER_硬件定时器
IMX.RT
关于硬件定时器框架和驱动的建议
发布于 2023-11-24 18:06:04 浏览:498
订阅该版
在使用 imxrt1061的timer做验证时出现的问题,以下是测试代码: ```c static rt_err_t timer1_callback(rt_device_t dev, rt_size_t size) { static rt_uint32_t count = 0; rt_hwtimerval_t timeout = {0}; rt_device_read(dev, 0, &timeout, sizeof(timeout)); rt_kprintf("this is timer1 callback read: sec = %d, usec = %d\n", timeout.sec, timeout.usec); count++; if(count >= 10) { rt_kprintf("timer1 end\n"); rt_device_close(dev); count=0; } return RT_EOK; } static rt_err_t timer2_callback(rt_device_t dev, rt_size_t size) { rt_hwtimerval_t timeout = {0}; rt_device_read(dev, 0, &timeout, sizeof(timeout)); rt_kprintf("this is timer2 callback read: sec = %d, usec = %d\n\n", timeout.sec, timeout.usec); return RT_EOK; } static void timer_sample(int argc, char *argv[]) { rt_device_t timer1_dev = RT_NULL; rt_device_t timer2_dev = RT_NULL; rt_hwtimer_mode_t mode = HWTIMER_MODE_ONESHOT; rt_hwtimerval_t timeout = {0}; /* configure timer0 */ timer1_dev = rt_device_find("gpt1"); if (timer1_dev == RT_NULL) { rt_kprintf("timer1_dev can't find\n"); return; } rt_device_open(timer1_dev, RT_DEVICE_FLAG_RDWR); rt_device_set_rx_indicate(timer1_dev, timer1_callback); rt_device_control(timer1_dev, HWTIMER_CTRL_MODE_SET, (void *)&mode); /* configure timer1 */ timer2_dev = rt_device_find("gpt2"); if (timer2_dev == RT_NULL) { rt_kprintf("timer2_dev can't find\n"); return; } rt_device_open(timer2_dev, RT_DEVICE_FLAG_RDWR); rt_device_set_rx_indicate(timer2_dev, timer2_callback); mode = HWTIMER_MODE_ONESHOT; rt_device_control(timer2_dev, HWTIMER_CTRL_MODE_SET, (void *)&mode); /* start timer2 period:1s*/ timeout.sec = 1; timeout.usec = 0; if(rt_device_write(timer2_dev, 0, &timeout, sizeof(timeout)) == 0) { rt_kprintf("timer2 fail\n"); return; } /* start timer1 period:2s */ timeout.sec = 5; timeout.usec = 0; if(rt_device_write(timer1_dev, 0, &timeout, sizeof(timeout)) == 0) { rt_kprintf("timer1 fail\n"); return; } } MSH_CMD_EXPORT(timer_sample, timer_sample); ``` 理论上打印值应该为: ```shell msh />timer_sample this is timer2 callback read: sec = 1, usec = 0 this is timer1 callback read: sec = 5, usec = 0 ``` 实际上打印值为: ```shell msh />timer_sample this is timer2 callback read: sec = 2, usec = 4 this is timer1 callback read: sec = 10, usec = 2 ``` 忽略误差不计,出现了获取到的值翻倍的情况,但是定时时间准确的情况; 经过调试和排查,发现是因为设置单次触发模式时,芯片定时器的重载值并不会像 stm32 一样自动重载,由此导致框架获取的定时器计数值出现错误,计算出翻倍的值,再往下探究发现框架中有如下处理: ```c void rt_device_hwtimer_isr(rt_hwtimer_t *timer) { rt_base_t level; RT_ASSERT(timer != RT_NULL); level = rt_hw_interrupt_disable(); timer->overflow ++; if (timer->cycles != 0) { timer->cycles --; } if (timer->cycles == 0) { timer->cycles = timer->reload; rt_hw_interrupt_enable(level); if (timer->mode == HWTIMER_MODE_ONESHOT) { if (timer->ops->stop != RT_NULL) { timer->ops->stop(timer); } } if (timer->parent.rx_indicate != RT_NULL) { timer->parent.rx_indicate(&timer->parent, sizeof(struct rt_hwtimerval)); } } else { rt_hw_interrupt_enable(level); } } ``` 在中断处理中,会判断定时器触发模式,如果是单次触发则会直接停止定时器,由此可得,就算直接将定时器配置为周期触发,也不会影响单次触发的功能,于是对驱动做如下修改: ```c static rt_err_t imxrt_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode) { GPT_Type *hwtimer_dev; hwtimer_dev = (GPT_Type *)timer->parent.user_data; RT_ASSERT(timer != RT_NULL); /* 原处理 */ // hwtimer_dev->CR |= (mode != HWTIMER_MODE_PERIOD) ? GPT_CR_FRR_MASK : 0U; /* 修改后的处理 */ hwtimer_dev->CR |= 0U; GPT_SetOutputCompareValue(hwtimer_dev, kGPT_OutputCompare_Channel1, cnt); GPT_EnableInterrupts(hwtimer_dev, kGPT_OutputCompare1InterruptEnable); NVIC_Configuration(); GPT_StartTimer(hwtimer_dev); return RT_EOK; } ``` 再次测试上述测试代码功能,打印如下: ```shell msh />timer_sample this is timer2 callback read: sec = 1, usec = 4 this is timer1 callback read: sec = 5, usec = 1 ``` 可证明猜测是正确的。 所以是否应该移除硬件定时器 ops ```c struct rt_hwtimer_ops { void (*init)(struct rt_hwtimer_device *timer, rt_uint32_t state); rt_err_t (*start)(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode); void (*stop)(struct rt_hwtimer_device *timer); rt_uint32_t (*count_get)(struct rt_hwtimer_device *timer); rt_err_t (*control)(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args); }; ``` 中 start 的参数 mode,避免对驱动开发造成误导
查看更多
zhkag
2023-11-25
这家伙很懒,什么也没写!
不能因为 其中某一个 bsp 的 mode 是有问题的就去把 rt_hwtimer_ops 的参数给移除,这个结构体 是所有的 bsp 都有可能用到的,而不单单是这一个 bsp
2
个回答
默认排序
按发布时间排序
winfeng
认证专家
2023-11-26
这家伙很懒,什么也没写!
虽然,但是, 我还没想过硬定时器回调函数里用read、write设备这样的操作,好像没意义,没实际用途。
撰写答案
登录
注册新账号
关注者
0
被浏览
498
关于作者
先森你的苏菲掉了
这家伙很懒,什么也没写!
提问
2
回答
0
被采纳
0
关注TA
发私信
相关问题
1
定时器中要延时,用什么办法?
2
cubemx配置定时器PWM可以输出移到RT_stdio不能输出?
3
对源码中优先级处理和定时器的两个疑问?
4
关于定时器时钟,怎么定时一个1MHz时钟
5
rt_spi_send、rt_spi_recv不能放在定时器里进行使用
6
关闭定时器中断,再开启中断
7
关于在L4潘多拉上定时器TIM3跑hwtimer_sample例程出错的问题
8
rtthread studio里定时器倍频问题
9
rt-thread-studio开发潘多拉的定时器出现问题?
10
多个软件定时器之间会不会冲突
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
5
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部