pinctrl子系统与gpio子系统实验-通过应用程序测试Led驱动程序

一. 简介

前面几篇文章基本完成了 Led驱动代码,前面通过加载驱动模块也测试了 驱动程序。

这里通过运行应用程序,通过应用程序调用 Led驱动程序,从而驱动 打开或者关闭 Led灯。

二.  通过应用程序测试Led驱动程序

1.  驱动代码实现

  gpioled.c文件代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>

#define  LED_OFF     0
#define  LED_ON      1
#define  GPIOLED_NAME  "gpioled"
#define  GPIOLED_CNT   1


//Led设备结构体
struct gpio_led {
    dev_t devid;
    int major;
    int minor;
    struct cdev cdev;
    struct class* class;
    struct device* dev;
    struct device_node * dev_node;
    int gpio_number;
};

struct gpio_led gpioled;

static int gpioled_open(struct inode *inode, struct file *filp)
{
    filp->private_data = &gpioled;
    return 0;
}

static ssize_t gpioled_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    int ret = 0;
    char rx_buf[2] = {0};

    ret = copy_from_user(rx_buf, buf, count);
    if(ret != 0)
    {
        printk("copy_from_user failed!\n");
    }
    if(rx_buf[0] == LED_ON)
    {    
        //设置低电平,打开Led
        gpio_set_value(gpioled.gpio_number, 0);  
    }
    else if(rx_buf[0] == LED_OFF)
    {   
        //设置高电平,关闭Led
        gpio_set_value(gpioled.gpio_number, 1);
    }
    return 0;
}

static int gpioled_close(struct inode *inode, struct file *filp)
{
    return 0;
}

const struct file_operations gpioled_fops = {
    .owner = THIS_MODULE,
    .open = gpioled_open,
	.release = gpioled_close,
    .write = gpioled_write,
};

/*驱动模块入口函数*/
static int __init gpioled_init(void)
{
    int ret = 0;

    /*1.注册设备号*/
    gpioled.major = 0;
    if(gpioled.major) //给出主设备号
    {
        gpioled.devid = MKDEV(gpioled.major, 0);
        ret = register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME);  
    }
    else //未给设备号时,向Linux申请设备号
    {
        ret = alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);
        gpioled.major = MAJOR(gpioled.devid);
        gpioled.minor = MINOR(gpioled.devid);
    }
    printk("gpioled.major: %d\n", gpioled.major);
    printk("gpioled.minor: %d\n", gpioled.minor);
    if(ret < 0)
    {
        printk("apply dev_number failed!\n");
        goto apply_devid_failed;
    }
    
    /*2.设备初始化 */
    gpioled.cdev.owner = THIS_MODULE;
    cdev_init(&gpioled.cdev, &gpioled_fops);
    ret = cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);
    if(ret < 0)
    {
        printk("cdev_add failed\n");
        goto cdev_add_failed;
    }

    /*3.自动创建设备节点*/
    gpioled.class = class_create(THIS_MODULE, GPIOLED_NAME);
    if (IS_ERR(gpioled.class)) {
		ret = PTR_ERR(gpioled.class);
		goto class_create_failed;
	}
    gpioled.dev = device_create(gpioled.class, NULL, gpioled.devid, NULL, GPIOLED_NAME);
    if (IS_ERR(gpioled.dev)) {
		ret = PTR_ERR(gpioled.dev);
		goto dev_create_failed;
	}	 

    /*读取设备节点*/
    gpioled.dev_node = of_find_node_by_path("/gpioled");
    if(NULL == gpioled.dev_node)
    {
        printk("find dev_node failed!\n");
        goto read_devnode_failed;
    }
    /*获取Led所对应的GPIO的编号*/
    gpioled.gpio_number = of_get_named_gpio(gpioled.dev_node, "led-gpio", 0);
    if(gpioled.gpio_number < 0)
    {
        printk("get_named_gpio failed!\n");
        goto read_devnode_failed;
    }
    /*申请GPIO管脚 */
    ret = gpio_request(gpioled.gpio_number, GPIOLED_NAME);
    if(ret != 0)
    {
        printk("gpio_request failed!\n");
        goto read_devnode_failed;
    }
    /*设置GPIO为输出,设置为高电平,关闭Led */
    ret = gpio_direction_output(gpioled.gpio_number, 1);
    if(ret != 0)
    {
        printk("gpio_direction_input failed!\n");
        goto set_gpio_input_failed;
    }

    return 0;

set_gpio_input_failed:
    gpio_free(gpioled.gpio_number);
read_devnode_failed:
    device_destroy(gpioled.class, gpioled.devid);
dev_create_failed:
    class_destroy(gpioled.class);
class_create_failed:
    cdev_del(&gpioled.cdev);
cdev_add_failed:
    unregister_chrdev_region(gpioled.devid, GPIOLED_CNT);
