【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 ( ...
随机推荐
- 【leetcode】1258. Synonymous Sentences
题目如下: Given a list of pairs of equivalent words synonyms and a sentence text, Return all possible sy ...
- sublime text 编辑器的操作
我一直在用的代码编辑器是sublime text,然后总结了一些相关的操作方法. 一 环境操作 1.放大显示比例:Ctrl+ 2.缩小显示比例:Ctrl- 3.分屏:Alt+ Shift +数字 ...
- react-router中,<switch>
有<Switch>标签,则其中的<Route>在路径相同的情况下,只匹配第一个,这个可以避免重复匹配: 无<Switch>标签,则其中的<Route>在 ...
- npm全局路径及cache路径设置
1.网上安装node的教程很多,下载安装包,自定义路径安装即可: 2.安装完成node默认npm已安装,可以通过npm安装其他包.cmd命令分别 node -v 或 npm -v 可以查看安 ...
- Jmeter -- 同步定时器
作用: 模拟并发. 设置一个阀值(请求数量),当请求数达到这个阀值时,允许请求同时发出.例如:想测试一座桥的并发(忽略载重等其他因素,只考虑通过),那么并发的请求就是类似于多少辆车可同时通过桥,而车辆 ...
- python学习之路(7)
调用函数 Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档: http: ...
- Java并发编程的艺术笔记(五)——Java中的锁
一.Lock接口的几个功能: 显示的获取和释放锁 尝试非阻塞的获取锁 能被中断的获取锁 超时获取锁 使用方式: Lock lock = new ReentrantLock(); lock.lock() ...
- 一款兼容性较强的H5播放器-Mediaelementjs
特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...
- Linux高级调试与优化——Address Sanitizer
Address Sanitizer ASAN最早可以追溯到 LLVM 的 sanitizers项目(https://github.com/google/sanitizers),这个项目包含了Addre ...
- Nature/Science 论文阅读笔记
Nature/Science 论文阅读笔记 Unsupervised word embeddings capture latent knowledge from materials science l ...