首页 > 系统相关 >Linux在驱动里做定时循环

Linux在驱动里做定时循环

时间:2024-09-06 09:14:17浏览次数:12  
标签:do detect thcvxxx timer Linux 驱动 定时 poll sensor

1. 使用内核定时器 实现

思路是,在驱动里使用一个内核定时器,定时一个时间后,执行回调函数,再在回调函数里重新设置一次定时时间,以此往复,在回调函数里里执行自己的业务

Linux4.4内核

/* 一些变量 */
#define POLL_PERIOD (HZ/1) /* (HZ/100): Polling period .01 seconds (10ms) */ static void thcvxxx_detect_do_poll(unsigned long dummy); static DEFINE_TIMER(thcvxxx_detect_timer, thcv241_detect_do_poll, 0, 0);
/* 开始定时器 */ mod_timer(&thcvxxx_detect_timer, jiffies + POLL_PERIOD);
/* 回调函数 */ static void thcvxxx_detect_do_poll(unsigned long dummy) {
  /* 自定义业务 */
  ......
  /* 重新开始定时器 */
  mod_timer(&thcv241_detect_timer, jiffies + POLL_PERIOD);
  /* 自定义业务 */
  ...... }

 或者


/* 一些变量 */
#define POLL_PERIOD (HZ/1) /* (HZ/100): Polling period .01 seconds (10ms) */
static struct timer_list timer;
static void thcvxxx_detect_do_poll(unsigned long dummy);

/* 开始定时器 */ init_timer(&timer); timer.function= thcvxxx_detect_do_poll; timer.expires = jiffies + 1*HZ; add_timer(&timer);

