其他分享
首页 > 其他分享> > 内核驱动:led驱动

内核驱动:led驱动

作者:互联网

#include <linux/string.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <mach/gpio.h>   //包含管脚操作的相关函数
#include <linux/device.h>  //包含创建设备文件的相关函数

#define DEVICE_NAME    "MYS-SAM9X5-ledtest"         
static int LED_Major = 0;

struct cdev cdev;

/** 应用程序执行 ioctl(fd, cmd, arg)时的第 2 个参数 **/            
#define  LED_OFF      0
#define  LED_ON       1

static unsigned long led_table [] =
{
    AT91_PIN_PB18,  /**led_blue**/
    AT91_PIN_PD21,  /**led_red**/
};

/*应用程序对设备文件/dev/leds 执行 open()时, 
*就会调用MYS_SAM9X5_ledtest_open */ 
static int MYS_SAM9X5_ledtest_open(struct inode *inode, struct file *file)
{
    printk("MYS-SAM9X5-ledtest Driver Open Called!\n");
    return 0;
}

static long MYS_SAM9X5_ledtest_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    if((cmd != 1 && cmd != 0) || (arg != 1 && arg != 0))
    	return -1;

    switch(cmd)
    {
        case LED_ON: 	   
			if(arg)
			{
				at91_set_gpio_value(led_table[arg], 1);
			}
			else
			{
				at91_set_gpio_value(led_table[arg], 0);
			}
			break;
        case LED_OFF:  
			if(arg)
			{
				at91_set_gpio_value(led_table[arg], 0);
			}
			else
			{
				at91_set_gpio_value(led_table[arg], 1);
			}
			break;
        default:
			return -EINVAL;
    }
    return 0;
}

static int MYS_SAM9X5_ledtest_release(struct inode *inode, struct file *file)
{
    printk("MYS_SAM9X5_LED Driver Release Called!\n");
    return 0;
}

/*这个结构是字符设备驱动程序的核心 
  *当应用程序操作设备文件时调用的 open、read等函数, 
  *最终会调用这个结构中指定的对应函数 */
static struct file_operations MYS_SAM9X5_ledtest_fops =
{ 
    .owner  	     =   THIS_MODULE,
    .open   	     =   MYS_SAM9X5_ledtest_open, 
    .release 	     =   MYS_SAM9X5_ledtest_release,
    .unlocked_ioctl    =   MYS_SAM9X5_ledtest_ioctl,
};

static struct class *MYS_SAM9X5_ledtest_class = NULL;

/**模块的初始化函数**/ 
static int __init MYS_SAM9X5_ledtest_init(void)
{
	int result,err;   
	dev_t devno  =  MKDEV(LED_Major, 0); 
    	
/**采用自动分配主设备号**/
  	if (LED_Major)  
  	{ 
		result = register_chrdev_region(devno, 1, DEVICE_NAME);
		printk("Got the Major number by register_chrdev_region !\n ");
	}
  	else  
  	{
		result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME); 
		LED_Major=MAJOR(devno);
		printk("Got the Major number by alloc_chrdev_region !\n");
  	}  
  
  	if (result < 0)
  	{
	  	printk(DEVICE_NAME " can't register major number\n");
	    return result;
    }
    	
    printk("register MYS_SAM9X5_ledtest Driver OK! Major = %d\n", LED_Major);
    	
    /**初始化cdev结构**/
    cdev_init(&cdev,&MYS_SAM9X5_ledtest_fops);
    cdev.owner=THIS_MODULE;
    cdev.ops=&MYS_SAM9X5_ledtest_fops;
    	
	/**注册字符设备**/
  	err=cdev_add(&cdev, MKDEV(LED_Major, 0), 1);
  	if (err)
  	{
		printk("error %d adding led \n ", err);
		goto fail_cdev_add;
	}
        /**自动创建设备文件**/
	MYS_SAM9X5_ledtest_class = class_create(THIS_MODULE, DEVICE_NAME);
	if(IS_ERR(MYS_SAM9X5_ledtest_class))
	{
		printk("Err: failed in MYS_SAM9X5_ledtest class. \n");
		goto fail_create_class;
	}
	device_create(MYS_SAM9X5_ledtest_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME);

	/**初始化PB18,PD21引脚**/
	at91_set_gpio_output(AT91_PIN_PB18, 1);
	at91_set_gpio_output(AT91_PIN_PD21, 1);

	at91_set_deglitch(AT91_PIN_PB18, 1);
	at91_set_deglitch(AT91_PIN_PD21, 1);

	printk(DEVICE_NAME " initialized\n");
	
	return 0;
    	
	fail_create_class:
	cdev_del(&cdev);
	fail_cdev_add: 
	unregister_chrdev_region(devno, 1);

	return -1;
}

/**模块的撤销函数**/ 
static void __exit MYS_SAM9X5_ledtest_exit(void)
{
	printk("MYS_SAM9X5 LED DRIVER MODULE EXIT\n");
	device_destroy(MYS_SAM9X5_ledtest_class, MKDEV(LED_Major, 0));
	class_destroy(MYS_SAM9X5_ledtest_class);
	cdev_del(&cdev);
	unregister_chrdev(LED_Major, DEVICE_NAME); 
}

/**指定驱动程序的初始化函数和卸载函数**/ 
module_init(MYS_SAM9X5_ledtest_init);
module_exit(MYS_SAM9X5_ledtest_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alvin");
MODULE_DESCRIPTION("This is an example of MYS_SAM9X5_LEDTEST drivers");
MODULE_ALIAS("A simplest module.");

  

 

调用

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define LED_DEV "/dev/MYS-SAM9X5-ledtest"


int main(int argc, char **argv)
{
    int fd, ret, led_num, led_status;
    if (argc!=3 || sscanf(argv[1],"%d", &led_num)!=1  
		|| sscanf(argv[2],"%d", &led_status)!=1)
    {
        printf("\r\nPlease input correct parameters !\r\n\n");
        printf("usage:\r\n%s <led_num> <led_status>\r\n", argv[0]);
	printf("\r\nOptions:\r\n");
        printf("  led_num\t-  1 for red led, 0 for blue led.\r\n  led_status\t-  1 for ON, 0 for OFF.\r\n\n");
        exit(1);
    }

    if((led_status!=1 && led_status!=0) || (led_num!=0 && led_num!=1))
    {
         printf("\r\nError: The parameter value must be '0' or '1' !\r\n");
         printf("\r\nPlease try again !!! !\r\n\n");
         exit(1);
    }

    fd = open(LED_DEV, 0);
    if (fd < 0)
    {
        printf("\r\nFail to open device '%s'!\r\n\n", LED_DEV);
        exit(1);
    }

    ret = ioctl(fd, led_status, led_num);
    if(ret < 0)   
    {
    	printf("\r\nFail calling ioctl !\r\n\n");	
    }

    close(fd);

    return 0;
}

  

标签:led,MYS,LED,ledtest,cdev,内核,驱动,SAM9X5
来源: https://www.cnblogs.com/hshy/p/14265174.html