本文基于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驱动)的更多相关文章

  1. 【转】深入浅出:Linux设备驱动之字符设备驱动

    深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...

  2. Linux驱动设计——字符设备驱动(一)

    Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...

  3. 【Linux-驱动】简单字符设备驱动结构和初始化

    (1)在编写简单字符设备驱动的时候,首先要申请一个设备结构struct cdev: struct cdev { struct kobject kobj; struct module *owner; / ...

  4. Linux 简单字符设备驱动程序 (自顶向下)

    第零章:扯扯淡 特此总结一下写的一个简单字符设备驱动程序的过程,我要强调一下“自顶向下”这个介绍方法,因为我觉得这样更容易让没有接触过设备驱动程序的童鞋更容易理解,“自顶向下”最初从<计算机网络 ...

  5. 【转】linux设备驱动程序之简单字符设备驱动

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...

  6. 手把手教Linux驱动3-之字符设备架构详解,有这篇就够了

    一.Linux设备分类 Linux系统为了管理方便,将设备分成三种基本类型: 字符设备 块设备 网络设备 字符设备: 字符(char)设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程 ...

  7. 深入浅出:Linux设备驱动之字符设备驱

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...

  8. 【Linux驱动】字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...

  9. linux设备驱动之字符设备驱动模型(1)

    一:字符设备驱动 在linux下面,应用层看到的一切皆为文件(名字)所有的设备都是文件,都可以调用open,read,write来操作,而在内核中每个中每个设备有唯一的对应一个设备号: APP   ( ...

随机推荐

  1. [CF1105E] Helping Hiaset

    问题描述 你在某社交网站上面注册了一个新账号,这个账号有\(n(n\leq 10^5)\)次记录.要么就是你更改过一次ID,要么就是一个ID为\(s(|s|\leq 40)\)的朋友访问过你的空间. ...

  2. vue的组件创建和使用

    首先说一下vue组件 什么是组件? 在我的理解,vue的所有页面内容都是组件. 什么是父子组件? 因为所有的页面内容都是组件,那么怎么区分父子组件呢?其实很简单,现在有一个页面,在js里面的 comp ...

  3. centos7排查swap占用过高

    使用free -h 查看发现服务器在可用内存还有91G的情况下,使用Swap分区空间 查看具体是哪进程在占用Swap分区 ###for i in $( cd /proc;ls |grep " ...

  4. python使用配置文件

    通过配置文件将变量暴露给用户修改 标准库模块configparser,从而可在配置文件中使用标准格式. 必须使用[files].[colors]等标题将配置文件分成几部分(section).标题的名称 ...

  5. “不是一个有效的Win32应用程序”

    造冰箱的大熊猫@cnblogs 2018/10/23 今天在Windows计算机上安装一个应用程序时遇到“不是一个有效的Win32应用程序”错误.原以为是应用程序与操作系统版本兼容问题,或者是应用程序 ...

  6. 【GDSOI2019】滑稽二乘法【数据结构】【LCT】

    Description 点数<=100000,操作数<=200000 Solution 经典的LCT维护子树路径信息的问题. 具体来说,我们对于每一个节点,它在splay上的子树对应了原树 ...

  7. Anaconda cheat sheet

    1 anaconda prompt 闪退的情况 在cmd中进入C:\ProgramData\Anaconda3\Scripts然后可以使用各种conda命令 2 anaconda 换源 # 方法参考 ...

  8. springboot+mybatis 使用事务

    一.一些概念 声明式的事务管理是基于AOP的,在springboot中可以通过@Transactional注解的方式获得支持,这种方式的优点是: 1)非侵入式,业务逻辑不受事务管理代码的污染. 2)方 ...

  9. 循环链表C语言实现

    按照单链表的设计,稍加改动.和单向链表不一样的地方,头节点不指向NULL,而是指向自己head 循环链表的判满 1)判断next是不是头结点,2)判断size /* * CycleLinkList.h ...

  10. hdfs、zookeepeer之HA模式

    HA简介 1.所谓HA,即高可用(high available) 2.消除单点故障,避免集群瘫痪,hdfs中namenode保存了整个集群的元数据,如果namenode所在机器宕机,则整个集群瘫痪,H ...