Rk3568驱动开发_GPIO点亮LED_12

article/2025/6/19 2:38:10

需求:

用配置寄存器方式控制点灯非常原始,现在采用更方便的Linux提供的pctrl和gpio子系统编写字符驱动

1.设备树配置:
在这里插入图片描述
现将开发板中呼吸灯关闭掉防止占用到我需要使用的引脚

在这里插入图片描述

	/* Narnat 2025-5-29 RK3568 GPIO 无需设置pinctrl*/gpioled{compatible = "atkrk3568-gpio-led";led-gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;status = "okay";};

下图为设备树中GPIO0的地址
在这里插入图片描述

在设备树根节点下添加gpioled节点,标明引脚,配置完设备树后将kernel单独编译,将生成的boot.img烧到设备中可以看到如下节点:
在这里插入图片描述
可以用cat读取相关信息

2.驱动编写:

驱动中需要读取上述gpioled设备节点找到对应的引脚,向内核申请这个引脚的使用权gpio_request(gpioled.led_gpio, “LED-GPIO”);这样能防止多个驱动程序抢夺一个引脚问题,申请使用权成功后就能使用Linux自带的GPIO函数了ret = gpio_direction_output(gpioled.led_gpio, 0);然后就是在/dev目录下创建设备节点了,创建设备节点分为:创建设备号、初始化并添加字符驱动、创建类、创建设备