static void thcvxxx_detect_do_poll(unsigned long dummy) { ...... timer.expires = jiffies + 1*HZ; add_timer(&timer); // 重新开始计时 ...... }

以上两种方式,都可以实现定时循环。

存在问题:

当在回调函数里执行iic读写时,会报错如下

------------[ cut here ]------------
WARNING: CPU: 0 PID: 0 at /home/ex/os/kernel/kernel/locking/rtmutex.c:1536 rt_mutex_trylock+0x6c/0xc4()
Modules linked in: sensor_ov9x7x3x4_thcvxxx(O) ak_isp(O) ak_mci(O) mmc_block mmc_core ak_fb(O) ak_gui(O) ak_uio(O) ak_leds(O) ak_ion(O) ak_gpio_keys(O) ak_pcm(O) ak_i2c(O) ak_rtc(O)
CPU: 0 PID: 0 Comm: swapper Tainted: G        W  O    4.4.192V2.2 #5
Hardware name: A*K*3*7*D
Backtrace:
[<c000d4e8>] (dump_backtrace) from [<c000d6e0>] (show_stack+0x18/0x1c)
 r6:c030facc r5:00000009 r4:00000000 r3:00000000
[<c000d6c8>] (show_stack) from [<c01681a0>] (dump_stack+0x20/0x28)
[<c0168180>] (dump_stack) from [<c00175bc>] (warn_slowpath_common+0x80/0xb8)
[<c001753c>] (warn_slowpath_common) from [<c0017698>] (warn_slowpath_null+0x24/0x2c)
 r8:c0438c40 r7:c0439460 r6:c042dd74 r5:c78c7420 r4:c78c7410
[<c0017674>] (warn_slowpath_null) from [<c030facc>] (rt_mutex_trylock+0x6c/0xc4)
[<c030fa60>] (rt_mutex_trylock) from [<c01eacb4>] (i2c_trylock_adapter+0x30/0x4c)
 r5:00000001 r4:c78c7410
[<c01eac84>] (i2c_trylock_adapter) from [<c01eb510>] (i2c_transfer+0x54/0xc8)
[<c01eb4bc>] (i2c_transfer) from [<c01eb5c8>] (i2c_master_send+0x44/0x54)
 r6:00000200 r5:bf0b7f14 r4:00000002 r3:00000000
[<c01eb584>] (i2c_master_send) from [<bf0b7d3c>] (i2c_read_reg2_value1+0x2c/0x54 [sensor_ov9x7x3x4_thcvxxx])
 r4:c78c7600
[<bf0b7d10>] (i2c_read_reg2_value1 [sensor_ov9x7x3x4_thcvxxx]) from [<bf0b7e58>] (i2c_read+0x50/0x70 [sensor_ov9x7x3x4_thcvxxx])
 r4:c78c7600
[<bf0b7e08>] (i2c_read [sensor_ov9x7x3x4_thcvxxx]) from [<bf0b54f8>] (ov9734_sensor_get_parameter_func+0x164/0x178 [sensor_ov9x7x3x4_thcvxxx])
[<bf0b5494>] (ov9734_sensor_get_parameter_func [sensor_ov9x7x3x4_thcvxxx]) from [<bf0b5528>] (ov9734_sensor_probe_id_func+0x1c/0x84 [sensor_ov9x7x3x4_thcvxxx])
 r5:c78c7600 r4:bf0b9700
[<bf0b550c>] (ov9734_sensor_probe_id_func [sensor_ov9x7x3x4_thcvxxx]) from [<bf0b5620>] (thcv241_detect_do_poll+0x90/0xb0 [sensor_ov9x7x3x4_thcvxxx])
 r5:bf0b5590 r4:bf0b9700
[<bf0b5590>] (thcv241_detect_do_poll [sensor_ov9x7x3x4_thcvxxx]) from [<c00482a4>] (call_timer_fn+0x2c/0xa4)
 r4:00000100 r3:c042de28
[<c0048278>] (call_timer_fn) from [<c00488b8>] (run_timer_softirq+0x118/0x1e8)
 r6:00000200 r5:00000000 r4:c0438c40
[<c00487a0>] (run_timer_softirq) from [<c001a0a4>] (__do_softirq+0xf4/0x238)
 r8:c042c000 r7:40000001 r6:00000100 r5:00000002 r4:00000001
[<c0019fb0>] (__do_softirq) from [<c001a48c>] (irq_exit+0xa8/0xf4)
 r10:80425a70 r9:c7fff460 r8:00000000 r7:00000000 r6:00000000 r5:c043d05c
 r4:00000000
[<c001a3e4>] (irq_exit) from [<c0040594>] (__handle_domain_irq+0x74/0xd0)
 r4:00000000 r3:00000000
[<c0040520>] (__handle_domain_irq) from [<c0009024>] (asm_do_IRQ+0x24/0x28)
 r8:c04464e2 r7:c042df54 r6:1380952e r5:60000013 r4:c000ab18 r3:c042df20
[<c0009000>] (asm_do_IRQ) from [<c000e000>] (__irq_svc+0x40/0x270)
Exception stack(0xc042df20 to 0xc042df68)
df20: 00000000 0005317f 0005217f 60000013 c042c000 c042e06c c042e06c c04464e2
df40: c04464e2 c7fff460 80425a70 c042df7c 600000d3 c042df70 c000ab20 c000ab18
df60: 60000013 ffffffff
[<c000aaec>] (arch_cpu_idle) from [<c003a8fc>] (default_idle_call+0x28/0x3c)
[<c003a8d4>] (default_idle_call) from [<c003a9d4>] (cpu_startup_entry+0xc4/0x120)
[<c003a910>] (cpu_startup_entry) from [<c030ccb4>] (rest_init+0x64/0x7c)
 r7:c042e000 r3:c0311ac0
[<c030cc50>] (rest_init) from [<c040ac3c>] (start_kernel+0x2dc/0x33c)
[<c040a960>] (start_kernel) from [<80008044>] (0x80008044)
---[ end trace cab02c313e6f2366 ]---

2. 使用内核定时器 + 工作队列 实现

针对以上报错,加入工作队列实现#define POLL_PERIOD (HZ/1) /* (HZ/100): Polling period .01 seconds (10ms) *static struct timer_list timerstatic void thcv241_detect_do_poll(unsigned long dummy);static struct work_struct my_work;

/* 一些变量 */
#define POLL_PERIOD (HZ/1) /* (HZ/100): Polling period .01 seconds (10ms) */
static struct timer_list timer;
static void thcv241_detect_do_poll(unsigned long dummy);

static struct work_struct my_work;
static void my_work_poll(struct work_struct *unused);

/* 开始定时器 */
init_timer(&timer);
timer.function= thcv241_detect_do_poll;
timer.expires = jiffies + 1*HZ;
add_timer(&timer);

INIT_WORK(&my_work, my_work_poll);

/* 定时器回调函数 */ static void thcv241_detect_do_poll(unsigned long dummy) { timer.expires = jiffies + 1*HZ; add_timer(&timer); // 重新开始计时
schedule_work(&my_work); }
/* 工作队列回调函数 */ static void my_work_poll(struct work_struct *unused) { /* 自定义业务,如iic读写 */
  ...... }

使用以上方法,在工作队列里 定时读写iic,不会报错了。

标签:do,detect,thcvxxx,timer,Linux,驱动,定时,poll,sensor
From: https://www.cnblogs.com/f1engmin11/p/18399553

相关文章

  • 首发 最新AWVS/Acunetix Premium V24.8高级版漏洞扫描器(最新版)Windows/Linux下载
    前言AcunetixPremium是一种Web应用程序安全解决方案,用于管理多个网站、Web应用程序和API的安全。集成功能允许您自动化DevOps和问题管理基础架构。AcunetixPremium:全面的Web应用程序安全解决方案Web应用程序对于企业和组织与客户、合作伙伴和员工的联系至关重要。......
  • linux curl命令介绍以及使用
    文章目录`curl`简介`curl`的安装基本用法发送GET请求将响应内容保存到文件显示请求的头部信息发送POST请求上传文件携带请求头处理重定向通过代理发送请求下载文件指定请求的超时时间高级用法模拟浏览器行为保持会话(Cookie)验证HTTPS请求总结在Linux中,curl是一个......
  • 硬件-常用驱动电路设计
    文章目录一:技术理论1.1驱动电路定义1.2低端驱动与高端驱动二:OC门与OD门2.1OC门(opencollect)2.2OD门(opendrain)2.3应用说明2.4阅读手册(达林顿管ULN2003A)三:推挽输出3.1定义3.2STM32单片机的GPIO口3.3图腾柱驱动电路四:半桥4.1定义4.2应用4.3阅读手册五:全......
  • 系统设计思想之Domain驱动
    一、DDD从放弃到入门   希望了解一套微服务框架的;希望学习到新技术的;开发的系统不复杂,模块少而独立的;当前自己设计的架构已满足拓展性,可复用性,技术与业务复杂度已分离的;   这几类人群不是DDD的目标人群,建议尽早放弃,学习领域驱动设计能得到的收获概括起来大致如下:  ......
  • Docker - 在Rockly Linux 9.4 上安装Docker-CE
    安装Docker-CE修改repo源修改为国内阿里源以提高安装速度sed-e's|^mirrorlist=|#mirrorlist=|g'\-e's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g'\-i.bak\/etc/yum.repos.d/rocky*.repo......
  • C++入门项目:Linux下C++轻量级Web服务器 跑通|运行|测试(小白进)
    TinyWebServer是一个开源的项目,适合小白入门C++网络编程,注意该项目是在linux系统下。Linux下C++轻量级Web服务器,助力初学者快速实践网络编程,搭建属于自己的服务器.使用线程池+非阻塞socket+epoll(ET和LT均实现)+事件处理(Reactor和Proactor均实现)的并发模型使用状......
  • Linux 系统的操作命令
    Author:ACatSmilingSince:2024-09-05文件与目录结构Linux系统中,一切皆文件。Linux目录结构:[zeloud@localhost~]$cd/[zeloud@localhost/]$lsbinbootdevetchomeliblib64mediamntoptprocrootrunsbinsrvsystmpusrvar/bin:存......
  • Linux-目录结构和Vim编辑器
    目录Linux目录结构基本介绍​编辑具体的目录结构Vim编辑器vi和vim的基本介绍vi和vim常用的三种模式正常模式插入模式命令行模式各种模式的相互切换vim快捷键盘图粘贴与删除拷贝当前行并粘贴拷贝多行并粘贴删除当前行删除多行Vim的退出保存命令普通退出保存......
  • 《 Kali Linux 安装的具体步骤》
    以下是KaliLinux安装的具体步骤: 准备工作: 1. 下载KaliLinux镜像:从官方网站(https://www.kali.org/downloads/)下载适合您的版本(如64位)的ISO镜像文件。2. 准备安装介质:您可以选择将镜像写入U盘(使用Rufus等工具)或者刻录到DVD光盘。3. 备份重要数据:安装......
  • 【操作系统存储篇】Linux文件基本操作
    目录一、Linux目录二、Linux文件的常用操作三、Linux文件类型一、Linux目录Linux有很多目录,Linux一切皆是文件,包括进程、设备等。相对路径:相对于当前的操作目录,文件位于哪个目录。绝对路径:从根目录开始的路径。二、Linux文件的常用操作touch:创建文件; vim:创建或......