Linux内核驱动开发-001字符设备开发-001Led驱动

上节完成了内核驱动框架的搭建,下面将利用Linux内核驱动第一个字符设备文件,即Led驱动。

1驱动程序编写

/*************************************************************************> File Name: led.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年04月21日 星期日 16时20分42秒************************************************************************/#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>#if 0
/*数据类型重定义*/
typedef unsigned char u8;
typedef unsigned int u32;
#endif#define DEVICE_MAJOR 200
#define DEVICE_NAME  "led_device"/*寄存器地址映射*/
#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)/**/
unsigned int *regGPBCON;
unsigned int *regGPBDAT;/*led函数声明*/
void led_init(void);
void led_off(void);
void led_on(u8 n);
void led_on_off(u8 n);
void delay_nms(u32 t);/*驱动函数声明*/
void r_ioremap(void);
static int __init led_driver_init(void);
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset);
static void __exit led_driver_exit(void);int led_driver_open(struct inode *node, struct file *fp);
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset);
int led_driver_close(struct inode *node, struct file *fp);/*定义结构体变量*/
static struct file_operations fops = 
{.owner = THIS_MODULE,.open = led_driver_open,.read = led_driver_read,.write = led_driver_write,.release = led_driver_close
};#if 1
/*******************************************************************************
* 函 数 名	: r_ioremap
* 函数功能	: 寄存器映射
* 输    入  :无 							
* 输    出  :无
*******************************************************************************/
void r_ioremap(void)
{/*寄存器映射*/regGPBCON = ioremap(GPBCON, 4);//【源地址】【需要映射的地址大小】<返回目标地址>regGPBDAT = ioremap(GPBDAT, 4);
}
#endif#if 0
static int __init led_driver_init(void)
{unsigned int t;/*注册字符设备*/register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &fops);/*寄存器映射*/regGPBCON = ioremap(GPBCON, 4);//【源地址】【需要映射的地址大小】<返回目标地址>regGPBDAT = ioremap(GPBDAT, 4);t = *regGPBCON;t &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));t |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);*regGPBCON = t;printk("led_driver_init OK\n");return 0;
}
#endif#if 1
/*******************************************************************************
* 函 数 名	: led_driver_init
* 函数功能	: led驱动初始化
* 输    入  :无 							
* 输    出  :无
*******************************************************************************/
static int __init led_driver_init(void)
{/*注册字符设备*/register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &fops);/*寄存器映射*/r_ioremap();//每次调用led函数都要先调用寄存器映射函数?/*led初始化*/led_init();printk("led_driver_init OK\n");return 0;
}
#endif#if 1
int led_driver_open(struct inode *node, struct file *fp)
{return 0;
}
#endif#if 1
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{return 0;
}
#endif#if 0
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{char n;unsigned int t;copy_from_user(&n, user_buffer, 1);n &= 0x0F;t = *regGPBDAT;t &= ~(0x0F << 5);t |= n << 5;*regGPBDAT = t;return 1;
}
#endif#if 1
/*******************************************************************************
* 函 数 名 : led_driver_write
* 函数功能 : led驱动写数据
* 输    入 :
*               fp:
*      user_buffer:
*           offset:
* 输    出 :无
*******************************************************************************/
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{char n;copy_from_user(&n, user_buffer, 1);led_on(n);return 1;
}
#endif#if 1
int led_driver_close(struct inode *node, struct file *fp)
{return 0;
}
#endif#if 1
/*******************************************************************************
* 函 数 名 : led_driver_exit
* 函数功能 : 退出led驱动
* 输    入 : 无
* 输    出 : 无
*******************************************************************************/
static void __exit led_driver_exit(void)
{	unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME);printk("led_driver_exit OK\n");
}
#endif/*=========================led配置函数=========================*//*******************************************************************************
* 函 数 名	: led_init
* 函数功能	: LED初始化
* 输    入  :无 							
* 输    出  :无
*******************************************************************************/
//LED1-GPB5,LED2-GPB6,LED3-GPB7,LED4-GPB8
void led_init(void)
{u32 t=0;t=*regGPBCON;//思考点:这里为何要使用中间变量配置寄存器?t&=~((3<<10)|(3<<12)|(3<<14)|(3<<16));//LED控制引脚清0t|=(1<<10|1<<12|1<<14|1<<16);//LED控制引脚配置-输出状态*regGPBCON=t;//配置端口B引脚led_off();//初始化LED为关闭
}
/*******************************************************************************
* 函 数 名	: led_on
* 函数功能	: 打开指定的LED
* 输    入  : n:打开第几个LED								
* 输    出  : 无
*******************************************************************************/
void led_on(u8 n)
{u8 i=0;for(i=0;i<n;i++){*regGPBDAT&=~(1<<(4+n));//配置端口B的数据寄存器	}
//	*regGPBDAT&=~(1<<5);//配置端口B的数据寄存器
}
/*******************************************************************************
* 函 数 名	: led_on_off
* 函数功能	: 指定的LED闪烁
* 输    入  : n:第几个LED闪烁								
* 输    出  : 无
*******************************************************************************/
void led_on_off(u8 n)
{led_on(n);delay_nms(2000);led_off();delay_nms(2000);
}
/*******************************************************************************
* 函 数 名	: led_off
* 函数功能	: 关闭LED
* 输    入  :无 									 
* 输    出  :无
*******************************************************************************/
void led_off(void)
{*regGPBDAT|=(1<<5|1<<6|1<<7|1<<8);//配置端口B的数据寄存器
}/*******************************************************************************
* 函 数 名         : delay_nms
* 函数功能		     : 延时nms
* 输    入         : 
*									 	t:延时时间
* 输    出         : 无
*******************************************************************************/
void delay_nms(u32 t)
{u32 i=0;u32 j=0;for(i=0;i<t;i++){for(j=0;j<100;j++);}
}module_init(led_driver_init);
module_exit(led_driver_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");

2应用程序编写

/*************************************************************************> File Name: main.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年04月21日 星期日 15时56分47秒************************************************************************/#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>int main(void)
{#if 1
/*====================led-r====================*/    int fd=0;unsigned char n=0;fd=open("dev/led",O_RDWR);if(fd<0){printf("opening is failed\n");return -1;}while(1){write(fd,&n,1);n=2;sleep(1);}return 0;
/*========================================*/    
#endif#if 0
/*====================led-demo====================*/    int fd=0;unsigned char n=0;fd=open("dev/led",O_RDWR);if(fd<0){printf("opening is failed\n");return -1;}while(1){write(fd,&n,1);++n;if(n>0X0F){n=0;}sleep(1);}return 0;
/*========================================*/    
#endif
}

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

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

相关文章

React vs Vue.js:两种流行框架背后的设计哲学差异

Vue.js 和 React 虽然都是流行的前端框架,但在设计哲学上有一些显著差异。这些差异源自它们不同的设计目标和出发点。 vue.js Vue.js 的核心设计原则是"渐进式"。它旨在尽可能降低学习成本和入门门槛,并与其他库和项目保持良好的整合性。Vue 的设计注重简单性和直观…

C语言堆区内存管理

一、C语言编译的内存分配 二、堆区空间的分配 1、malloc函数 功能&#xff1a;从堆区分配内存 #include <stdlib.h> void *malloc(unsigned int size)//size 分配内存的字节数2、free函数 功能&#xff1a;释放内存 #include <stdlib.h> void free(void *ptr)…

数据恢复宝典:应对磁盘损坏无法读取的终极攻略

当电脑屏幕上突然弹出“磁盘损坏无法读取”的提示时&#xff0c;许多人的心情都会瞬间跌入谷底。那些存储在磁盘中的重要文件、珍贵的回忆&#xff0c;似乎在一瞬间都化为乌有。面对这样的困境&#xff0c;我们该如何应对&#xff1f;本文将深入探讨磁盘损坏无法读取的原因&…

常见的经典目标检测算法

目标检测是计算机视觉领域的一个核心任务&#xff0c;它涉及到识别图像中的物体并确定它们的位置。以下是一些常见的经典目标检测算法&#xff1a; R-CNN系列 R-CNN&#xff08;Region-based Convolutional Neural Network&#xff09;是一种用于目标检测的算法&#xff0c;它…

深度学习500问——Chapter08:目标检测(2)

文章目录 8.2.4 R-FCN 8.2.5 FPN 8.2.6 Mask R-CNN 8.2.4 R-FCN R-FCN 有哪些创新点 R-FCN仍然属于two-stage目标检测算法&#xff1a;RPN R-FCN Fully convolutional位置敏感得分图&#xff08;position-sentive score maps&#xff09; our region-based detector is ful…

开源数据库postgresql在统信系统上的离线安装shell脚本

一个tar包&#xff1a;pgsql_install.tar.bz2 #!/bin/sh echo "安装pgsql_15.4" rm -rf /home/postgres/postgresql mysqldir"/home/postgres" mkdir -p $mysqldir cp /home/pgsql_install.tar.bz2 $mysqldir cd $mysqldirtar -jxvf pgsql_install.tar.bz…

OpenVINO安装教程 npm版

从 npm Registry安装 OpenVINO™ 工具套件的英特尔发行版 请注意&#xff1a; 仅提供 JavaScript API 专用于所有主要操作系统的用户&#xff1a;Windows、Linux 和 macOS &#xff08;所有 x86_64 / ARM64 架构&#xff09; macOS 仅支持 CPU 推理 系统要求软件要求 Window…

Python 数据结构和算法实用指南(二)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;列表和指针结构 我们已经在 Python 中讨论了列表&#xff0c;它们方便而强大。通常情况下&#xff0c;我们使用 Python…

【洛谷 P8630】[蓝桥杯 2015 国 B] 密文搜索 题解(字符串+映射+排序)

[蓝桥杯 2015 国 B] 密文搜索 题目描述 福尔摩斯从 X 星收到一份资料&#xff0c;全部是小写字母组成。 他的助手提供了另一份资料&#xff1a;许多长度为 8 8 8 的密码列表。 福尔摩斯发现&#xff0c;这些密码是被打乱后隐藏在先前那份资料中的。 请你编写一个程序&…

【C语言】求最小新整数(贪心算法)

文章目录 题目描述方法一方法二 题目描述 给定一个十进制正整数n(0 < n < 1000000000)&#xff0c;每个数位上数字均不为0。n的位数为m。 现在从m位中删除k位(0<k < m)&#xff0c;求生成的新整数最小为多少&#xff1f; 例如: n 9128456, k 2, 则生成的新整数最…

windows ubuntu 子系统:肿瘤全外篇,2. fq 数据质控,比对。

目录 1.质控 2.比对并排序 3.标记PCR重复,使用picard 4.samtools建立索引 首先我们先下载一组全外显子测序数据。nabi sra库&#xff0c;随机找了一个。 来自受试者“16177_CCPM_1300019”(SRR28391647, SRR28398576)的样本“16177_CCPM_1300019_BB5”的基因组DNA配对端文库…

C#字典底层原理

一&#xff1a;前言 Dictionary是一种键值对的形式存放数据&#xff0c;即 key和value一一映射。key的类型没有限制&#xff0c;可以是整数、字符串甚至是实例对象 C#字典源码 时间复杂度 ——Add&#xff1a;O(1) ——Remove&#xff1a;一般情况下为O(1)&#xff0c;最差情…

Android开发如何从入门进阶到架构

最近按照Android学习体系整理了下Android学习课程&#xff0c;这个体系的设计是为了帮助学习者系统性地掌握Android开发的各个方面。。分为入门学习、项目实战、底层原理、性能优化、架构设计、面试和综合能力提升系列。大家按照这个路径来学习一定能够Android架构师。 需要课…

# 从浅入深 学习 SpringCloud 微服务架构(三)注册中心 Eureka(3)

从浅入深 学习 SpringCloud 微服务架构&#xff08;三&#xff09;注册中心 Eureka&#xff08;3&#xff09; 段子手168 1、eureka&#xff1a;高可用的引入 Eureka Server 可以通过运行多个实例并相互注册的方式实现高可用部署&#xff0c; Eureka Server 实例会彼此增量地…

python爬虫小案例——汽车之家

本篇文章是使用bs4中的BeautifulSoup和requests解析网页和获取数据&#x1f451;&#x1f31f; 文章目录 &#x1f31f;前言一、&#x1f349;bs4中的BeautifulSoup二、&#x1f349;bs4的语法三、&#x1f349;内容实践1. 确定想要爬取的内容2. 分析网页3. 获取数据分析 &…

AI预测福彩3D➕体彩排3合并2024年4月21日预测结果

由于今天是周末&#xff0c;周末事情比较多&#xff0c;今天回来比较晚了&#xff0c;数据刚跑完&#xff0c;趁着离开奖还有一段时间&#xff0c;咱们还是把3D和排3的预测合并发布。好了&#xff0c;废话不多说&#xff0c;直接放结果吧&#xff5e; 一.4月21日3D预测结果 …

探索C++的奇妙世界:学习之旅的点点滴滴

在这个信息技术飞速发展的时代&#xff0c;编程语言作为计算机与人类沟通的桥梁&#xff0c;其重要性不言而喻。在众多编程语言中&#xff0c;C以其高效、灵活和强大的特性&#xff0c;吸引了无数编程爱好者的目光。今天&#xff0c;我将与大家分享我学习C的历程和心得&#xf…

JAVA并发编程面试题

作者有话说&#xff1a;目前正在跟新一系列的java面试题&#xff0c;持续不断更新。需要找工作或者不需要找工作的猴子们&#xff0c;都可以关注一下。着急的可以评论区留留言&#xff0c;面试文档以及简历模板。看到了我会发 1. 说说进程和线程的区别 进程 当一个程序在计算机…

java-Spring-入门学习-第二天(单例模式和多例模式)

目录 Bean作用域 单例模式(默认可以不写) Spring下的 AutoWired 依赖注入 JaveEE下的 Resource 依赖注入 多例模式 Bean作用域 ​在Spring框架中&#xff0c;Bean是按照作用域来创建的&#xff0c;常见的作用域有两种&#xff1a;Singleton 和 Prototype。Singleton (单例…

Python编程与算法面试-编程面试的重点

在求职面试的过程中&#xff0c;编程能力也是面试官非常看重的一项能力。而对于编程这项能力主要的考察点也有三个维度&#xff1a; 初级&#xff1a;编程的基本功 编程的基本功主要考察的编程语言的基本语法&#xff0c;原理知识&#xff0c;以及一些在编程过程中的常见问题…