蚂蚁S9矿板PS 轮询实现非阻塞IO驱动
参考蚂蚁S9矿板引脚定义.csdn设备树system-user.dtsi#include dt-bindings/gpio/gpio.h#include dt-bindings/input/input.h#include dt-bindings/media/xilinx-vip.h#include dt-bindings/phy/phy.h#include dt-bindings/interrupt-controller/irq.h/{modelz7 Board ant 789;compatiblexlnx,zynq-zc702,xlnx,zynq-7000;chosen{bootargsconsolettyPS0,115200 earlyconcdns,mmio,0xe0000000,115200n8 keep_bootcon earlyprintk root/dev/mmcblk0p2 rw rootwait;stdout-pathserial0:115200n8;};led{compatibleming,led;statusokay;default-stateon;led-gpiogpio037GPIO_ACTIVE_HIGH;};beeper{compatibleming,beeper;statusokay;default-stateoff;beeper-gpiogpio038GPIO_ACTIVE_HIGH;};key{compatibleming,key;statusokay;key-gpiogpio047GPIO_ACTIVE_LOW;interrupt-parentgpio0;interrupts47IRQ_TYPE_EDGE_BOTH;};};驱动 noblockio.c#includelinux/types.h#includelinux/kernel.h#includelinux/delay.h#includelinux/ide.h#includelinux/init.h#includelinux/module.h#includelinux/errno.h#includelinux/gpio.h#includeasm/mach/map.h#includeasm/uaccess.h#includeasm/io.h#includelinux/cdev.h#includelinux/of.h#includelinux/of_address.h#includelinux/of_gpio.h#includelinux/of_irq.h#includelinux/irq.h#includelinux/poll.h#defineKEY_CNT1/* 设备号个数 */#defineKEY_NAMEkey/* 名字 *//* 定义按键状态 */enumkey_status{KEY_PRESS0,// 按键按下KEY_RELEASE,// 按键松开KEY_KEEP,// 按键状态保持};/* 按键设备结构体 */structkey_dev{dev_tdevid;/* 设备号 */structcdevcdev;/* cdev结构体 */structclass*class;/* 类 */structdevice*device;/* 设备 */intkey_gpio;/* GPIO编号 */intirq_num;/* 中断号 */structtimer_listtimer;/* 定时器 */wait_queue_head_tr_wait;/* 读等待队列头 */};staticstructkey_devkey;/* 按键设备 */staticatomic_tstatus;/* 按键状态 *//* * description : 打开设备 * param – inode : 传递给驱动的inode * param – filp : 设备文件file结构体有个叫做private_data的成员变量 * 一般在open的时候将private_data指向设备结构体。 * return : 0 成功;其他 失败 */staticintkey_open(structinode*inode,structfile*filp){return0;}/* * description : 从设备读取数据 * param – filp : 要打开的设备文件(文件描述符) * param – buf : 返回给用户空间的数据缓冲区 * param – cnt : 要读取的数据长度 * param – offt : 相对于文件首地址的偏移 * return : 读取的字节数如果为负值表示读取失败 */staticssize_tkey_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt){intret;if(filp-f_flagsO_NONBLOCK){//非阻塞方式访问if(KEY_KEEPatomic_read(status))return-EAGAIN;}else{//阻塞式访问/* 加入等待队列当有按键按下或者松开动作发生时才会被唤醒 */retwait_event_interruptible(key.r_wait,KEY_KEEP!atomic_read(status));if(ret)returnret;}/* 将按键状态信息发送给应用程序 */retcopy_to_user(buf,status,sizeof(int));/* 状态重置 */atomic_set(status,KEY_KEEP);returnret;}/* * description : poll函数用于处理非阻塞访问 * param – filp : 要打开的设备文件(文件描述符) * param – wait : 等待列表poll_table * return : 设备或者资源状态 */staticunsignedintkey_poll(structfile*filp,structpoll_table_struct*wait){unsignedintmask0;poll_wait(filp,key.r_wait,wait);if(KEY_KEEP!atomic_read(status))//按键按下或松开动作发生maskPOLLIN|POLLRDNORM;//返回POLLINreturnmask;}/* * description : 向设备写数据 * param – filp : 设备文件表示打开的文件描述符 * param – buf : 要写给设备写入的数据 * param – cnt : 要写入的数据长度 * param – offt : 相对于文件首地址的偏移 * return : 写入的字节数如果为负值表示写入失败 */staticssize_tkey_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt){return0;}/* * description : 关闭/释放设备 * param – filp : 要关闭的设备文件(文件描述符) * return : 0 成功;其他 失败 */staticintkey_release(structinode*inode,structfile*filp){return0;}staticvoidkey_timer_function(structtimer_list*unused){staticintlast_val1;intcurrent_val;/* 读取按键值并判断按键当前状态 */current_valgpio_get_value(key.key_gpio);if(0current_vallast_val){// 按下atomic_set(status,KEY_PRESS);wake_up_interruptible(key.r_wait);//唤醒r_wait队列头中的所有队列}elseif(1current_val!last_val){atomic_set(status,KEY_RELEASE);// 松开wake_up_interruptible(key.r_wait);//唤醒r_wait队列头中的所有队列}elseatomic_set(status,KEY_KEEP);// 状态保持last_valcurrent_val;}staticirqreturn_tkey_interrupt(intirq,void*dev_id){/* 按键防抖处理开启定时器延时15ms */mod_timer(key.timer,jiffiesmsecs_to_jiffies(15));returnIRQ_HANDLED;}staticintkey_parse_dt(void){structdevice_node*nd;constchar*str;intret;/* 获取key节点 */ndof_find_node_by_path(/key);if(NULLnd){printk(KERN_ERRkey: Failed to get key node\n);return-EINVAL;}/* 读取status属性 */retof_property_read_string(nd,status,str);if(!ret){if(strcmp(str,okay))return-EINVAL;}/* 获取compatible属性值并进行匹配 */retof_property_read_string(nd,compatible,str);if(ret)returnret;if(strcmp(str,ming,key)){printk(KERN_ERRkey: Compatible match failed\n);return-EINVAL;}/* 获取设备树中的key-gpio属性得到按键的GPIO编号 */key.key_gpioof_get_named_gpio(nd,key-gpio,0);if(!gpio_is_valid(key.key_gpio)){printk(KERN_ERRkey: Failed to get key-gpio\n);return-EINVAL;}/* 获取GPIO对应的中断号 */key.irq_numirq_of_parse_and_map(nd,0);if(!key.irq_num)return-EINVAL;return0;}staticintkey_gpio_init(void){unsignedlongirq_flags;intret;/* 申请使用GPIO */retgpio_request(key.key_gpio,Key Gpio);if(ret)returnret;/* 将GPIO设置为输入模式 */gpio_direction_input(key.key_gpio);/* 获取设备树中指定的中断触发类型 */irq_flagsirq_get_trigger_type(key.irq_num);if(IRQF_TRIGGER_NONEirq_flags)irq_flagsIRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING;/* 申请中断 */retrequest_irq(key.irq_num,key_interrupt,irq_flags,PS Key0 IRQ,NULL);if(ret){gpio_free(key.key_gpio);returnret;}return0;}/* 设备操作函数 */staticstructfile_operationskey_fops{.ownerTHIS_MODULE,.openkey_open,.readkey_read,.writekey_write,.releasekey_release,.pollkey_poll,};staticint__initmykey_init(void){intret;/* 初始化等待队列头 */init_waitqueue_head(key.r_wait);/* 初始化按键状态 */atomic_set(status,KEY_KEEP);/* 设备树解析 */retkey_parse_dt();if(ret)returnret;/* GPIO、中断初始化 */retkey_gpio_init();if(ret)returnret;/* 初始化cdev */key.cdev.ownerTHIS_MODULE;cdev_init(key.cdev,key_fops);/* 添加cdev */retalloc_chrdev_region(key.devid,0,KEY_CNT,KEY_NAME);if(ret)gotoout1;retcdev_add(key.cdev,key.devid,KEY_CNT);if(ret)gotoout2;/* 创建类 */key.classclass_create(THIS_MODULE,KEY_NAME);if(IS_ERR(key.class)){retPTR_ERR(key.class);gotoout3;}/* 创建设备 */key.devicedevice_create(key.class,NULL,key.devid,NULL,KEY_NAME);if(IS_ERR(key.device)){retPTR_ERR(key.device);gotoout4;}/* 初始化定时器 */timer_setup(key.timer,key_timer_function,0);return0;out4:class_destroy(key.class);out3:cdev_del(key.cdev);out2:unregister_chrdev_region(key.devid,KEY_CNT);out1:free_irq(key.irq_num,NULL);gpio_free(key.key_gpio);returnret;}staticvoid__exitmykey_exit(void){/* 删除定时器 */del_timer_sync(key.timer);/* 注销设备 */device_destroy(key.class,key.devid);/* 注销类 */class_destroy(key.class);/* 删除cdev */cdev_del(key.cdev);/* 注销设备号 */unregister_chrdev_region(key.devid,KEY_CNT);/* 释放中断 */free_irq(key.irq_num,NULL);/* 释放GPIO */gpio_free(key.key_gpio);}/* 驱动模块入口和出口函数注册 */module_init(mykey_init);module_exit(mykey_exit);MODULE_AUTHOR(DengTao 773904075qq.com);MODULE_DESCRIPTION(Gpio Key Interrupt Driver);MODULE_LICENSE(GPL);keyApp.c#includestdio.h#includeunistd.h#includesys/types.h#includesys/stat.h#includefcntl.h#includestdlib.h#includestring.h#includepoll.h/* * description : main主程序 * param – argc : argv数组元素个数 * param – argv : 具体参数 * return : 0 成功;其他 失败 */intmain(intargc,char*argv[]){fd_set readfds;intfd,ret;intkey_val;/* 判断传参个数是否正确 */if(2!argc){printf(Usage:\n\t./keyApp /dev/key\n);return-1;}/* 打开设备 */fdopen(argv[1],O_RDONLY|O_NONBLOCK);if(0fd){printf(ERROR: %s file open failed!\n,argv[1]);return-1;}FD_ZERO(readfds);FD_SET(fd,readfds);/* 循环轮询读取按键数据 */for(;;){retselect(fd1,readfds,NULL,NULL,NULL);switch(ret){case0://超时/*用户自定义超时处理*/break;case-1://错误/*用户自定义错误处理*/break;default:if(FD_ISSET(fd,readfds)){read(fd,key_val,sizeof(int));if(key_val0)printf(Key Press\n);elseif(key_val1)printf(Key Release\n);}break;}}/* 关闭设备 */close(fd);return0;}编译驱动和app$CC-okeyApp keyApp.c测试rootant:~# insmod noblockio.koinsmod: can not insert noblockio.ko: Device or resource busy rootant:~# rmmod blockio.kormmod: cant unload module blockio: Resource temporarily unavailable rootant:~# kill -9 495rootant:~# rmmod blockiorootant:~# insmod noblockio.korootant:~# chmod 777 keyApprootant:~# ./keyApp /dev/keyKey Press Key Release rootant:~# rmmod noblockiorootant:~# ls /dev/keyls: /dev/key: No suchfileor directory

