imx6ull设备树驱动--pinctl、ioctl

添加pinctl节点

进入arch/arm/boot/dts目录下dts文件

在iomuxc下添加pinctl+led节点

将 GPIO1_IO03 这个 PIN 复用为 GPIO1_IO03,电气属性(配置GPIO一些列寄存器)值为 0X10B0

添加led设备节点

与上一节一样,在 / 下面添加设备节点

pinctrl-0 属性设置 LED 灯所使用的 PIN 对应的 pinctrl 节点。
led-gpio 属性指定了 LED 灯所使用的 GPIO,在这里就是 GPIO1 的 IO03,低电平
有效。
 

检查IO有没有被其他外设占用

一个引脚一次只能实现一个功能,否则的话驱动程序在申请 GPIO 的时候就会失败。
搜索GPIO1_IO03,发现被tsc这个外设占用了,我们没用到这个外设,直接把他注释了

除了pinctl的占用,还有设备IO的占用

除了我们使用到的,找到一个注释一个,暂时只有这两个

编译复制

设备树文件就修改好了

驱动代码

gpioled.c

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define GPIOLED_CNT      1        //device number
#define GPIOLED_NAME     "gpioled" //device name//gpioled设备结构体
struct gpioled_dev{dev_t devid;                //设备号struct cdev cdev;           //CDEVstruct class *class;        //类struct device *device;      //设备int major;                  //主设备号int minor;                  //次设备号struct device_node *nd;     //设备节点int led_gpio;   //          //led使用的GPIO编号
};struct gpioled_dev gpioled;       //设备static int led_open(struct inode *inode, struct file *filp)
{filp->private_data = &gpioled;   //设置私有数据return 0;
}static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{int ret;unsigned char databuf[1];unsigned char ledstat;struct gpioled_dev *dev = filp->private_data;ret = copy_from_user(databuf, buf, cnt);if(ret < 0){printk("kernel copy_from_user failed: %d\n", ret);return -EFAULT;}ledstat = databuf[0];if(1 == ledstat)            //开{gpio_set_value(dev->led_gpio, 0);}else if(0 == databuf[0])    //关{gpio_set_value(dev->led_gpio, 1);}return 0;
}static int led_close(struct inode *inode, struct file *file)
{return 0;
}static struct file_operations gpioled_fops = {.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release = led_close,
};static int __init led_init(void)
{int ret;gpioled.nd = of_find_node_by_path("/gpioled");  //通过路径查找指定节点,返回节点if(gpioled.nd == NULL){printk("find_node_by_path failed\n");return -EINVAL;}printk("gpioled node has been found\n");/* 2、 获取设备树中的 gpio 属性,得到 LED 所使用的 LED 编号 */gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0);if(gpioled.led_gpio < 0) {printk("can't get led-gpio");return -EINVAL;}printk("led-gpio num = %d\r\n", gpioled.led_gpio);/* 3、设置 GPIO1_IO03 为输出,并且输出高电平,默认关闭 LED 灯 */ret = gpio_direction_output(gpioled.led_gpio, 1);if(ret < 0) {printk("can't set gpio!\r\n");}/* 注册字符设备驱动 */if(gpioled.major)                            //如果定义了设备号用它{gpioled.devid = MKDEV(gpioled.major, 0);register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME);}else                                        //没定义设备号,自动创建{alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);gpioled.major = MAJOR(gpioled.devid);gpioled.minor = MINOR(gpioled.devid);}printk("gpioled major = %d minor = %d\n", gpioled.major, gpioled.minor);  //打印主次设备号gpioled.cdev.owner = THIS_MODULE;                //初始化cdevcdev_init(&gpioled.cdev, &gpioled_fops);cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);  //添加cdevgpioled.class = class_create(THIS_MODULE, GPIOLED_NAME);  //创建类if(IS_ERR(gpioled.class)){return PTR_ERR(gpioled.class);}gpioled.device = device_create(gpioled.class, NULL, gpioled.devid, NULL, GPIOLED_NAME);//创建设备if(IS_ERR(gpioled.device)){return PTR_ERR(gpioled.device);}return 0;
}static void __exit led_exit(void)
{cdev_del(&gpioled.cdev);unregister_chrdev_region(gpioled.devid, GPIOLED_CNT);device_destroy(gpioled.class, gpioled.devid);class_destroy(gpioled.class);
}module_init(led_init);
module_exit(led_exit);MODULE_LICENSE("GPL");

