【Linux 驱动】简单字符设备驱动架构(LED驱动)
本文基于icool210开发板,内核版本:linux2.6.35;
驱动代码:
(1)头文件:led.h
#ifndef __LED_H__
#define __LED_H__ #define LED_MAGIC 'l'
#define LED_1_ON _IO(LED_MAGIC, 0)
#define LED_1_OFF _IO(LED_MAGIC, 1)
#define LED_2_ON _IO(LED_MAGIC, 3)
#define LED_2_OFF _IO(LED_MAGIC, 4)
#define LED_3_ON _IO(LED_MAGIC, 5)
#define LED_3_OFF _IO(LED_MAGIC, 6)
#define LED_4_ON _IO(LED_MAGIC, 7)
#define LED_4_OFF _IO(LED_MAGIC, 8)
#define LED_5_ON _IO(LED_MAGIC, 9)
#define LED_5_OFF _IO(LED_MAGIC, 10)
#define LED_6_ON _IO(LED_MAGIC, 11)
#define LED_6_OFF _IO(LED_MAGIC, 12) #endif
(2)代码文件:led.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "led.h" #define GPBCON 0xE0200040
#define GPBDAT 0xE0200044
#define GPH0CON 0xE0200C00
#define GPH0DAT 0xE0200C04
unsigned int *led_gpb_config;
unsigned int *led_gpb_data;
unsigned int *led_gph0_config;
unsigned int *led_gph0_data; struct cdev led_dev;
dev_t devno; /****************************************************************************
** 函数名: led_open
** 功 能: led设备驱动的操作函数集的open函数
** 参 数: struct inode *pstInode
** struct file *pstFile
** 日 期: 2017年2月22日
** 作 者: Rookie
*****************************************************************************/
int led_open(struct inode *pstInode, struct file *pstFile)
{
unsigned int uiDataTemp; /*
** 配置LED对应的GPIO为Output
** LED1 -- GPB0 LED2 -- GPIO2
** LED3 -- GPB1 LED4 -- GPIO4
*/
led_gpb_config = ioremap(GPBCON, );
uiDataTemp = readl(led_gpb_config);
uiDataTemp &= 0xFFFF0000;
uiDataTemp |= 0x1111;
writel(uiDataTemp, led_gpb_config); /* LED5 -- GPH0_7 LED6 -- GPH0_5 */
led_gph0_config = ioremap(GPH0CON, );
uiDataTemp = readl(led_gph0_config);
uiDataTemp &= 0xF0FFFFF;
uiDataTemp |= 0x10100000;
writel(uiDataTemp, led_gph0_config); led_gpb_data = ioremap(GPBDAT, );
led_gph0_data = ioremap(GPH0DAT, ); return ;
} /****************************************************************************
** 函数名: led_ioctl
** 功 能: led设备驱动的操作函数集的ioctl函数
** 参 数: struct file *pstFile
** unsigned int uiCmd
** unsigned long ulArgc
** 日 期: 2017年2月22日
** 作 者: Rookie
*****************************************************************************/
long led_ioctl(struct file *pstFile, unsigned int uiCmd, unsigned long ulArgc)
{
unsigned int uiDataTemp; switch (uiCmd)
{
case (LED_1_ON):
uiDataTemp = readl(led_gpb_data);
uiDataTemp |= 0x1;
writel(uiDataTemp, led_gpb_data);
printk("led1--on\r\n");
break; case (LED_1_OFF):
uiDataTemp = readl(led_gpb_data);
uiDataTemp &= 0xFFFFFFFE;
writel(uiDataTemp, led_gpb_data);
printk("led1--off\r\n");
break; case (LED_2_ON):
uiDataTemp = readl(led_gpb_data);
uiDataTemp |= 0x4;
writel(uiDataTemp, led_gpb_data);
printk("led2--on\r\n");
break; case (LED_2_OFF):
uiDataTemp = readl(led_gpb_data);
uiDataTemp &= 0xFFFFFFFB;
writel(uiDataTemp, led_gpb_data);
printk("led2--off\r\n");
break; case (LED_3_ON):
uiDataTemp = readl(led_gpb_data);
uiDataTemp |= 0x2;
writel(uiDataTemp, led_gpb_data);
break; case (LED_3_OFF):
uiDataTemp = readl(led_gpb_data);
uiDataTemp &= 0xFFFFFFFD;
writel(uiDataTemp, led_gpb_data);
break; case (LED_4_ON):
uiDataTemp = readl(led_gpb_data);
uiDataTemp |= 0x8;
writel(uiDataTemp, led_gpb_data);
break; case (LED_4_OFF):
uiDataTemp = readl(led_gpb_data);
uiDataTemp &= 0xFFFFFFF7;
writel(uiDataTemp, led_gpb_data);
break; case (LED_5_ON):
uiDataTemp = readl(led_gph0_data);
uiDataTemp |= 0x80;
writel(uiDataTemp, led_gph0_data);
break; case (LED_5_OFF):
uiDataTemp = readl(led_gph0_data);
uiDataTemp &= 0xFFFFFF7F;
writel(uiDataTemp, led_gph0_data);
break; case (LED_6_ON):
uiDataTemp = readl(led_gph0_data);
uiDataTemp |= 0x20;
writel(uiDataTemp, led_gph0_data);
break; case (LED_6_OFF):
uiDataTemp = readl(led_gph0_data);
uiDataTemp &= 0xFFFFFFDF;
writel(uiDataTemp, led_gph0_data);
break; default:
return -EINVAL;
} return ;
} static struct file_operations led_ops =
{
.open = led_open,
.unlocked_ioctl = led_ioctl,
}; /****************************************************************************
** 函数名: led_init
** 功 能: led设备驱动初始化函数
** 参 数: void
** 日 期: 2017年2月22日
** 作 者: Rookie
*****************************************************************************/
static int __init led_init(void)
{
cdev_init(&led_dev, &led_ops); alloc_chrdev_region(&devno, , , "my_led");
cdev_add(&led_dev, devno, ); return ;
} /****************************************************************************
** 函数名: led_exit
** 功 能: led设备驱动退出函数
** 参 数: void
** 日 期: 2017年2月22日
** 作 者: Rookie
*****************************************************************************/
static void __exit led_exit(void)
{
cdev_del(&led_dev);
unregister_chrdev_region(devno, ); return;
} module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
(3)Makefile文件
obj-m := led.o
KDIR := /root/wksp/icool210/linux2.6.35-icool210-v1.
all:
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
rm -rf *.ko *.o *.order *symvers
(4)测试应用程序:app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "led.h" int main(int argc, const char *argv[])
{
int iFd;
int iLedNum;
int iLedStatus; if (argc < )
{
printf("Please Enter 3 Para!\r\n");
return -;
} iLedNum = atoi(argv[]);
iLedStatus = atoi(argv[]); iFd = open("/dev/my_led", O_RDWR); if ( == iLedNum)
{
if ( == iLedStatus)
{
ioctl( iFd, LED_1_ON);
}
else
{
ioctl( iFd, LED_1_OFF);
}
}
else if ( == iLedNum)
{
if ( == iLedStatus)
{
ioctl( iFd, LED_2_ON);
}
else
{
ioctl( iFd, LED_2_OFF);
}
}
else if ( == iLedNum)
{
if ( == iLedStatus)
{
ioctl( iFd, LED_3_ON);
}
else
{
ioctl( iFd, LED_3_OFF);
}
}
else if ( == iLedNum)
{
if ( == iLedStatus)
{
ioctl( iFd, LED_4_ON);
}
else
{
ioctl( iFd, LED_4_OFF);
}
}
else if ( == iLedNum)
{
if ( == iLedStatus)
{
ioctl( iFd, LED_5_ON);
}
else
{
ioctl( iFd, LED_5_OFF);
}
}
else if ( == iLedNum)
{
if ( == iLedStatus)
{
ioctl( iFd, LED_6_ON);
}
else
{
ioctl( iFd, LED_6_OFF);
}
} return ;
}
操作方法:
(1)编译 .ko 文件
在驱动代码路径直接执行 make
(2)编译 应用程序
arm-linux-gcc -static app.c -o app
(3)记载内核模块
insmod led.ko
(4)创建设备节点
mknod /dev/my_led c 251 0
(5) 执行应用程序
./app 1 1
【Linux 驱动】简单字符设备驱动架构(LED驱动)的更多相关文章
- 【转】深入浅出:Linux设备驱动之字符设备驱动
深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...
- Linux驱动设计——字符设备驱动(一)
Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...
- 【Linux-驱动】简单字符设备驱动结构和初始化
(1)在编写简单字符设备驱动的时候,首先要申请一个设备结构struct cdev: struct cdev { struct kobject kobj; struct module *owner; / ...
- Linux 简单字符设备驱动程序 (自顶向下)
第零章:扯扯淡 特此总结一下写的一个简单字符设备驱动程序的过程,我要强调一下“自顶向下”这个介绍方法,因为我觉得这样更容易让没有接触过设备驱动程序的童鞋更容易理解,“自顶向下”最初从<计算机网络 ...
- 【转】linux设备驱动程序之简单字符设备驱动
原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...
- 手把手教Linux驱动3-之字符设备架构详解,有这篇就够了
一.Linux设备分类 Linux系统为了管理方便,将设备分成三种基本类型: 字符设备 块设备 网络设备 字符设备: 字符(char)设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程 ...
- 深入浅出:Linux设备驱动之字符设备驱
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
- 【Linux驱动】字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...
- linux设备驱动之字符设备驱动模型(1)
一:字符设备驱动 在linux下面,应用层看到的一切皆为文件(名字)所有的设备都是文件,都可以调用open,read,write来操作,而在内核中每个中每个设备有唯一的对应一个设备号: APP ( ...
随机推荐
- 写在centos7 最小化安装之后
1.最小化安装之后首先解决联网问题(https://lintut.com/how-to-setup-network-after-rhelcentos-7-minimal-installation/) ...
- Python 正则表达式Ⅴ
正则表达式实例 字符匹配 字符类 特殊https://www.xuanhe.net/字符类
- MySQL--关于MySQL的那些练习题
之前联系了一些MySQL的查询相关知识,现在补充作为一个记录,免得自己忘记. 致谢博主:https://blog.csdn.net/dehu_zhou/article/details/52881587 ...
- SQLSERVER 连接常见问题
1.从索引 0 处开始,初始化字符串的格式不符合规范 解决办法:检查数据库连接字符串 参考链接: https://www.cnblogs.com/guodongsky/archive/2013/04/ ...
- 隐藏表单域、URL重写、cookie、session
隐藏表单域: 隐藏域是用来收集或发送信息的不可见元素,对于网页的访问者来说,隐藏域是看不见的.当表单被提交时,隐藏域就会将信息用你设置时定义的名称和值发送到服务器上. 代码格式:<input t ...
- Sqlmap自动注入--REQEST
数据段: --data sqlmap.py -u ”192.168.1.101/mullitea/login.php" --data="username&passwd=2& ...
- SpringMVC参数传递 HttpServletRequest,HttpServletResponse和HttpSession
SpringMVC参数传递 HttpServletRequest,HttpServletResponse和HttpSession 2017-11-27 16:44:51 douunderstand 阅 ...
- C++入门经典-例4.9-输出不同生命周期的变量值
1:代码如下: // 4.9.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using ...
- hibernate entitymanager的理解
hibernate EntityManager是围绕提供JPA编程接口的Hibernate Core的一个包装,支持JPA实体实例的生命周期,并允许你用标准的JavaPersistence查询语言编写 ...
- Springboot集成Swagger操作步骤
特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...