014——超声波模块驱动开发Plus(基于I.MX6uLL、SR04和poll机制)

目录

一、基础知识

二、分析为什么打印会影响中断 

三、驱动程序

四、应用程序

五、验证及其它


一、基础知识

013——超声波模块驱动开发(基于I.MX6uLL与SR04)-CSDN博客

二、分析为什么打印会影响中断 

 

asmlinkage __visible int printk(const char *fmt, ...)  
{  va_list args;  int r;  // 初始化可变参数列表  va_start(args, fmt);  // 调用 vprintk_func 函数来格式化字符串并输出到内核日志  r = vprintk_func(fmt, args);  // 清理可变参数列表  va_end(args);  // 返回 vprintk_func 的结果  return r;  
}  EXPORT_SYMBOL(printk);

我们一层一层往下找找到了这个

        这是一个保护中断的自旋锁,这里上锁后其它需要用中断的进程就无法使用了。

        所以当超声波模块中断触发后我们没有接收到。这就是为什么打印会影响中断的原因,这里相当于32库函数里面关闭全局中断的那个操作,实现虽然不一样但是作用是一样的。

三、驱动程序

#include "asm-generic/errno.h"
#include "asm-generic/gpio.h"
#include "asm/delay.h"
#include "linux/jiffies.h"
#include <linux/module.h>
#include <linux/poll.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>#define CMD_TRIG  100struct gpio_desc{int gpio;int irq;char *name;int key;struct timer_list key_timer;
} ;static struct gpio_desc gpios[2] = {{115, 0, "trig", },{116, 0, "echo", },
};/* 主设备号                                                                 */
static int major = 0;
static struct class *gpio_class;/* 环形缓冲区 */
#define BUF_LEN 128
static int g_keys[BUF_LEN];
static int r, w;struct fasync_struct *button_fasync;#define NEXT_POS(x) ((x+1) % BUF_LEN)static int is_key_buf_empty(void)
{return (r == w);
}static int is_key_buf_full(void)
{return (r == NEXT_POS(w));
}static void put_key(int key)
{if (!is_key_buf_full()){g_keys[w] = key;w = NEXT_POS(w);}
}static int get_key(void)
{int key = 0;if (!is_key_buf_empty()){key = g_keys[r];r = NEXT_POS(r);}return key;
}static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);/* 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t sr04_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);int err;int key;if (is_key_buf_empty() && (file->f_flags & O_NONBLOCK))return -EAGAIN;// printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);wait_event_interruptible(gpio_wait, !is_key_buf_empty());key = get_key();if (key == -1)return -ENODATA;err = copy_to_user(buf, &key, 4);return 4;
}static unsigned int sr04_poll(struct file *fp, poll_table * wait)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);poll_wait(fp, &gpio_wait, wait);return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;
}static int sr04_fasync(int fd, struct file *file, int on)
{if (fasync_helper(fd, file, on, &button_fasync) >= 0)return 0;elsereturn -EIO;
}// ioctl(fd, CMD, ARG)
static long sr04_ioctl(struct file *filp, unsigned int command, unsigned long arg)
{// send trig switch (command){case CMD_TRIG:{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);gpio_set_value(gpios[0].gpio, 1);udelay(20);gpio_set_value(gpios[0].gpio, 0);// start timermod_timer(&gpios[1].key_timer, jiffies + msecs_to_jiffies(50));  }}return 0;
}/* 定义自己的file_operations结构体                                              */
static struct file_operations sr04_drv = {.owner	 = THIS_MODULE,.read    = sr04_read,.poll    = sr04_poll,.fasync  = sr04_fasync,.unlocked_ioctl = sr04_ioctl,
};static irqreturn_t sr04_isr(int irq, void *dev_id)
{struct gpio_desc *gpio_desc = dev_id;int val;static u64 rising_time = 0;u64 time;val = gpio_get_value(gpio_desc->gpio);//printk("sr04_isr echo pin %d is %d\n", gpio_desc->gpio, val);if (val){/* 上升沿记录起始时间 */rising_time = ktime_get_ns();}else{if (rising_time == 0){//printk("missing rising interrupt\n");return IRQ_HANDLED;}/* 下降沿记录结束时间, 并计算时间差, 计算距离 */// stop timerdel_timer(&gpios[1].key_timer);time = ktime_get_ns() - rising_time;rising_time = 0;put_key(time);wake_up_interruptible(&gpio_wait);kill_fasync(&button_fasync, SIGIO, POLL_IN);}return IRQ_HANDLED;
}static void sr04_timer_func(unsigned long data)
{put_key(-1);wake_up_interruptible(&gpio_wait);kill_fasync(&button_fasync, SIGIO, POLL_IN);
}/* 在入口函数 */
static int __init sr04_init(void)
{int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);// trig pinerr = gpio_request(gpios[0].gpio, gpios[0].name);gpio_direction_output(gpios[0].gpio, 0);// echo pin{		gpios[1].irq  = gpio_to_irq(gpios[1].gpio);err = request_irq(gpios[1].irq, sr04_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, gpios[1].name, &gpios[1]);setup_timer(&gpios[1].key_timer, sr04_timer_func, (unsigned long)&gpios[1]);}/* 注册file_operations 	*/major = register_chrdev(0, "100ask_sr04", &sr04_drv);  /* /dev/gpio_desc */gpio_class = class_create(THIS_MODULE, "100ask_sr04_class");if (IS_ERR(gpio_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "100ask_sr04");return PTR_ERR(gpio_class);}device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "sr04"); /* /dev/sr04 */return err;
}/* 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数*/
static void __exit sr04_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(gpio_class, MKDEV(major, 0));class_destroy(gpio_class);unregister_chrdev(major, "100ask_sr04");// trig pingpio_free(gpios[0].gpio);// echo pin{free_irq(gpios[1].irq, &gpios[1]);del_timer(&gpios[1].key_timer);}
}/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */module_init(sr04_init);
module_exit(sr04_exit);MODULE_LICENSE("GPL");

