当前位置: 首页 > news >正文

linux led 驱动

前言

今天是儿童节,挣个奖牌给小孩玩玩。
在这里插入图片描述
在 linux 驱动大家庭中,LED 驱动算是个儿童,今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》,记得那时候他还穿着开裆裤呢,裸鸡嘛在这里插入图片描述在这里插入图片描述在这里插入图片描述

ioremap()

裸机程序也好、linux 驱动程序也好,最终都是要操作真实设备的,那就要操作物理地址(设备寄存器)。之前写裸机程序,由于没有开启 MMU,CPU 操作的地址就是物理地址。现在写 linux 驱动程序不一样了,内核(包括驱动)操作的都是虚拟地址而无法直接操作物理地址。要想操作物理地址,就要上一个大杀器:ioremap(),可以参考我之前的一篇文章《ioremap()》,这里就不多介绍了。

代码

led.c

#include <asm/io.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>#define LED_MAJOR 200  /* 主设备号 */
#define LED_NAME "led" /* 字符设备名称: cat /proc/devices 显示的字符设备名称 */#define LEDOFF 0	   /* 关灯 */
#define LEDON 1		   /* 开灯 *//* 寄存器物理地址 */
#define CCM_CCR_BASE 0x020C4000	 // Clock Controller Module(CCM)
#define CCM_CCGR1 (CCM_CCR_BASE + 0x6C)
#define GPIO1_BASE 0x0209C000
#define GPIO1_DR (GPIO1_BASE + 0x0)
#define GPIO1_GDIR (GPIO1_BASE + 0x4)
#define SW_MUX_CTL_BASE 0x020E0000	// software mux control registers
#define SW_MUX_CTL_PAD_GPIO1_IO03 (SW_MUX_CTL_BASE + 0x68)
#define SW_PAD_CTL_PAD_GPIO1_IO03 (SW_MUX_CTL_BASE + 0x2F4)/* 映射后的寄存器虚拟地址指针 */
static void __iomem *V_CCM_CCGR1;
static void __iomem *V_SW_MUX_GPIO1_IO03;
static void __iomem *V_SW_PAD_GPIO1_IO03;
static void __iomem *V_GPIO1_DR;
static void __iomem *V_GPIO1_GDIR;static int led_open(struct inode *inode, struct file *filp)
{return 0;
}static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}void led_switch(u8 sta)
{u32 val;if (sta == LEDON) {val = readl(V_GPIO1_DR);val &= ~(1 << 3);writel(val, V_GPIO1_DR);} else if (sta == LEDOFF) {val = readl(V_GPIO1_DR);val |= (1 << 3);writel(val, V_GPIO1_DR);}
}/** @description		: 向设备写数据* @param - filp 	: 设备文件,表示打开的文件描述符* @param - buf 	: 要写给设备写入的数据* @param - cnt 	: 要写入的数据长度* @param - offt 	: 相对于文件首地址的偏移* @return 			: 写入的字节数,如果为负值,表示写入失败*/
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;retvalue = copy_from_user(databuf, buf, cnt);if (retvalue < 0) {printk("kernel write failed!\n");return -EFAULT;}ledstat = databuf[0]; /* 获取状态值 */if (ledstat == LEDON) {led_switch(LEDON);	/* 打开LED灯 */} else if (ledstat == LEDOFF) {led_switch(LEDOFF); /* 关闭LED灯 */}return 0;
}static int led_release(struct inode *inode, struct file *filp)
{return 0;
}/* 设备操作函数 */
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release = led_release,
};static int __init led_init(void)
{int retvalue = 0;u32 val = 0;/* 1. 寄存器地址映射 */V_CCM_CCGR1 = ioremap(CCM_CCGR1, 4);V_SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_CTL_PAD_GPIO1_IO03, 4);V_SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_CTL_PAD_GPIO1_IO03, 4);V_GPIO1_DR = ioremap(GPIO1_BASE, 4);V_GPIO1_GDIR = ioremap(GPIO1_GDIR, 4);/* 2. 使能GPIO1时钟 */val = readl(V_CCM_CCGR1);val |= (3 << 26);writel(val, V_CCM_CCGR1);/* 3. 设置GPIO1_IO03的复用功能,将其复用为 GPIO1_IO03,最后设置IO属性 */writel(5, V_SW_MUX_GPIO1_IO03);/* 4. 设置GPIO1_IO03为输出功能 */val = readl(V_GPIO1_GDIR);val |= (1 << 3);writel(val, V_GPIO1_GDIR);/* 5. 配置引脚属性,驱动能力、速度、上下拉 */writel(0x10B0, V_SW_PAD_GPIO1_IO03);/* 6. 默认关闭 LED */val = readl(V_GPIO1_DR);val |= (1 << 3);writel(val, V_GPIO1_DR);/* 7. 注册字符设备驱动 */retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);if (retvalue < 0) {printk("register chrdev failed!\n");return -EIO;}return 0;
}static void __exit led_exit(void)
{/* 取消映射 */iounmap(V_CCM_CCGR1);iounmap(V_SW_MUX_GPIO1_IO03);iounmap(V_SW_PAD_GPIO1_IO03);iounmap(V_GPIO1_DR);iounmap(V_GPIO1_GDIR);/* 注销字符设备驱动 */unregister_chrdev(LED_MAJOR, LED_NAME);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liyongjun");

led_app.c

#include "fcntl.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/stat.h"
#include "sys/types.h"
#include "unistd.h"#define LEDOFF 0
#define LEDON 1int main(int argc, char *argv[])
{int fd, retvalue;char *filename;unsigned char databuf[1];if (argc != 3) {printf("Usage: %s devfile 0/1\n", argv[0]);return -1;}filename = argv[1];/* 打开设备文件驱动 */fd = open(filename, O_RDWR);if (fd < 0) {printf("file %s open failed!\n", argv[1]);return -1;}/* 要执行的操作:打开或关闭 */databuf[0] = atoi(argv[2]);/* 向 /dev/led 文件写入数据 */retvalue = write(fd, databuf, sizeof(databuf));if (retvalue < 0) {printf("LED Control Failed!\n");close(fd);return -1;}/* 关闭文件 */retvalue = close(fd);if (retvalue < 0) {printf("file %s close failed!\n", argv[1]);return -1;}return 0;
}

Makefile

KERNELDIR := ../../../linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/
CURRENT_PATH := $(shell pwd)obj-m := led.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modulesclean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) cleanrm led_appCROSS_COMPILE = ../../../tool/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gccapp:$(CROSS_COMPILE) led_app.c -o led_appinstall:cp led.ko led_app ../../../rootfs/home/root/