apply_devid_failed:
    return ret;
}

/*驱动模块出口函数*/
static void __exit gpioled_exit(void)
{
    //关闭Led灯
    gpio_set_value(gpioled.gpio_number, 1);

    /*1. 删除设备*/
    cdev_del(&gpioled.cdev);
    /*2. 注销设备号*/
    unregister_chrdev_region(gpioled.devid, GPIOLED_CNT);

    //3. 销毁设备
    device_destroy(gpioled.class, gpioled.devid);
    /*4. 销毁类*/
    class_destroy(gpioled.class);

    /*释放IO */
    gpio_free(gpioled.gpio_number);
}

/*驱动入口与出口*/
module_init(gpioled_init);
module_exit(gpioled_exit);
MODULE_LICENSE("GPL");  //License
MODULE_AUTHOR("WeiWuXian"); //author

2.  驱动测试

这里应用程序还使用 前面实现所使用的,开发板之前有拷贝过 应用程序 led_app。

重新编译驱动程序,驱动程序跟之前只做了简单的更改。驱动入口函数 gpioled_init()中,默认关闭了 Led灯,驱动出口函数 gpioled_exit()函数中也关闭了 Led灯。

开发板上电后进入系统,进入 /lib/modules/4.1.15/目录下,运行测试程序,打开Led灯:

/lib/modules/4.1.15 # ./led_app /dev/gpioled 1

这时可以查看开发板上的红色 Led灯是否开启:

这里可以看出,Led红色灯已亮。说明Led灯关闭功能可以正常运行。

运行应用程序,即运行关闭 Led的命令:

/lib/modules/4.1.15 # ./led_app /dev/gpioled 0

这时可以查看开发板上的红色 Led灯是否已灭:

可以看出,Led红色灯已经灭。说明 关闭Led灯功能可以正常运行。

综上所示,驱动模块,设备树文件都可以正常运行。至此,pinctrl子系统与 gpio子系统实验已经顺利完成。

从驱动代码实现中可以看出,与之前直接配置寄存器来驱动Led灯的方法相比,在 pinctrl子系统与gpio子系统基础上实现 的 GPIO驱动代码更简洁。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Qt】—— 项⽬⽂件解析

目录 &#xff08;一&#xff09;.pro⽂件解析 &#xff08;二&#xff09;widget.h⽂件解析 &#xff08;三&#xff09;main.cpp⽂件解析 &#xff08;四&#xff09;widget.cpp⽂件解析 &#xff08;五&#xff09;widget.ui⽂件解析 &#xff08;一&#xff09;.pro⽂…

Sg5032can(晶体振荡器spxo)规格书

SG5032CAN是爱普生推出的一款小体积尺寸5.0x3.2mm石英晶体振蒎器&#xff0c;四脚贴片晶振&#xff0c;输出频率范围为4MHz~72MHz,电源电压1.8V ~ 3.3V&#xff0c;支持CMOS输出&#xff0c;具有超小型&#xff0c;轻薄型&#xff0c;高精度&#xff0c;高性能&#xff0c;高品…

(二)hadoop搭建

1. 下载 访问https://hadoop.apache.org/releases.html查看hadoop最新下载地址 wget https://dlcdn.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz 2.解压 tar zxvf hadoop-3.3.4.tar.gz mv hadoop-3.3.4 /usr/local 3.配置环境变量&#xff08;新建.sh文件&…

【网站项目】066农家乐信息平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

面向对象(基础)---面向对象编程概述、Java语言的基本元素:类和对象

学习面向对象内容的三条主线&#xff1a; ①Java类及类的成员&#xff1a;&#xff08;重点&#xff09;属性、方法、构造器&#xff1b;&#xff08;熟悉&#xff09;代码块、内部类 ②面向对象的特征&#xff1a;封装、继承、多态、&#xff08;抽象&#xff09; ③其他关…

stm32--simulink开发之--timer的学习,硬件输入中断,触发事件,STM32通用定时器之输出比较模式与PWM模式(重要理解)

下面三个模块&#xff0c;一个比一个高级&#xff0c;当然使用是越来越简单 STM32F4xx系列控制器有2个高级控制定时器、10个通用定时器和2个基本定时器(推荐学习) 1&#xff0c;第一个模块&#xff1a;Timer 浅层理解&#xff1a;计数&#xff0c;不停的触发 Starts timer co…

Servlet简述

Servlet是动态web资源开发技术&#xff0c;其实就是一个接口&#xff0c;将来定义Servlet实现类时&#xff0c;都必须实现该接口&#xff0c;并让web服务器运行Servlet 1.快速入门 使用注释配置访问路径在Servlet3.0之后应用&#xff0c;在此之前都是使用xml配置文件来配置的。…

零基础怎么学鸿蒙开发?