驱动代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.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_address.h>
#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define GPIOLED_CNT    1   // 设备号数目
#define GPIOLED_NAME   "gpioled" // 名字
#define LEDOFF         0 // 关灯
#define LEDON          1 // 开灯struct gpioled_dev{  // 设备结构体dev_t devid;       // 设备号int major;         // 主设备号int minor;         // 次设备号struct cdev cdev;  // 字符设备struct class* class; // 类struct device_node* nd; // 设备节点struct device* device; // 设备int led_gpio;  // led所使用的编号
};struct gpioled_dev gpioled; // led设备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 retvalue;unsigned char databuf[1];unsigned char ledstat;struct gpioled_dev* dev = filp->private_data;retvalue = copy_from_user(databuf, buf, cnt);if(retvalue < 0){printk("kernel write failed \r\n");return -1;}ledstat = databuf[0];if(ledstat == LEDON){gpio_set_value(dev->led_gpio, 1); // 打开LED}else if(ledstat == LEDOFF){gpio_set_value(dev->led_gpio, 0); // 关灯}return 0;
}static int led_release(struct inode* inode, struct file* filp){return 0;
}static struct file_operations gpioled_fops = { // 设备操作函数.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release =  led_release,
};static int __init led_init(void){int ret = 0;const char* str;/* 设置LED所使用的GPIO */// 1.获取设备节点gpioled.nd = of_find_node_by_path("/gpioled");if(gpioled.nd == NULL){printk("gpioled node not find \r\n");return -1;}// 2.读取status属性ret = of_property_read_string(gpioled.nd, "status", &str);if(ret < 0){printk("read status error \r\n");return -1;}if(strcmp(str, "okay")){printk("status is not okay \r\n");return -1;}// 3.读取compatible属性值ret = of_property_read_string(gpioled.nd, "compatible", &str);if(ret < 0){printk("read compatible error \r\n");return -1;}if(strcmp(str, "atkrk3568-gpio-led")){printk("compatible is not atkrk3568-gpio-led \r\n");return -1;}//4.获取设备树中的gpio属性,得到LED所使用的LED编号gpioled.led_gpio = of_get_named_gpio(gpioled.nd, "led-gpio", 0); // 0取第一个if(gpioled.led_gpio < 0){printk("cant get led-gpio \r\n");return -1;}printk("led-gpio num = %d \r\n", gpioled.led_gpio);//5.向gpio子系统申请使用GPIO 当前驱动独自占有此驱动ret = gpio_request(gpioled.led_gpio, "LED-GPIO");if(ret){printk("request led-gpio failed \r\n");return -1;}//6.设置GPIO为输出,并且输出低电平,关闭LED灯ret = gpio_direction_output(gpioled.led_gpio, 0);if(ret < 0){printk("cant set gpio \r\n");return -1;}/* 注册字符设备驱动 */// 1.创建设备号if(gpioled.major){gpioled.devid = MKDEV(gpioled.major, 0);ret = register_chrdev_region(gpioled.devid, GPIOLED_CNT, GPIOLED_NAME); // 注册字符设备号if(ret < 0){gpio_free(gpioled.led_gpio);printk("cant register %s char driver ret = %d \r\n", GPIOLED_NAME, ret);return -1;}}else{ret = alloc_chrdev_region(&gpioled.devid, 0, GPIOLED_CNT, GPIOLED_NAME);  // 申请设备号if(ret < 0){gpio_free(gpioled.led_gpio);printk("cant alloc_chrdev_region %s, ret = %d \r\n", GPIOLED_NAME, ret);return -1;}gpioled.major = MAJOR(gpioled.devid);gpioled.minor = MINOR(gpioled.devid); // 获取主次设备号}printk("%s gpioled major = %d, minnor=%d \r\n", GPIOLED_NAME, gpioled.major, gpioled.minor);// 2.初始化字符驱动gpioled.cdev.owner = THIS_MODULE;cdev_init(&gpioled.cdev, &gpioled_fops);// 3.添加一个字符驱动cdev_add(&gpioled.cdev, gpioled.devid, GPIOLED_CNT);if(ret < 0){  // 添加失败unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注销掉设备号gpio_free(gpioled.led_gpio);return -1;}// 4.创建类gpioled.class = class_create(THIS_MODULE, GPIOLED_NAME);if(IS_ERR(gpioled.class)){ // 创建类失败cdev_del(&gpioled.cdev); // 删掉字符驱动unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注销掉设备号gpio_free(gpioled.led_gpio);return -1;}// 5.创建设备gpioled.device = device_create(gpioled.class, NULL, gpioled.devid, NULL, GPIOLED_NAME);if(IS_ERR(gpioled.device)){ // 设备创建失败class_destroy(gpioled.class); // 删掉类cdev_del(&gpioled.cdev); // 删掉字符驱动unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注销掉设备号gpio_free(gpioled.led_gpio);return -1;}return 0;
}static void __exit led_exit(void){device_destroy(gpioled.class, gpioled.devid); // 注销设备class_destroy(gpioled.class); // 删掉类cdev_del(&gpioled.cdev); // 删掉字符驱动unregister_chrdev_region(gpioled.devid, GPIOLED_CNT); // 注销掉设备号gpio_free(gpioled.led_gpio);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Narnat");

在这里插入图片描述

应用层代码:略

开灯关灯命令:

在这里插入图片描述
效果图:略


http://www.hkcw.cn/article/jJJJpVrRuy.shtml

相关文章

Compose原理 - 整体架构与主流程

一、整体架构 在官方文档中&#xff08;Jetpack Compose 架构层 | Android Developers&#xff09;&#xff0c;对Compose的分层有所阐述&#xff1a; 其中 Runtime&#xff1a;提供Compose的基础运行能力&#xff0c;包括State、Side-effects、CompositionLocal、Compositio…

LeetCode 高频 SQL 50 题(基础版)之 【聚合函数】部分

题目&#xff1a;620. 有趣的电影 题解&#xff1a; select * from cinema where description !boring and id%21 order by rating desc题目&#xff1a;1251. 平均售价 题解&#xff1a; select p.product_id product_id,round(ifnull(sum(p.price*u.units)/sum(u.units),0)…

雪花算法的实际应用

什么场景下用雪花算法&#xff1f; 软件项目开发中&#xff0c;主键自动生成是基本需求。而各个数据库对于该需求也提供了相应的支持&#xff0c;比如&#xff1a;数据库自增(MySql,oracle)。但是在分布式环境中&#xff0c;分库分表之后&#xff0c;不同表生成全局唯一的ID是非…

Thinkphp6实现websocket

项目需要连接一台自动售货机&#xff0c;售货机要求两边用websocket连接,监听9997端口。本文实现了一个基于PHP的WebSocket服务器&#xff0c;用于连接自动售货机&#xff0c;支持start/stop/restart命令操作 1.新建文件 新建文件 /command/socket.php <?php namespace a…

痉挛性斜颈带来的困扰

当颈部不受控制地扭转歪斜&#xff0c;生活便被打乱了节奏。颈部肌肉异常收缩&#xff0c;导致头部不自觉偏向一侧或后仰&#xff0c;不仅让外观明显异于常人&#xff0c;还会引发持续的酸痛与僵硬感。长时间保持扭曲姿势&#xff0c;肩颈肌肉过度紧绷&#xff0c;甚至会牵连背…

【中国・珠海】2025 物联网与边缘计算国际研讨会(IoTEC2025)盛大来袭!

2025 物联网与边缘计算国际研讨会&#xff08;IoTEC2025&#xff09;盛大来袭&#xff01; 科技浪潮奔涌向前&#xff0c;物联网与边缘计算已成为驱动各行业变革的核心力量。在此背景下&#xff0c;2025 物联网与边缘计算国际研讨会&#xff08;IoTEC2025&#xff09;即将震撼…

一周学会Pandas2之Python数据处理与分析-数据重塑与透视-pivot() - 透视 (长 -> 宽,有限制)

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili pivot() 是 pandas 中用于数据重塑的核心方法&#xff0c;它将长格式数据转换为宽格式数据&#xff0c;与 melt() 方…

WordPress通过简码插入bilibili视频

发布于&#xff1a;Eucalyptus-Blog 一、前言 B站是国内非常受欢迎的视频分享平台&#xff0c;上面不仅内容丰富&#xff0c;而且很多视频制作精良、趣味十足。很多人&#xff0c;比如我&#xff0c;就喜欢将B站的视频通过 iframe 嵌入到自己的网页中&#xff0c;但这段代码又…

【Unity博客节选】Timeline 的 Traversal mode参数

注&#xff1a;软件版本Unity 6.0 Timeline 1.8.7 作者&#xff1a;CSDN RingleaderWang 原文&#xff1a;《Unity第25期——Timeline结构及其源码浅析》 文章首发Github&#x1f44d;&#xff1a;《Timeline结构及其源码浅析》 Bilibili 视频版&#x1f44d;&#x1f44d;&a…

Constraints and Triggers

目录 Kinds of Constraints Single-Attribute Keys Multiattribute Key Foreign Keys Expressing Foreign Keys Enforcing Foreign-Key Constraints Actions Taken Attribute-Based Checks Timing of Checks Tuple-Based Checks Assertions Timing of Assertion Ch…

免费且好用的PDF水印添加工具

软件介绍 今天要给大家推荐一款超实用的PDF添加水印工具&#xff0c;它能够满足用户给PDF文件添加水印的需求&#xff0c;而且完全免费。 这款PDF添加水印的软件有着简洁的界面&#xff0c;操作简便&#xff0c;无需安装&#xff0c;解压后即可使用。 在使用前&#xff0c;先…

设计模式——面向对象设计六大原则

摘要 本文详细介绍了设计模式中的六大基本原则&#xff0c;包括单一职责原则、开放封闭原则、里氏替换原则、接口隔离原则、依赖倒置原则和合成复用原则。每个原则都通过定义、理解、示例三个部分进行阐述&#xff0c;旨在帮助开发者提高代码的可维护性和灵活性。通过具体代码…

DO指数GPU版本

大指数下DO指数模型计算优化 DO指数模型概述 DO指数&#xff08;Duranton-Overman Index&#xff09;是由Duranton和Overman于2005年提出的产业空间集聚测度方法&#xff0c;它通过分析企业间的精确地理距离分布来识别产业集聚模式。与传统集聚指标相比&#xff0c;DO指数具有…

工业物联网中的事件驱动采样架构及优化

论文标题 Event-Based Sampling Architecture and Optimization for Industrial Internet of Things 工业物联网中的事件驱动采样架构及优化 作者信息 Tejas Thosani Process Control Systems, Micron Technology Inc., Manassas, USA tthosanimicron.com Andres Prado Esp…

Windows | 总误按Num Lock?修改注册表永久禁用Numlk键使小键盘一直输入数字

先说需修改注册表的位置与键值 路径&#xff1a;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout\ 二进制键&#xff1a;Scancode Map 键值&#xff1a; 00 00 00 00 00 00 00 00 01 00 00 00 00 00 45 00 00 00 00 00 00 00 00 00如下图&#xff1a; …

c#与halcon环境配置,导出算法库,使用halcon环境编程

目录 1. C#配置halcon运行环境 2.导出halcon算法库 3.使用方法 记录下C#配置halcon环境的方法&#xff0c;以及halcon导出库的使用方法。 1. C#配置halcon运行环境 VS版本&#xff1a; vs2019 halcon版本: 20.11 创建c#工程&#xff0c;点击“创建新项目”&#xff0c;…

tomcat yum安装

使用yum安装 yum install -y java-1.7.0-openjdk* tomcat* --disablerepoepel## java-1.7.0-openjdk* 注意&#xff1a;最终安装的是java-1.8.0版本## --disablerepoepel 禁用&#xff1a;EPEL源&#xff0c;防止版本冲突 java -version (2) 启停&#xff1a;Tomcat 7 s…

时间的基本概念与相关技术三

1.5 守时技术 所谓守时&#xff08;time keeping&#xff09;是指一个时频系统&#xff08;包括频标和分频钟&#xff09;对时间信号和时间信息的保持。频率标准&#xff08;简称频标&#xff09;的频率准确度、频率稳定度和守时系统的环境条件是决定守时能力的三个关键因素。…

云原生安全基石:Kubernetes 核心概念与安全实践指南

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. Kubernetes 架构全景 Kubernetes&#xff08;简称 K8s&#xff09;采用主从架构&#xff0c;由控制平面&#xff08;Control Plane&…

【python】uv管理器

uv是一个速度极快的 Python 包和项目管理器&#xff0c;用 Rust 编写。 安装 安装uv之前&#xff0c;确保你的电脑不需要安装了python 在Windows下&#xff0c;可以使用官方的脚本直接安装 powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.…