嵌入式开发记录-day45 pinctrl子系统配置管脚为输入
1、 硬件部分
使用开发板上的home(gpx1 1)按键,作为GPIO的输入。按下低电平,默认高电平
2、设备树修改
屏蔽掉其它代码对gpx1 1的引用,在前面几节设备树的基础上,添加设备树注册部分
itop_gpio_in { compatible = "gpio_in"; status = "okay"; gpioin = <&gpx1 1 0>; };
3、驱动代码
#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/miscdevice.h> #include <linux/fs.h> #define DRIVER_NAME "gpio_in" int gpio_pin = 0; int gpio_open(struct inode *inode,struct file *filp) { printk("Device Opened Success!\n"); return nonseekable_open(inode,filp); } int gpio_release(struct inode *inode,struct file *filp) { printk("Device Closed Success!\n"); return 0; } long gpio_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) { printk("debug: gpio_ioctl cmd is %d,arg is %d\n" , cmd,arg); switch(cmd) { case 0: case 1: return gpio_get_value(gpio_pin); // 获取管脚电平值 break; default: return -EINVAL; } return 0; } static struct file_operations gpio_ops = { .owner = THIS_MODULE, .open = gpio_open, .release= gpio_release, .unlocked_ioctl = gpio_ioctl, }; static struct miscdevice gpio_dev = { .minor = MISC_DYNAMIC_MINOR, .fops = &gpio_ops, .name = DRIVER_NAME, }; static int gpio_probe(struct platform_device * pdev) { struct device_node *node = pdev->dev.of_node; int ret,value; printk("gpio init\n"); // 获取管脚编号 gpio_pin = of_get_named_gpio(node, "gpioin", 0); if (gpio_pin < 0) printk("gpio_pin is not available \n"); // 根据管脚编号申请空间 ret = gpio_request(gpio_pin, "gpio-in"); if(ret!=0){ printk("gpio_pin request %d faigpio.", gpio_pin); return ret; } printk("gpio_pin is %d\n",gpio_pin); // 释放管脚 gpio_free(gpio_pin); // 配置为直接输入 gpio_direction_input(gpio_pin); // 获取管脚电平 value = gpio_get_value(gpio_pin); printk("the value is %d\n",value); // 杂项设备注册 ret = misc_register(&gpio_dev); if(ret<0){ printk("gpio:register device faigpio!\n"); goto exit; } return 0; exit: misc_deregister(&gpio_dev); return ret; } static int gpio_remove(struct platform_device * pdev) { printk(KERN_ALERT "Goodbye, curel world, this is remove\n"); misc_deregister(&gpio_dev); return 0; } static const struct of_device_id of_gpio_dt_match[] = { {.compatible = DRIVER_NAME}, {}, }; MODULE_DEVICE_TABLE(of,of_gpio_dt_match); static struct platform_driver gpio_driver = { .probe = gpio_probe, .remove = gpio_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = of_gpio_dt_match, }, }; static int gpio_init(void) { printk(KERN_ALERT "Hello, world\n"); return platform_driver_register(&gpio_driver); return 0; } static void gpio_exit(void) { printk(KERN_ALERT "Goodbye, curel world\n"); platform_driver_unregister(&gpio_driver); } module_init(gpio_init); module_exit(gpio_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("rty"); MODULE_DESCRIPTION("topeet4412_regiter_dev_drv");
4、应用代码
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc,char **argv) { int fd; if(argc!=2){ printf("arvc is 2:\nargv1 is device_node\n"); } if((fd = open(argv[1], O_RDWR|O_NOCTTY|O_NDELAY))<0){ printf("open %s failed\n",argv[1]); return -1; } else{ printf("open %s ok\n",argv[1]); printf("key value is %d\n",ioctl(fd,0,0)); } close(fd); return 0; }
5、待测试
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java线程池详解:高效并发编程的核心利器
· 从“看懂世界”到“改造世界”:AI发展的四个阶段你了解了吗?
· 协程本质是函数加状态机——零基础深入浅出 C++20 协程
· 编码之道,道心破碎。
· 记一次 .NET 某发证机系统 崩溃分析
· dotnetty 新的篇章- 开源
· DotTrace系列:1. 理解四大经典的诊断类型(上)
· 【大数据高并发核心场景实战】 - 数据持久化之冷热分离
· 这5种规则引擎,真香!
· 如何用大语言模型提取任意文档中的知识点