对于零基础的学习者来说&#xff0c;掌握鸿蒙开发不仅是迈向新技术的第一步&#xff0c;更是开拓职业道路的重要机遇。随着鸿蒙系统在各行各业的应用逐渐扩展&#xff0c;对于掌握这一项技术的开发人员需求也随之增长。下文将为大家提供针对零基础学习鸿蒙开发的逻辑&#xff0…

粒子群优化算法

PSO算法 粒子群算法&#xff08;Particle,Swarm Optimization,PSO&#xff09;由Kennedy和Eberhart于1995年提出&#xff0c;算法模仿鸟群觅食行为对优化问题进行求解。 粒子群算法中每个粒子包含位置和速度两个属性&#xff0c;其中&#xff0c;位置代表了待求问题的一个候选…

2024年最强网络安全学习路线,详细到直接上清华的教材!

关键词&#xff1a;网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊&#xff0c;学习网络安全方向通常会有哪些问题 前排提示&#xff1a;文末有CSDN官方认证Python入门资料包&#xff01; 1、打基础时间太长 学基础花费很长时间&#xff0c;光语言…

mysql 慢查询调优实战

目录 异常现象&#xff1a;进行复现&#xff1a;寻找原因&#xff1a;解决办法&#xff1a;办法一&#xff1a;指定执行索引办法二&#xff1a;先按二级索引里字段排序&#xff0c;再按id排序办法三&#xff1a;取消排序 最终方案&#xff1a;复盘&#xff1a; 异常现象&#x…

基于springboot+vue的校园赛事资讯网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

搜维尔科技:【简报】元宇宙数字人赛道,优秀作品《星云时报》赏析

AI 对人们来说是一种新产业&#xff0c;而人们对于它未来会面临的议题仍有许多疑虑&#xff0c;因此我们用新闻报导的方式列举一些有趣且具有可能性的标题&#xff0c;希望能让 大家了解 AI 在未来可能会带来什么问题&#xff0c;以及我们应该采取的态度。 学校&#xff1a; 新…

C++(17)——list的模拟实现

前面的文章中&#xff0c;介绍了&#xff0c;的模拟实现&#xff0c;本篇文章将介绍对于的模拟实现。 目录 1. list的基本结构&#xff1a; 2. list功能实现&#xff1a;尾部插入元素&#xff1a; 3. list迭代器的实现&#xff1a; 4. list功能实现&#xff1a;在任意位置前…

vue2 导入使用vue-codemirror详解

目录 vue2 导入使用vue-codemirror详解1 介绍2 安装使用2.1 安装 vue-codemirror2.2 使用 codemirror2.2.1 引入 3 配置详情3.1 语言模式配置3.2 自动高度设置3.4 主题配置 4 总结 vue2 导入使用vue-codemirror详解 1 介绍 vue-codemirror是一个基于Vue的代码在线编辑器组件&…

【jenkins】主从机制及添加Slave节点操作

一、master-slave 日常构建Jenkins任务中&#xff0c;会经常出现下面的情况&#xff1a; 自动化测试需要消耗大量的 CPU 和内存资源&#xff0c;如果服务器上还有其他的服务&#xff0c;可能会造成卡顿或者宕机这样的情况&#xff1b; Jenkins 平台上除了这个项目&#xff0c…

把成绩私发给家长

与家长保持及时、有效的沟通对于学生的成长至关重要。但有时候&#xff0c;我会选择将学生的成绩私发给家长&#xff0c;而不是在公共场合公布。这样做有以下几个原因。 保护学生的隐私。每个学生都拥有自己的个人信息&#xff0c;这包括学习成绩。在公共场合公布成绩&#xf…

Sqoop数据迁移工具

概述 Apache Sqoop&#xff08;SQL-to-Hadoop&#xff09;项目旨在协助RDBMS与Hadoop之间进行高效的大数据交流。用户可以在 Sqoop 的帮助下&#xff0c;轻松地把关系型数据库的数据导入到 Hadoop 与其相关的系统 (如HBase和Hive)中&#xff1b;同时也可以把数据从 Hadoop 系统…

【计算机二级考试C语言】C递归

目录 C 递归 数的阶乘 实例 斐波那契数列 实例 C 递归 递归指的是在函数的定义中使用函数自身的方法。 举个例子&#xff1a; 从前有座山&#xff0c;山里有座庙&#xff0c;庙里有个老和尚&#xff0c;正在给小和尚讲故事呢&#xff01;故事是什么呢&#xff1f;"从…

都 2024 年了!程序员的到底出路在哪里!?继续卷技术?晋升管理层?还是转业?

都 2024 年了&#xff01;程序员的到底出路在哪里&#xff01;&#xff1f;继续卷技术&#xff1f;晋升管理层&#xff1f;还是转业&#xff1f; 1&#xff09;程序员的难处2&#xff09;程序员专业方向3&#xff09;大数据3.1.大数据开发涉及到哪些技术3.2.大数据开发涉及到的…