四、应用程序

加入poll机制查询是不是有数据


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <sys/ioctl.h>#define CMD_TRIG  100static int fd;/** ./button_test /dev/sr04**/
int main(int argc, char **argv)
{int val;struct pollfd fds[1];int timeout_ms = 5000;int ret;int	flags;int i;/* 1. 判断参数 */if (argc != 2) {printf("Usage: %s <dev>\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}while (1){ioctl(fd, CMD_TRIG);printf("I am goning to read distance: \n");fds[0].fd = fd;fds[0].events = POLLIN;if (1 == poll(fds, 1, 5000)){if (read(fd, &val, 4) == 4)printf("get distance: %d cm\n", val*17/1000000);elseprintf("get distance err\n");}else{printf("get distance poll timeout/err\n");}sleep(1);}close(fd);return 0;
}

五、验证及其它

我们现在用的4.9.88版本用setup_timer

新的5.几的内核使用timer_setup

key_timer_expire函数的参数也不一样,4点几是long,5点几是把结构体传入。

现象和上次一样

013——超声波模块驱动开发(基于I.MX6uLL与SR04)-CSDN博客

 

这个数据后面需要处理一下不然太不稳定了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/589397.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Chatgpt掘金之旅—有爱AI商业实战篇|聊天机器人|(四)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 聊天机器人企业知识库&#xff1a;https://work.jingyuai.com/ 鲸鱼AI知识库 官方论坛&#xff1a; www.jingyuai.com 京娱AI 聊天机器人创建服务&#xff0c;随着企业越来越多地寻求创新的方式与客户互动&#xff0c;聊天机…

Linux部分命令

目录 1.文件介绍 2.ls命令 3.目录命令 4.相对路径以及绝对路径 5.命令创建目录&#xff08;文件夹&#xff09; 6.which命令 7.find命令 8.grep命令 9.wc命令 10.echo、tail、重定向符 1.文件介绍 和window不同&#xff0c;Linux没有盘路径&#xff0c;所有的文件都存…

家用洗地机选购指南,哪款洗地机性价比高且用户评价好?

在当今快节奏的生活中&#xff0c;无论是商业场所还是家庭&#xff0c;清洁环境都是我们追求的目标之一。而一台高性价比的洗地机在频繁清洁地面时尤为重要。市面上的洗地机种类繁多&#xff0c;如何选择适合自己的洗地机成为了一个挑战。那么&#xff0c;到底哪款牌子的洗地机…

Intel TBB安装​​​​

下载 windows 版本&#xff0c;如: oneapi-tbb-2021.11.0-win.zip Releases oneapi-src/oneTBB (github.com)https://github.com/oneapi-src/oneTBB/releases 下载后解压&#xff0c;执行 env 文件夹下的 vars.bat 即可 Intel TBB&#xff0c;全称Intel Threading Building…

LLM大模型可视化-以nano-gpt为例

内容整理自&#xff1a;LLM 可视化 --- LLM Visualization (bbycroft.net)https://bbycroft.net/llm Introduction 介绍 Welcome to the walkthrough of the GPT large language model! Here well explore the model nano-gpt, with a mere 85,000 parameters. 欢迎来到 GPT 大…

【Jenkins】关于账号,证书验证的设置问题

当你的电脑启动了Jenkins&#xff0c;这时候一定要小心更改管理员账号和密码~~~ 当你的电脑启动了Jenkins&#xff0c;这时候一定要小心更改管理员账号和密码~~~ 当你的电脑启动了Jenkins&#xff0c;这时候一定要小心更改管理员账号和密码~~~ 重要的事情说3遍&#xff0c;如…

Redis高可用及持久化

文章目录 一、Redis高可用1、Redis高可用概述2、Redis高可用策略 二、Redis持久化1、Redis持久化的功能2、Redis持久化的两种方式2.1 RDB持久化2.2 AOF持久化&#xff08;append only file&#xff09; 3、RDB持久化3.1 触发条件3.1.1 手动触发3.1.2 自动触发3.1.2.1 配置方式3…

【数据结构与算法篇】动态顺序表实战项目:通讯录

【数据结构与算法】动态顺序表实战项目&#xff1a;通讯录 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;数据结构与算法&#x1f345; 目录 【数据结构与算法】动态顺序表实战项目&#xff1a;通讯录 ​编辑 1. PerInfo.h 头文件…

搭建电商网站外贸网站用API接口可以实现哪些功能(天猫API接口|京东API接口)

在电商领域&#xff0c;API接口可以实现多种功能&#xff0c;起到连接内外部系统及优化电商业务流程等多种作用&#xff0c;从而来提高电商企业的运营效率。 具体来看&#xff0c;API接口接入可以用来&#xff1a; 商品管理&#xff1a; API接口能够用来获取商品详情等&#…

收下这份地表最强参会指南,4月16日,玩转百度Create大会不迷路

欢迎来到英杰社区&#xff1a; https://bbs.csdn.net/topics/617804998 欢迎来到阿Q社区&#xff1a; https://bbs.csdn.net/topics/617897397 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff…

如何处理Flutter内存泄漏检测和优化

处理Flutter内存泄漏问题是构建高性能、稳定的应用程序的关键部分之一。在本文中&#xff0c;我将详细介绍如何检测和优化Flutter内存泄漏问题&#xff0c;以确保应用程序的良好性能和用户体验。 1. 了解内存泄漏 在深入了解如何处理Flutter内存泄漏之前&#xff0c;首先需要了…

Lambda表达式,Stream流

文章目录 Lambda表达式作用前提函数式接口特点 语法省略模式和匿名对象类的区别 Stream流思想作用三类方法获取方法单列集合(Collection[List,Set双列集合Map(不能直接获取)数组同一类型元素(Stream中的静态方法) 常见的中间方法终结方法收集方法 Optional类 Lambda表达式 作用…