NUC980开源项目34-GPIO驱动

上面是我的微信和QQ群,欢迎新朋友的加入。

 驱动源码

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

#include <mach/gpio.h>
 
#define LEDOFF 0 /* 关灯 */
#define LEDON 1 /* 开灯 */

#define DEVICE_NAME "board_led"
#define DEVICE_CNT 1
 
static int major = 0; /* 静态设备号方式的默认值 */
static int minor = 0; /* 静态设备号方式的默认值 */
 
module_param(major, int, S_IRUGO);
module_param(minor, int, S_IRUGO);
 
struct cdev *led; /* cdev 数据结构 */
static dev_t devno; /* 设备编号 */
static struct class *nuc980_led_class;
 
static int nuc980_led_open(struct inode *inode, struct file *file )
{ 
	printk(KERN_INFO DEVICE_NAME " opened!\n");
	return 0;
}
 
static int nuc980_led_release(struct inode *inode, struct file *file )
{
	printk(KERN_INFO DEVICE_NAME " closed!\n");
	return 0;
}
 
static ssize_t nuc980_led_read(struct file *file, char *buf,size_t count, loff_t *f_pos)
{
	printk(KERN_INFO DEVICE_NAME " read method!\n");
	return count;
}
 
static ssize_t nuc980_led_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)
{

	return count;
}
 
//static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long nuc980_led_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
    printk("cmd is %d,arg is %d \n",cmd,(unsigned int)(arg));
	switch(cmd)
	{
		case LEDOFF:
			{
				printk(KERN_INFO "LEDOFF \n");
				gpio_set_value(NUC980_PF7, 0);	
				break;		
			}
			
		case LEDON:
			{
				printk(KERN_INFO "LEDON \n");	
				gpio_set_value(NUC980_PF7, 1);
				break;		
			}
 
	}
	printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
	return 0;
}
 
struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = nuc980_led_read,
.write = nuc980_led_write,
.open = nuc980_led_open,
.release = nuc980_led_release,
.unlocked_ioctl = nuc980_led_ioctl
};
 
static int __init nuc980_led_init(void)
{
	int ret;
 
	/* 注册字符设备驱动 */
	if (major > 0) { /* 静态设备号 */
		devno = MKDEV(major, 0);
		ret = register_chrdev_region(devno, DEVICE_CNT, DEVICE_NAME);
        printk(KERN_ALERT "分配静态设备号: %d \n", major); 
	} else { /* 动态设备号 */
		ret = alloc_chrdev_region(&devno, 0, DEVICE_CNT, DEVICE_NAME); /* 从系统获取主设备号 */
		major = MAJOR(devno);
		minor = MINOR(minor);
        printk(KERN_ALERT "分配动态设备号: %d \n", major); 
	}
	
	if (ret < 0) {
		printk(KERN_ERR "设备号获取失败 %d \n", major); 
		return -1;
	}
	printk(KERN_ALERT " major:%d! minor:%d\n",major,minor);
	
	led = cdev_alloc(); /* 分配 led 结构 */
	if (led != NULL) { 
		cdev_init(led, &led_fops); /* 初始化 led 结构 */
		led->owner = THIS_MODULE;
		if (cdev_add(led, devno, DEVICE_CNT) != 0) { /* 增加 led 到系统中 */
			printk(KERN_ERR "add cdev error!\n");
			goto error;
		}
	} else {
		printk(KERN_ERR "cdev_alloc error!\n"); 
		return -1;
	}
 
	nuc980_led_class = class_create(THIS_MODULE, DEVICE_NAME);
	if (IS_ERR(nuc980_led_class)) { 
		printk(KERN_INFO "create class error\n");
		return -1;
	}
 
	device_create(nuc980_led_class, NULL, devno, NULL, DEVICE_NAME);
    printk(KERN_ALERT "mod init!\n"); 

    ret = gpio_request(NUC980_PF7,"NUC980_PF7");
	if(ret < 0){
		printk(KERN_EMERG "gpio_request NUC980_PF7 failed!\n");
		return ret; 
	}
	
	gpio_direction_output(NUC980_PF7,1);
	
	printk(KERN_INFO "nuc980_led_init module initialized\n");
	return 0;
 
	error:
	unregister_chrdev_region(devno, DEVICE_CNT); /* 释放已经获得的设备号 */
	return ret;
}
 
static void __exit nuc980_led_exit(void)
{
	/* 注销字符设备 */
    gpio_free(NUC980_PF7);
	cdev_del(led);/*移除字符设备*/
	unregister_chrdev_region(devno,DEVICE_CNT);/*释放设备号*/
	device_destroy(nuc980_led_class,devno);
	class_destroy(nuc980_led_class);
    printk(KERN_INFO "nuc980_led_exit module\n");
}
 
module_init(nuc980_led_init);
module_exit(nuc980_led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jun,2839084093@qq.com");

makefile

obj-m := board_led.o
 
KERNEL_SRC := /home/jun/nuc980/nuc980bsp/linux-master
SRC := $(shell pwd)
 
all:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC)
 
modules_install:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
 
clean:
	rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
	rm -f Module.markers Module.symvers modules.order
	rm -rf .tmp_versions Modules.symvers

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
 
#define IOCTL_LED_ON    1
#define IOCTL_LED_OFF   0
 
#define DEVICE_ADDR "/dev/board_led"
int main(int argc, char **argv)
{
    int fd = -1;

    fd = open(DEVICE_ADDR, 0);  // 打开设备
    if (fd < 0) {
        printf("Can't open %s\n",DEVICE_ADDR);
        return -1;
    }
    
    if (strcmp(argv[1], "on")) {
        ioctl(fd, IOCTL_LED_ON, 0);    // 点亮它
    } else{
        ioctl(fd, IOCTL_LED_OFF, 0);   // 熄灭它
    }
    
    close(fd);
    return 0;
}

测试

万用表测试IO口,有正常反转电平

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值