相关新闻

铜徽章制作全流程指南:从雕刻到电镀的DIY手工教程

铜徽章制作全流程指南:从雕刻到电镀的DIY手工教程

这次我们来看一个关于铜徽章制作的项目,特别适合喜欢手工制作的女孩子。铜徽章制作不仅是一种创意表达方式,还能锻炼动手能力,而且门槛不高,适合初学者尝试。本文将详细介绍铜徽章制作的全流程,从材料准备到成品抛光&a…

2026/7/30 2:15:36 阅读更多 →
8 月技术阅读清单:值得精读的论文、博客与开源项目

8 月技术阅读清单:值得精读的论文、博客与开源项目

8 月技术阅读清单:值得精读的论文、博客与开源项目 一、深度引言与场景痛点:在网上刷了 100 篇技术文章,真正有收获的不到 10 篇 7 月的数据:我在各种技术平台上阅读了约 120 篇文章。但到月底复盘时,能清晰回忆出内…

2026/7/30 2:15:36 阅读更多 →
终极指南:5分钟免费获取B站直播推流码,轻松使用OBS专业直播

终极指南:5分钟免费获取B站直播推流码,轻松使用OBS专业直播

终极指南:5分钟免费获取B站直播推流码,轻松使用OBS专业直播 【免费下载链接】bilibili_live_stream_code 获取B站直播推流码,支持开关播,管理直播标题、分区,显示弹幕和礼物。 项目地址: https://gitcode.com/gh_mir…

