linux-3.0.1下ok6410的led字符设备驱动
来源:互联网 发布:python exec函数 编辑:程序博客网 时间:2024/05/22 20:27
#include <linux/kernel.h> //以便使用printk()等函数
#include <linux/module.h> //编写任何模块都需要包含此头文件,包含宏MODULE_LICENSE(‘GPL’)
#include <linux/init.h> //必须的,定义了module_init()与module_exit()宏
#include <linux/fs.h> //包含常用的数据结构,如struct file等
#include <linux/cdev.h> //该头文件定义了struct cdev数据结构,也包含了字符设备操作的相关函数
#include <linux/pci.h> //包含readl,wrietl
#include <asm/uaccess.h> //copy_to_user,copy_from_user
#include <mach/map.h>
#include <mach/regs-gpio.h> //定义了GPIO相关的数据宏
#include <plat/gpio-cfg.h> //包含了GPIO的各种配置函数,如设置输入输出,设置上拉电阻等
#include <mach/gpio-bank-m.h> //以便于使用s3c64xx_GPM
#define DEVICE_NAME "led" //定义设备名
#define LED_MAJOR 240 //主设备号
static int led_open(struct inode *inode, struct file *filp)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPMCON);
tmp = (tmp & ~(0xffff)) | (0x1111); //set the GPIO output mode
writel(tmp, S3C64XX_GPMCON);
tmp = readl(S3C64XX_GPMDAT); //读取寄存器之前的数据
tmp |= 0xf;
writel(tmp, S3C64XX_GPMDAT); //写入1让所有的灯都熄灭
printk("$$$$$$$$$$$led_open$$$$$$$$$\n");
return 0;
}
//此函数为空,我们在此不涉及设备的读操作
static ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
printk("$$$$$$$$$$led_read$$$$$$$$$\n");
return count;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char mbuf;
unsigned int tmp;
copy_from_user(&mbuf,buf,count); //将用户空间的数据复制到内核空间的mbuf
tmp = readl(S3C64XX_GPMDAT); //获取GPMDAT寄存器数据
switch(mbuf) //通过switch语句解析用户空间传下来的命令,然后case语句中对控制设备实现对应的操作
{
case 0: tmp |= (0x1);//GPM0输出高电平,led1灭
break;
case 1: tmp &= ~(0x1); //GPM0输出低电平,led1亮
break;
case 2: tmp |= (0x2);//GPM1输出高电平,led2灭
break;
case 3: tmp &= ~(0x2); //GPM1输出低电平,led2亮
break;
case 4: tmp |= (0x4);//GPM2输出高电平,led3灭
break;
case 5: tmp &= ~(0x4); //GPM2输出低电平,led3亮
break;
case 6: tmp |= (0x8);//GPM3输出高电平,led4灭
break;
case 7: tmp &= ~(0x8); //GPM3输出低电平,led4亮
break;
default:
break;
}
writel(tmp, S3C64XX_GPMDAT); //将新数据写入GPMDAT
printk("$$$$$$$$$$led_write$$$$$$$$$\n");
return count;
}
static int led_release(struct inode *inode, struct file *filp)
{
printk("$$$$$$$$$$led_release$$$$$$$$$\n");
return 0;
}
/*这个结构是字符设备驱动的核心,当应用程序操作设备文件所提供的
open,read,write等函数,最终会调用到这个结构中的对应函数*/
static struct file_operations my_fops = {
.owner = THIS_MODULE,//这是一个宏,指向编译模块时自动创建的__this_module变量
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
static int led_init(void)
{
int rc;
printk("Test led dev\n");
rc = register_chrdev(LED_MAJOR, DEVICE_NAME, &my_fops); //注册设备驱动到内核,成功返回0
/*注册失败时函数返回负整数,在此判断是否注册失败,然后对失败后进行相应的处理,好的驱动
程序应该考虑到若失败,若何妥善处理,以免造成内核崩溃等错误后果造成大的隐患*/
if(rc < 0)
{
printk("register %s mychar dev error\n", DEVICE_NAME);
return -1;
}
printk("$$$$$$$$$ register led dev OK\n");
return 0;
}
static void led_exit(void)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPMCON); //获取GPMCON寄存器数据
tmp &= (~0xffff); //清除之前设置
writel(tmp, S3C64XX_GPMCON); //配置IO模式
/*注销函数中的参数,要与注册的参数保持相同,因为只有这样才能注册什么就注销什么,不会
造成错误注销以免导致其他设备不能用,若写入的参数在内核中并不存在,注销是会失败的*/
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
printk("Good Bye!\n");
}
//动态加载驱动接口(必需)
module_init(led_init);
module_exit(led_exit);
//其它信息(非必需)
MODULE_AUTHOR("xy02261110@sina.com"); //驱动程序作者信息
MODULE_DESCRIPTION("OK6410(S3C6410) LED Driver"); //一些描述信息
MODULE_LICENSE("GPL"); //遵循的原则
接着是makefile
obj-m := led.o
<span style="font-family:Times New Roman;font-size:16px;"> </span>
然后建个makemod
make -C /forlinx/linux-3.0.1/ M=`pwd` modules
led.c,makefile,makemod放在同一个目录下,比如led_drv。通过终端进入这个目录,然后只要source makemod就可以编译成led.ko。
从图中可以看到已经生成led.ko。然后到led_drv目录下去看,果然已经有了。
为了实现驱动还要写应用程序,应用程序名为ledapp.c,代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DEVICE "/dev/myled"
int main(void)
{
int fd, i;
const unsigned char buf[i] = {0, 1, 2, 3, 4, 5, 6, 7};
fd = open(DEVICE, O_RDWR);
if(fd < 0)
{
printf("Open /dev/myled file error\n");
return -1;
}
while(1)
{
for(i = 7; i>=0; i--)
{
write(fd, &buf[i], 1);
sleep(1);
}
}
close(fd);
return 0;
}
应用程序比较简单,就是一个简单的流水灯,没有写注释。
然后makefile
CC = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc
ledapp:ledapp.o
$(CC) -o ledapp ledapp.o
ledapp.o:ledapp.c
$(CC) -c ledapp.c
clean :
rm ledapp.o
把应用程序ledapp.c和makefile放在一个目录下,比如led_app下,然后从终端中进入这一个目录,执行make就可以了。
从下图中可以看到已经生成了ledapp,到led_app目录中,看到果然已经有ledapp了。
通过sd卡可以把编译好的led.ko和ledapp放到板子上,当然还有别的办法。
先在板子的终端中输入cd sdcard进入sd卡的目录,如果led.ko和ledapp就放在sd卡的根目录下,那这样就可以了。如果放在更下层的目录,那就还要继续进入下层目录。
然后在终端中输入insmodled.ko,如果注册没有问题
继续输入 mknod/dev/myledc 2400
设备文件也创立以后就可以跑应用了,直接输入ledapp,就可以看到4个led成流水灯跑起来了。
- linux-3.0.1下ok6410的led字符设备驱动
- Linux驱动开发-OK6410-LED字符设备驱动实现过程
- OK6410 linux第一个字符型设备驱动:LED驱动
- OK6410字符设备驱动点亮LED
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- “手把手教你学linux驱动开发”OK6410系列之02---LED字符设备驱动 .
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动 .
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- 手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- 手把手教你学linux驱动开发 OK6410系列之03---LED字符设备驱动
- Linux 字符设备驱动 LED
- OK6410 linux LED驱动
- OK6410 linux LED驱动
- linux OK6410 LED驱动
- OK6410的LED驱动
- 开源电子海图和webGIS
- Ubuntu下hadoop的配置
- 删除指定文件夹下小于指定大小的全部文件
- 利用spring注解定义服务信息
- The request sent by the client was syntactically incorrect.
- linux-3.0.1下ok6410的led字符设备驱动
- 勾引蜘蛛去自己的网站提升PR之交叉连接
- iOS开发中的应用标识
- 大型网站系统架构的演化
- Api指南--Loaders介绍
- iptables里面的dport和sport
- 勾引蜘蛛去自己的网站提升PR之交叉连接
- 也谈函数闭包
- 勾引蜘蛛去自己的网站提升PR之交叉连接