嵌入式Linux LED驱动开发

一、LED驱动概述

本笔记基于IMX6ULL处理器的LED驱动开发,详细介绍了字符设备驱动开发的基本流程。该驱动实现了对LED的基本控制功能,通过字符设备接口供用户空间程序调用。

二、LED驱动核心概念

1. 寄存器地址定义

本驱动涉及多个硬件寄存器的配置:

#define CCM_CGR1_BASE        0x020C406C // 时钟控制寄存器
#define SW_MUX_GPIO1_IO03_BASE 0x020E0068 // 引脚复用配置
#define SW_PAD_GPIO1_IO03_BASE 0x020E02F4 // 引脚电气特性配置
#define GPIO1_DR_BASE        0x0209C000 // 数据寄存器
#define GPIO1_GDIR_BASE      0x0209C004 // 方向寄存器

2. 寄存器操作方法

  • ioremap:将物理地址映射到内核虚拟地址空间
  • readl:读取寄存器值
  • writel:写入寄存器值
  • iounmap:解除地址映射

3. LED状态定义

#define LEDOFF 0 // LED关闭
#define LEDON  1 // LED开启

三、LED驱动开发步骤

1. 驱动模块初始化与卸载

static int __init led_init(void) {// 初始化代码
}static void __exit led_exit(void) {// 清理代码
}module_init(led_init);
module_exit(led_exit);

2. 硬件初始化

  1. 地址映射
CCM_CGR1 = ioremap(CCM_CGR1_BASE, 4);
SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
  1. 时钟使能
val = readl(CCM_CGR1);
val &= ~(3 << 26); // 清除旧设置
val |= (3 << 26);  // 启用GPIO1时钟
writel(val, CCM_CGR1);
  1. 引脚配置
writel(0x5, SW_MUX_GPIO1_IO03); // 设置为GPIO模式
writel(0x10B0, SW_PAD_GPIO1_IO03); // 配置电气特性
  1. GPIO方向设置
val = readl(GPIO1_GDIR);
val |= (1 << 3); // 设置GPIO1_IO03为输出
writel(val, GPIO1_GDIR);

3. 设备操作函数实现

  1. LED开关函数
static void led_switch(unsigned char state) {unsigned int val = 0;val = readl(GPIO1_DR);if (state == LEDON) {val &= ~(1 << 3); // 拉低电压点亮LED} else if (state == LEDOFF) {val |= (1 << 3); // 拉高电压关闭LED}writel(val, GPIO1_DR);
}
  1. 文件操作结构体
static const struct file_operations led_fops = {.owner = THIS_MODULE,.write = led_write,.open = led_open,.release = led_release,
};
  1. open和release函数
static int led_open(struct inode *inode, struct file *file) {printk("LED device opened\n");return 0;
}static int led_release(struct inode *inode, struct file *file) {printk("LED device closed\n");return 0;
}
  1. write函数
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {int ret = 0;unsigned char databuf[1];ret = copy_from_user(databuf, buf, count);if (ret < 0) {printk("Failed to copy data from user space\n");return -EIO;}led_switch(databuf[0]);return 0;
}

4. 模块注册与注销

static int __init led_init(void) {// ...ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);// ...
}static void __exit led_exit(void) {// ...unregister_chrdev(LED_MAJOR, LED_NAME);// ...
}

四、用户空间测试程序

1. 测试程序功能

int main(int argc, char *argv[]) {if (argc != 3) {fprintf(stderr, "Usage: %s <led_device> <0|1>\n", argv[0]);return -1;}char* filename;unsigned char databuf[1];filename = argv[1];databuf[0] = atoi(argv[2]);int fd = 0;int ret = 0;fd = open(filename, O_RDWR);if (fd < 0) {perror("open led device error");return -1;}ret = write(fd, databuf, 1);if (ret < 0) {perror("write led device error");close(fd);return -1;}close(fd);return 0;
}

2. 测试方法

# 编译测试程序
arm-linux-gnueabihf-gcc ledAPP.c -o ledAPP# 加载驱动
sudo insmod led.ko# 创建设备节点
sudo mknod /dev/led c 200 0# 点亮LED
sudo ./ledAPP /dev/led 1# 关闭LED
sudo ./ledAPP /dev/led 0

五、Makefile说明

KERNERDIR := /home/ubuntu2004/linux/IMX6ULL/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga
CURRENTDIR := $(shell pwd)obj-m := led.obuild : kernel_moduleskernel_modules:$(MAKE) -C $(KERNERDIR) M=$(CURRENTDIR) modulesclean:$(MAKE) -C $(KERNERDIR) M=$(CURRENTDIR) clean

六、驱动开发关键知识点

1. 地址映射与硬件访问

  • 使用ioremap将物理地址映射到内核地址空间
  • 使用readlwritel进行寄存器读写
  • 使用iounmap解除地址映射

2. 内核空间与用户空间交互

  • 使用copy_from_user从用户空间复制数据
  • 使用printk输出内核日志信息

3. 字符设备驱动注册

  • 使用register_chrdev注册字符设备
  • 使用unregister_chrdev注销字符设备

4. GPIO操作

  • 配置GPIO为输出模式
  • 通过修改DR寄存器控制LED状态
  • 注意GPIO电平的含义(低电平点亮LED)

5. 驱动调试

  • 使用dmesg查看内核日志
  • 使用insmod加载驱动
  • 使用mknod创建设备节点
  • 使用测试程序验证驱动功能

七、LED驱动工作流程

  1. 驱动加载

    • 执行insmod led.ko加载驱动
    • 执行dmesg查看"LED module initialized"确认加载成功
  2. 设备节点创建

    • 执行mknod /dev/led c 200 0创建设备节点
  3. LED控制

    • 执行./ledAPP /dev/led 1点亮LED
    • 执行./ledAPP /dev/led 0关闭LED
  4. 驱动卸载

    • 执行rmmod led.ko卸载驱动
    • 执行dmesg查看"LED module exited"确认卸载成功

八、常见问题与解决

  1. LED不工作

    • 检查地址映射是否正确
    • 使用printk调试输出确认驱动加载
    • 检查GPIO方向是否设置为输出
    • 验证硬件连接
  2. 驱动加载失败

    • 检查设备号是否冲突
    • 查看dmesg日志定位错误
    • 确认内核版本与编译环境匹配
  3. 用户程序无法访问

    • 检查设备节点权限
    • 确认设备节点主设备号匹配
    • 检查open和write函数实现

九、驱动开发总结

本驱动实现了对IMX6ULL处理器GPIO接口的LED控制,展示了字符设备驱动开发的基本流程:

  1. 硬件寄存器地址定义和初始化
  2. 地址映射和硬件配置
  3. 字符设备注册
  4. 文件操作函数实现
  5. 用户空间接口设计
  6. 驱动模块加载和卸载
  7. 测试程序开发

Gitee 源码仓库

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

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

相关文章

Excel Word Pdf 格式转换

引入aspose包手动更新本地mvn仓库mvn install:install-file -DfileC:\aspose-cells-22.9.jar -DgroupIdaspose -DartifactIdaspose-cells -Dversion22.9 -Dpackagingjar mvn install:install-file -DfileC:\aspose-pdf-22.9.jar -DgroupIdaspose -DartifactIdaspose-pdf -Dvers…

变频器实习DAY40 调整测试零伺服PI LDO

目录变频器实习DAY40一、工作内容1.1 调整测试零伺服PI二、学习内容2.1 LDOLDO的核心工作原理——“采样-比较-调整”闭环控制LDO的关键参数——选型核心依据LDO与其他稳压器的选型对比附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^)变频器实习DAY40 一、工作内容 1.1 调整…