2026/7/30 2:14:36 阅读更多 →

最新新闻

电子系统设计实战:从硬件到Windows客户端软件开发全流程解析

电子系统设计实战:从硬件到Windows客户端软件开发全流程解析

1. 项目概述:从电路板到智能终端做电子系统设计,尤其是嵌入式开发,很多人会把重心放在硬件上——画原理图、PCB布局、焊接调试,觉得软件不过是“最后写几行代码”的事。但真正踩过坑的工程师都明白,一个电子系统的成败…

2026/7/30 2:26:38 阅读更多 →
Unity VFX Graph核心技巧:从节点操作到GPU特效优化实战

Unity VFX Graph核心技巧:从节点操作到GPU特效优化实战

1. 项目概述:为什么VFX Graph是Unity特效的“工业革命”? 如果你还在用传统的Particle System(粒子系统)一个模块一个模块地调参数,看着满屏的粒子却难以实现精细的、数据驱动的复杂效果,那VFX Graph的出现…

2026/7/30 2:26:38 阅读更多 →
深入Linux内核:gpio-leds驱动与heartbeat心跳灯实现机制解析

深入Linux内核:gpio-leds驱动与heartbeat心跳灯实现机制解析

1. 项目概述:从闪烁的服务器到嵌入式设备的心跳如果你曾经维护过服务器,或者捣鼓过树莓派、香橙派这类开发板,你大概率见过那个在黑暗中规律闪烁的绿色或红色小灯。它不是故障告警,而是一种无声的“健康宣言”——这就是心跳灯。在…