验证

step1:安装驱动程序

insmod led.ko

# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
81 video4linux
89 i2c
90 mtd
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
200 led
207 ttymxc

step2:创建字符设备文件

# mknod /dev/led c 200 0
#
# ls -lh /dev/led
crw-r--r-- 1 root root 200, 0 May 31 14:06 /dev/led

step3:执行测试程序

# ./led_app /dev/led 1
# ./led_app /dev/led 0

看到 led 亮、灭

相关文章:

linux led 驱动

前言 今天是儿童节&#xff0c;挣个奖牌给小孩玩玩。 在 linux 驱动大家庭中&#xff0c;LED 驱动算是个儿童&#xff0c;今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》&#xff0c;记得那时候他还穿着开裆裤呢&#xff0c;裸鸡嘛。 ioremap() 裸机程…...

平面最近点对(分治算法)

文章目录 平面最近点对&#xff08;分治算法&#xff09;Solution流程完整模板代码 平面最近点对&#xff08;分治算法&#xff09; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 平面最近点对&#xff08;加强版&#xff09; - 洛谷 给你一些点&#xff0c;求两点之…...

【基于前后端分离的博客系统】Servlet版本

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一. 项目简介 1. 项目背景 2. 项目用到的技…...

在线Excel绝配:SpreadJS 16.1.1+GcExcel 6.1.1 Crack

前端&#xff1a;SpreadJS 16.1.1 后端&#xff1a; GcExcel 6.1.1 全能 SpreadJS 16.1.1此版本的产品中包含以下功能和增强功能。 添加了各种输入掩码样式选项。 添加了在保护工作表时设置密码以及在取消保护时验证密码的支持。 增强了组合图以将其显示为仪表图。 添加了…...

一个轻量的登录鉴权工具Sa-Token 集成SpringBoot简要步骤

Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下&#xff1a; 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…...

day 44 完全背包:518. 零钱兑换 II;377. 组合总和 Ⅳ

完全背包&#xff1a;物品可以使用多次 完全背包1. 与01背包区别 518. 零钱兑换 II1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:不能颠倒两个for循环顺序5. 代码 377. 组合总和 Ⅳ:与零钱兑换类似&#xff0c;但是是求组合数1. dp数组以及下标名义2. 递归…...

K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods

K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods 你已了解Pod以及如何通过ReplicaSets等资源部署它们以确保持续运行。虽然某些Pod可以独立完成工作&#xff0c;但现今许多应用程序需要响应外部请求。例如&#xff0c;在微服务的情况…...

牛客网DAY2(编程题)

圣诞节来啦&#xff01;请用CSS给你的朋友们制作一颗圣诞树吧~这颗圣诞树描述起来是这样的&#xff1a; 1. "topbranch"是圣诞树的上枝叶&#xff0c;该上枝叶仅通过边框属性、左浮动、左外边距即可实现。边框的属性依次是&#xff1a;宽度为100px、是直线、颜色为gr…...

Java经典笔试题—day14