【半导体制造流程概述】

半导体制造流程概述 半导体制造是一个高度复杂且精密的过程&#xff0c;涉及多个关键步骤&#xff0c;通常分为以下几个主要阶段&#xff1a;设计、晶圆制备、光刻、刻蚀、掺杂、薄膜沉积、互连和封装测试。 文章目录半导体制造流程概述晶圆制备光刻刻蚀掺杂薄膜沉积互连封装测…

为什么大模型需要文档预处理:从数据到智能的关键一步

在人工智能&#xff0c;尤其是大语言模型&#xff08;LLM, Large Language Models&#xff09;的应用落地过程中&#xff0c;数据质量与处理流程的重要性正逐渐被各行各业所认识。无论是企业内部构建知识库、自动化文档审核&#xff0c;还是面向用户提供智能问答服务&#xff0…

50.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--新增功能--二期功能规划

啰嗦了这么多文章&#xff0c;我们终于进入到了二期功能的开发。这篇文章我们先来规划一下二期要做的功能&#xff0c;在一期功能中&#xff0c;我们完成了基础的记账功能&#xff0c;但是作为一个记账软件&#xff0c;仅有这些功能是远远不够的。我们需要更多的功能来满足用户…

Oracle下载安装(学习版)

1. 下载&#xff08;学习版&#xff09; 网址&#xff1a;软件下载 | Oracle 中国 2. 安装 解压缩 双击可执行文件 下一步 选同意&#xff0c;下一步 下一步 设置密码&#xff08;自己记住&#xff09; 开始安装 测试安装是否成功

`basic_filebuf`、`basic_ifstream`、`basic_ofstream`和 `basic_fstream`。

C 文件 I/O 模板类深度解析 文章目录C 文件 I/O 模板类深度解析1. basic_filebuf 深度解析1.1 类模板定义详解1.2 关键成员变量1.3 核心成员函数实现原理1.3.1 open() 函数实现1.3.2 overflow() 函数实现1.4 完整示例&#xff1a;自定义缓冲策略2. basic_ifstream 深度解析2.1 …

计算机毕设 java 阿歹果园养鸡场管理系统 基于 SSM 框架的果园养鸡场全流程管理系统设计与实现 Java+MySQL 的养殖生产与进销存一体化平台开发