用户层代码和上一节一样

编译运行

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

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

相关文章

数电期末复习(四)组合逻辑电路

这里写目录标题 4.1 概述4.2 组合逻辑电路的分析方法4.3 组合逻辑电路的设计方法4.4 若干常用组合逻辑电路4.4.1 编码器&#xff08;encoder&#xff09;4.4.2 译码器(decoder)4.4.3 数据选择器 (data selector)4.3.4 加法器&#xff08;Adder&#xff09;4.4.4 数值比较器&…

kubectl常用命令行介绍

1、kubectl用法概述 kubectl命令⾏的语法如下&#xff1a; $ kubectl [command] [type] [name] [flags] command&#xff1a;命令&#xff0c;用于操作Kubernetes集群资源对象的命令&#xff0c;例如create、delete、describe、get、apply等TYPE&#xff1a;资源对象的类型&am…

OpenHarmony UI开发-ohos-svg

简介 ohos-svg是一个SVG图片的解析器和渲染器&#xff0c;解析SVG图片并渲染到页面上。它支持大部分 SVG 1.1 规范&#xff0c;包括基本形状、路径、文本、样式和渐变,它能够渲染大多数标准的 SVG 图像。ohos-svg的优点是性能好、内存占用低。 效果展示 SVG图片解析并绘制: …

uni-app HBuilderX通过easycom省略import自动导入自定义组件

快速尝试 自HBuilderX 2.5.5起支持easycom组件模式。更新HBuilderX即可尝试。 easycom默认已启用&#xff0c;并对项目下的components和uni_modules目录开启自动扫描&#xff0c;对符合下面路径和命名规则的组件自动导入。 components/组件名/组件名.vue uni_modules/组件名/…

使用飞桨快速部署stable diffusion模型

这可以说是最快的部署stable diffusion模型的方法了&#xff0c;而且星河社区还有免费的GPU算力提供&#xff0c;这样再也不用担心没有算力了&#xff01; 操作方法&#xff1a; # 安装相关库 pip install docarray0.21.0 pip install paddlehub# 初始化 from PIL import Imag…

踊跃参与,您有机会尊享300000水晶奖励!【AI书童】代言形象大投票活动开启~~~

【AI书童】运营官 未来智慧人工智能 2024-04-19 09:55 ✧ 快来选出你心目中的【AI书童】 ✦ 我们想为【AI书童】选择一个形象代言&#xff0c;使用【AI书童】软件生成了一部分形象照片。大家觉得哪个书童最合适呢&#xff1f;希望你们能给出宝贵的建议&#xff01; 【AI书童…

手把手教你实现 OceanBase 数据到 Apache Doris 的便捷迁移|实用指南

作者|SelectDB 技术团队 作为广受认可的分布式数据库&#xff0c;OceanBase 已在众多企业关键业务系统中得到广泛应用。在 Apache Doris 社区&#xff0c;有众多用户选择基于 OceanBase 与 Apache Doris 以构建强大的数据处理与分析链路&#xff0c;本文将详细介绍如何便捷高效…

Java反序列化-CC3链

前言 前面的CC1与CC6链都是通过 Runtime.exec() 进行命令执行的。当服务器的代码将 Runtime放入黑名单的时候就不能使用了。 CC3链的好处是通过动态加载类的机制实现恶意类代码执行。 版本限制 jdk8u65Commons-Collections 3.2.1 动态类加载 loadClass -> 负责加载load…

38. UE5 RPG 修改火球术的攻击方向以及按住Shift攻击

在前面&#xff0c;我们实现了火球术火球的制作&#xff0c;能够在释放火球术时&#xff0c;角色将播放释放技能动画&#xff0c;并实现了对火球的目标的服务器同步功能。 我们先回忆一下之前完成的内容。 在前面&#xff0c;我们先做了一个Actor&#xff0c;用于承载发射的火…

