led驱动

//***********************led_driver.c**********************************************/#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>


static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev;


//这个是设备的名称,也就是对应在/dev/test-dev
#define DEV_NAME "test-dev"
//LED灯IO口的地址,也就是刚刚我们在上面的芯片手册看到的Address
#define GPM4COM     0x110002E0
//定义配置模式的指针变量
volatile unsigned long *led_config = NULL ; 
//定义配置状态的指针变量
volatile unsigned long *led_dat = NULL ; 
//open方法,对LED灯进行初始化
int led_open(struct inode *inode, struct file *filp)
{
printk("led_open\n");//上层程序对LED进行Open操作的时候会执行这个函数
//先对LED的端口进行清0操作
*led_config &= ~((0xf<<(3*4)) | (0xf<<(2*4)) | (0xf<<(1*4)) | (0xf<<(0*4)));
//将4个IO口16位都设置为Output输出状态
*led_config |= ((0x1<<(3*4)) | (0x1<<(2*4)) | (0x1<<(1*4)) | (0x1<<(0*4)));
return 0;
}
//write方法
int led_write(struct file *filp , const char __user *buf , size_t count , loff_t *f_pos)
{
int val ; 
//注意,这里是在内核中进行操作,我们需要使用copy_from_user这个函数将用户态的内容拷贝到内核态
copy_from_user(&val , buf , count);
//以下就是当val是哪个值的时候,led就执行相应的操作,这里不多说
switch(val)
{
case 0 : 
       //对状态寄存器进行赋值,以下雷同
printk(KERN_EMERG"led1_on\n");
*led_dat &= ~(1<<0) ;
break ;
case 1 :
printk(KERN_EMERG"led2_on\n");
*led_dat &= ~(1<<1) ;
break ;
case 2 :
printk(KERN_EMERG"led3_on\n");
*led_dat &= ~(1<<2) ;
break ;
case 3 :
printk(KERN_EMERG"led4_on\n");
*led_dat &= ~(1<<3) ; 
break ;
case 4 :
printk(KERN_EMERG"ledall_on\n");
*led_dat &= ~((1<<0) | (1<<1) |(1<<2)| (1<<3));
break ;
case 5 : 
printk(KERN_EMERG"ledall_off\n");
*led_dat |= ((1<<0) | (1<<1) |(1<<2)| (1<<3)) ;
break ;


}
return 0;
}
//close方法
int led_close(struct inode *inode, struct file *filp)
{
printk("led_close\n");
*led_dat |= (1<<0) | (1<<1) | (1<<2) | (1<<3);  //全灭,因为高电平是灭的,0xf ----> 1111
return 0;
}
//用ioctl这个方法也可以实现LED的操作的,自己去实现吧
#if 0
long led_ioctl(struct file *filp, unsigned int request, unsigned long arg)
{
switch(request)
{
case 0:
printk(KERN_EMERG"led1 on\n");
*led_dat &=~(1<<0) ;
break;


case 1:
printk(KERN_EMERG"led2 on\n");
*led_dat &=~(1<<1) ;
break;


case 3:
printk(KERN_EMERG"led3 on\n");
*led_dat &=~(1<<2) ;
break;


case 4:
printk(KERN_EMERG"led4 on\n");
*led_dat &=~(1<<3) ;
break ;
default : 
*led_dat |= 0xf ;
}
}
#endif
//对方法进行初始化
struct file_operations fops = {
.owner = THIS_MODULE ,
.open = led_open,
.release = led_close,
// .unlocked_ioctl = led_ioctl,
.write = led_write,
};
//主设备号
int major ;
//启动函数
static __init int test_init(void)
{
printk("led_init\n");
major = register_chrdev(0, DEV_NAME, &fops);
firstdrv_class = class_create(THIS_MODULE, DEV_NAME);
firstdrv_class_dev = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, DEV_NAME); /* /dev/xyz */



led_config = (volatile unsigned long *)ioremap(GPM4COM , 16);
led_dat = led_config + 1 ;
return 0;
}
//注销函数
static __exit void test_exit(void)
{
printk("led_exit\n");
unregister_chrdev(major, DEV_NAME);
device_destroy(firstdrv_class,  MKDEV(major, 0));
class_destroy(firstdrv_class);
iounmap(led_config);
}


module_init(test_init);
module_exit(test_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("hai");

MODULE_VERSION("2017.4.29");

//****************myled.c*********************************************//

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(int argc, char **argv)
{
int fd;
int val = 0 ;
//打开对应的设备
fd = open("/dev/test-dev",O_RDWR) ;
if(-1 == fd)
{
printf("open fair!\n");
return -1 ;
}

while(1){
val = 0 ;
write(fd , &val , 4);
sleep(1);
val = 1 ;
write(fd , &val , 4);
sleep(1);
val = 2 ;
write(fd , &val , 4);
sleep(1);
val = 3 ;
write(fd , &val , 4);
sleep(1);
val = 5 ;
write(fd , &val , 4);
sleep(1);

return 0;
}

//**********************Makefile*******************************************

KERN_DIR = /home/tools/linux-3.5


all:
make -C $(KERN_DIR) M=`pwd` modules 


clean:
make -C $(KERN_DIR) M=`pwd` clean
rm -rf modules.order


obj-m += led_driver.o


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZHULINHAIBAO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值