计算机毕设 java 阿歹果园养鸡场管理系统ky7dc9 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09;本套源码可以先看具体功能演示视频领取&#xff0c;文末有联xi 可分享 随着农业养殖规模化发展&#xff0c;传统果园养鸡场依赖人工记录、纸质台账的管理模式&#xf…

生成式BI工具(WrenAI)

生成式 BI 工具支持自然语言查询数据库&#xff0c;自动生成 SQL 与可视化图表&#xff0c;被金融分析师和数据科学家广泛采用。 WrenAI是由Canner团队开发的开源生成式BI&#xff08;GenBI&#xff09;智能体&#xff0c;致力于通过自然语言交互实现数据库查询、可视化生成和洞…

论文Review 3DGS PGSR | TVCG2024 ZJU-3DV | 几何约束的3DGS表面重建

基本信息 题目&#xff1a;PGSR: Planar-based Gaussian Splatting for Efficient and High-Fidelity Surface Reconstruction 来源&#xff1a;TVCG2024 学校&#xff1a;ZJU-3DV 是否开源&#xff1a;https://github.com/zju3dv/PGSR 摘要&#xff1a;3DGS表面重建 最近…

最新After Effects2025下载安装(含安装包)AE 2025 保姆级下载一键安装图文教程

文章目录一、After Effects 2025下载二、After Effects 2025安装教程三、核心功能升级详解四、系统配置与兼容性说明一、After Effects 2025下载 ①夸克网盘下载链接&#xff1a;https://pan.quark.cn/s/a06e6200e64c 二、After Effects 2025安装教程 1.解压安装包:找到下载…

【网络安全领域】边界安全是什么?目前的发展及应用场景

在网络安全领域&#xff0c;边界安全&#xff08;Perimeter Security&#xff09; 是指围绕企业或组织网络的 “物理与逻辑边界” 构建的防护体系&#xff0c;核心目标是阻止未授权访问从外部网络&#xff08;如互联网、合作方网络&#xff09;侵入内部可信网络&#xff0c;同时…

虚拟机快照对内存与磁盘空间的影响

核心概念&#xff1a;快照是什么&#xff1f;虚拟机快照捕获的是在某个特定时间点上虚拟机的完整状态。这包括&#xff1a;磁盘状态&#xff1a;虚拟磁盘的数据。内存状态&#xff1a;当时虚拟机内存中的所有内容&#xff08;如果选择&#xff09;。配置状态&#xff1a;虚拟机…

免费开源的 Gemini 2.5 Flash 图片生成器

免费开源的 Gemini 2.5 Flash 图片生成器&#xff1a;gemini-nano-banana 项目详解 在 AI 图片生成领域&#xff0c;大多数工具要么收费昂贵&#xff0c;要么需要复杂的配置。今天为大家介绍一个完全免费开源的解决方案——gemini-nano-banana&#xff0c;一个基于 Google Gemi…

介绍分布式事务之Seata

简介 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式事务解决方案。 &#x1f680; 一、Seata 的四种主要模式 Seata 提供的分布式事…

安卓/ios按键精灵脚本开发工具:OpenCV.FindImgAll命令介绍

函数名称OpenCV.FindImgAll 找图返回全部结果函数功能使用OpenCV多尺度模板找图&#xff0c;返回全部结果与FindPic的区别&#xff1a;OpenCV找图&#xff1a;基于特征相似性的找图&#xff0c;允许一定几何形变或颜色差异&#xff0c;从而提高多分辨率容兼及抗干扰能力&#x…

Linux时间处理函数

gettimeofday 是 Linux 系统中一个用于获取当前时间的系统调用函数。它能够获取从 Unix 纪元&#xff08;1970年1月1日 00:00:00 UTC&#xff09;到当前时刻的秒数和微秒数。函数原型#include <sys/time.h>int gettimeofday(struct timeval *tv, struct timezone *tz);参…

C++ 面试高频考点 力扣 34. 在排序数组中查找元素的第一个和最后一个位置 二分查找左右端点 题解 每日一题

文章目录二分查找进阶&#xff0c;精准定位左右边界题目描述先踩坑&#xff1a;朴素二分为什么搞不定重复元素&#xff1f;第一步&#xff1a;找左边界——如何定位“第一个target”&#xff1f;第二步&#xff1a;找右边界——如何定位“最后一个target”&#xff1f;完整代码…

在word以及latex中引用zotero中的参考文献

背景 如何在word以及latex中引用zotero中的参考文献 历史参考 恢复Zotero软件内的误删条目数据/文献-CSDN博客使用zotero保存 CNKI知网文章时发生错误。改为尝试用 Save as Webpage 保存。-CSDN博客 word 在word中引用zotero中的参考文献 打开word&#xff0c;点击引用 经典…

docker 部署Skywalking

创建网络 docker network create skywalking-network docker compose 安装SkyWalking docker-compose.yaml 文件 version: "3" services:# SkyWalking OAP server with Elasticsearch storageskywalking-oap:image: apache/skywalking-oap-server:8.9.0container…