集成学习-Bagging与随机森林回归

reg_fRFR() reg_tDTR()#实例化决策树 cvKFold(n_splits5,shuffleTrue,random_state1412)#实例化验证方式 result_tcross_validate(reg_t#要进行交叉验证的评估器,X,y,cvcv,scoringneg_mean_squared_error#评估指标,return_train_scoreTrue#是否返回训练分数&#xff0c;后面这几…

Git 原理及使用 (带动图演示)

文章目录 &#x1f308; Ⅰ Git 安装&#x1f319; 01. Linux - centos &#x1f308; Ⅱ Git 工作区、暂存区和版本库&#x1f319; 01. 认识工作区、暂存区和版本库&#x1f319; 02. 使用 Git 管理工作区的文件 &#x1f308; Ⅲ Git 基本操作&#x1f319; 01. 创建本地仓库…

动态Web项目讲解+Demo

web流程演示 请求路径 请求路径明确要请求的是哪个servlet 请求方式 servlet含有两种请求方式&#xff1a;doGet和doPost doGet&doPost 返回数据就是httpResponse&#xff0c;返回给success 参数 包含在request当中 成功 上述流程任何一步都没出问题&#xff0c;就会…

SpringBoot+layuimini实现左侧菜单动态展示

layuimini左侧菜单动态显示 首先我们看一下layuimini的原有菜单显示格式 {"homeInfo": {"title": "首页","href": "page/welcome-2.html?t2"},"logoInfo": {"title": "LAYUI MINI","…

cv2技术原理-图像旋转原理及手动实现

cv2技术原理-图像旋转原理及手动实现 1、图像旋转opencv实现2、cv2.getRotationMatrix2D函数解释3、数学原理推导旋转矩阵M4、手动计算旋转矩阵M5、旋转矩阵M的使用6、使用旋转矩阵M手动实现旋转功能 1、图像旋转opencv实现 图像旋转在对数据集数据增强&#xff08;主要是随机…

Java语言——封装

一.封装的定义 在面向对象程式设计方法中&#xff0c;封装&#xff08;英语&#xff1a;Encapsulation&#xff09;是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。 封装可以被认为是一个保护屏障&#xff0c;防止该类的代码和数据被外部类定义的代码随机访问…

linux|将用户加入白名单

一 用root用户找到etc\sudoers文件 cd etc 二 修改etc\sudoers 文件的权限 默认是只读的 修改为可写的 chmod uw sudoers 三 打开 sudoers文件&#xff0c;在Allow root to run any commands anywhere 后面 添加一条&#xff08;把上面的一条内容复制下来 修改用户名即…

什么是程控电源?以及程控电源的工作原理与应用。

一、程控电源的简介&#xff1a; 程控电源是一种具有编程功能的电源设备&#xff0c;它可以通过外部控制来设定输出电压、电流的稳压、稳流或稳压/稳流模式&#xff0c;因此可以进行电压、电流、相位、频率、功率等参数的试验和检定。一些具体的产品特性包括微机控制、高精度、…

表达式求值(后缀表达式)(数据结构)

一、概念 算术表达式是由操作数&#xff08;运算数&#xff09;、运算符&#xff08;操作符&#xff09;、和界线符&#xff08;括号&#xff09;三部分组成&#xff0c;在计算机中进行算术表达式的计算是通过堆栈来实现的。 二后缀表达式的逻辑和实现方式&#xff08;逆波兰…

电商平台数据有哪些?如何进行电商平台数据分析?(内附模板及工具)

在电商日常的贩卖工作中会产生大量的数据&#xff0c;如果你还不知道如何利用这些宝贵的数据指导未来的销售策略、增长销售额的话&#xff0c;就和我一起看下去吧&#xff01;电商数据采集API接口包含哪些数据&#xff1f; 电商平台数据可以大致分为以下几个组成部分&#xff…

Java中的封装

package day32; ​ public class Person {private String name;private int age; ​public String getName() {return name;} ​public void setName(String name) {this.name name;} ​public int getAge() {return age;} ​public void setAge(int age) {if (age>120 || …