2026/7/30 2:26:38 阅读更多 →
LLaMa-Factory大模型微调实战:从硬件选型到部署优化

LLaMa-Factory大模型微调实战:从硬件选型到部署优化

1. 项目概述LLaMa-Factory作为当前开源大模型微调领域的热门工具,正在改变我们处理NLP任务的方式。这个项目本质上是一个模块化的大模型微调框架,它让普通开发者也能在消费级硬件上高效完成大语言模型的定制化训练。我在实际工作中发现,很多团…

2026/7/30 2:26:38 阅读更多 →
2026 年AI财税软件推荐:财税一体化适配金税四期,集团集中管控靠谱安全

2026 年AI财税软件推荐:财税一体化适配金税四期,集团集中管控靠谱安全

2026 年AI财税软件推荐:财税一体化适配金税四期,集团集中管控靠谱安全开篇:2026 年集团财税的双重命题 —— 金税四期合规与集中管控效率2026 年金税四期进入全面深化阶段,“以数治税” 监管体系实现全量数据联动稽核,…

2026/7/30 2:26:38 阅读更多 →
治愈系设计趋势:数据驱动的个性化与无障碍的融合

治愈系设计趋势:数据驱动的个性化与无障碍的融合

治愈系设计趋势:数据驱动的个性化与无障碍的融合 一、治愈系设计的演进瓶颈:千篇一律的"温暖" 当前治愈系UI陷入了一个同质化困境——暖色背景、大圆角卡片、柔和的阴影过渡。这些元素在100个治愈系产品中反复出现,用户已经产生了…

2026/7/30 2:25:38 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