Java经典笔试题—day14 &#x1f50e;选择题&#x1f50e;编程题&#x1f36d;计算日期到天数转换&#x1f36d;幸运的袋子 &#x1f50e;结尾 &#x1f50e;选择题 (1)定义学生、教师和课程的关系模式 S (S#,Sn,Sd,Dc,SA &#xff09;&#xff08;其属性分别为学号、姓名、所…...

一个帮助写autoprefixer配置的网站

前端需要用到postcss的工具&#xff0c;用到一个插件叫autoprefixer&#xff0c;这个插件能够给css属性加上前缀&#xff0c;进行一些兼容的工作。 如何安装之类的问题在csdn上搜一下都能找到&#xff08;注意&#xff0c;vite是包含postcss的&#xff0c;不用在项目中安装pos…...

C语言中的类型转换

C语言中的类型转换 隐式类型转换 整型提升 概念&#xff1a; C语言的整型算术运算总是至少以缺省&#xff08;默认&#xff09;整型类型的精度来进行的为了获得这个精度&#xff0c;表达式中字符和短整型操作数在使用之前被转换为普通整型&#xff0c;这种转换成为整型提升 如…...

String底层详解(包括字符串常量池)

String a “abc”; &#xff0c;说一下这个过程会创建什么&#xff0c;放在哪里&#xff1f; JVM会使用常量池来管理字符串直接量。在执行这句话时&#xff0c;JVM会先检查常量池中是否已经存有"abc"&#xff0c;若没有则将"abc"存入常量池&#xff0c;否…...

C++ 里面lambda和函数指针的转换

问题说明 原始问题&#xff0c;代码如下会编译报错&#xff1a; using DecisionFn bool(*)();class Decide { public:Decide(DecisionFn dec) : _dec{dec} {} private:DecisionFn _dec; };int main() {int x 5;Decide greaterThanThree{ [x](){ return x > 3; } };retur…...

前端Rust开发WebAssembly与Swc插件快速入门

前言 现代前端对速度的追求已经进入二进制工具时代&#xff0c;Rust 开发成为每个人的必修课。 一般我们将常见的前端 Rust 开发分为以下几类&#xff0c;难度由上至下递增&#xff1a; 开发 wasm 。 开发 swc 插件。 开发代码处理工具。 我们将默认读者具备最简单的 Rus…...

【C++ 学习 ⑧】- STL 简介

目录 一、什么是 STL&#xff1f; 二、STL 的版本 三、STL 的 6 大组件和 13 个头文件 四、学习 STL 的 3 个境界 五、STL 的缺陷 参考资料&#xff1a; STL教程&#xff1a;C STL快速入门&#xff08;非常详细&#xff09; (biancheng.net)。 C STL是什么&#xff0c;有…...

论文笔记--Deep contextualized word representations

论文笔记--Deep contextualized word representations 1. 文章简介2. 文章概括3 文章重点技术3.1 BiLM(Bidirectional Language Model)3.2 ELMo3.3 将ELMo用于NLP监督任务 4. 文章亮点5. 原文传送门 1. 文章简介 标题&#xff1a;Deep contextualized word representations作者…...

【MySQL高级篇笔记-性能分析工具的使用 (中) 】

此笔记为尚硅谷MySQL高级篇部分内容 目录 一、数据库服务器的优化步骤 二、查看系统性能参数 三、统计SQL的查询成本&#xff1a;last_query_cost 四、定位执行慢的 SQL&#xff1a;慢查询日志 1、开启慢查询日志参数 2、查看慢查询数目 3、慢查询日志分析工具&#xf…...

大学生数学建模题论文

大学生数学建模题论文篇1 浅论高中数学建模与教学设想 论文关键词&#xff1a;数学建模 数学 应用意识 数学建模教学 论文摘要&#xff1a;为增强学生应用数学的意识&#xff0c;切实培养学生解决实际问题的能力&#xff0c;分析了高中数学建模的必要性&#xff0c;并通过对高中…...

论文阅读 —— 滤波激光SLAM

文章目录 FAST-LIO2FAST-LIOIMUR2LIVER3LIVEEKFLINS退化摘要第一句 FAST-LIO2 摘要&#xff1a; 本文介绍了FAST-LIO2&#xff1a;一种快速、稳健、通用的激光雷达惯性里程计框架。 FAST-LIO2建立在高效紧耦合迭代卡尔曼滤波器的基础上&#xff0c;有两个关键的新颖之处&#…...

JavaScript键盘事件

目录 一、keydown&#xff1a;按下键盘上的任意键时触发。 二、keyup&#xff1a;释放键盘上的任意键时触发。 三、keypress&#xff1a;在按下并释放能够产生字符的键时触发&#xff08;不包括功能键等&#xff09;。 四、input&#xff1a;在文本输入框或可编辑元素的内容…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...