LED驱动程序(GPIO常见接口)


前言

基于imx283a的一个简单驱动程序


在这里插入图片描述

一、GPIO申请

int gpio_request(unsigned gpio, const char *label) //申请引脚资源
gpio:为对应哪一个引脚
label:引脚名

#define LED1_GPIO	MXS_PIN_TO_GPIO(PINID_SAIF1_SDATA0)//p3.26
gpio_request(LED1_GPIO,"led1");

二、操作函数

int gpio_direction_output(unsigned gpio, int value)//引脚作为输出是一定要调此函数   
int gpio_direction_input(unsigned gpio)          //作为输入时调用
int gpio_get_value(unsigned int gpio)            //读取引脚状态
void gpio_set_value(unsigned int gpio, int value)  //写操作
gpio:哪个引脚
value:设置高低电平   0 or 1

gpio_direction_output(LED1_GPIO,data[0]);   //写

gpio_direction_input(LED1_GPIO);      //读引脚之前要调用
ret = gpio_get_value(LED1_GPIO);	  //读
gpio_set_value(LED1_GPIO,data[0]);    //写
注:IO脚只能是输出或者输入 不能同时满足 即输出的值再用get_value得到的不一定正确    只能用变量来维护

三、GPIO释放

void gpio_free(unsigned gpio)

gpio_free(LED1_GPIO);

ioctl、write控制亮灭 read、ioctl实时读取 led.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/capability.h>
#include <linux/rtc.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <../arch/arm/mach-mx28/mx28_pins.h>

#define DEVICE_NAME	"imx28x_led"
#define LED1_GPIO	MXS_PIN_TO_GPIO(PINID_SAIF1_SDATA0)

static int 	led_open(struct inode *inode, struct file *filp);
static int  led_release(struct inode *inode, struct file *filp);
static int 	led_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg);
static int 	led_init(void);
static void led_exit(void);
static ssize_t 	led_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
static ssize_t  led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);


char ledstatu;
static int led_open(struct inode *inode, struct file *filp)
{
	gpio_request(LED1_GPIO,"led1");
	gpio_direction_output(LED1_GPIO,1);
	ledstatu = 0;
	return 0;
}
static int  led_release(struct inode *inode, struct file *filp)
{
	gpio_free(LED1_GPIO);
	return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
	char data[2];
	
	copy_from_user(data,buf,count);
	gpio_direction_output(LED1_GPIO,data[0]);
	ledstatu = data[0];
	return count;
}
static ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	copy_to_user(buf, &ledstatu, 1);

	return 1;
}

static int led_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
{
	switch(command)
	{
		case 0:
			gpio_direction_output(LED1_GPIO,1);
			ledstatu = 0;
			break;
		case 1:
			gpio_direction_output(LED1_GPIO,0);	
			ledstatu = 1;
			break;
		case 2:
			copy_to_user(&arg,(int *)&ledstatu,1);
			break;
	}

	return 0;
}


static struct file_operations led_fops =
{
	.owner		= THIS_MODULE,
	.open 		= led_open,
	.release	= led_release,
	.ioctl		= led_ioctl,
	.read  		= led_read,
};

static struct miscdevice led_miscdevice =
{
	.minor  = MISC_DYNAMIC_MINOR,   //次设备
	.name	= DEVICE_NAME,			//设备名   open调用时的名称
	.fops	= &led_fops,			//操作结构体实现功能
};



static int __init led_init(void)
{
	misc_register(&led_miscdevice);
	return 0;
}

static void __exit led_exit(void)
{
	misc_deregister(&led_miscdevice);
}


module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("Dual BSD/GPL");

main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <limits.h>
#include <sys/ioctl.h>
#include <time.h>
#include <pthread.h>

int main(void)
{
	int fd;
	char buf[2];
	int cmd;

	fd = open("/dev/imx28x_led", O_RDWR);
	if (fd < 0) 
	{
		perror("open /dev/imx283_led");
		return;
	}

	while(1)
	{
		printf("pleasure input led1 status....\n");
		scanf("%d", &cmd);
		
//		write(fd,&(char)cmd,1);
		ioctl(fd, cmd, 1); 			 //写状态
//		read(fd, buf, 1);  			 //read 读取状态
		ioctl(fd,2,cmd);    		 //ioctl读取状态
		printf("led1 status:%d\r\n",cmd);
	}

	close(fd);
}


实现一个混杂设备对应一个io。

init:
init时进行一个io对应一个混杂设备的注册(遍历注册)、对混杂设备的成员进行赋值,公用一个操作结构体,动态注册次设备号所得到的次设备号,作为数组的索引,类似于奖所有的io脚及信息按次设备号进行排序

操作时:
要进行某个io的操作时,用户层调用open进而进入gpio_open,根据调用时所得到的inode获得minor
通过minor找到对应io脚的pin,再进行gpio_request的申请,之后将io信息的地址通过filp->private_data绑定
方便之后调用write,read,ioctl时知道对应知道操作那个引脚

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/capability.h>
#include <linux/rtc.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/slab.h>


#include <../arch/arm/mach-mx28/mx28_pins.h>
#include "gpio.h"

#define  ZLG_IMX_283   0
#define  ZLG_IMX_287   1
#define  ZLG_IMX_280   2

extern int zlg_board_type;


struct gpio_info {
	u32  	 	   pin;
	char 	 	   pin_name[20];
	struct miscdevice *pmiscdev;
};

static struct gpio_info *gpio_info_file[255];

static struct gpio_info *all_gpios_info;

static struct gpio_info all_gpios_info_287B[] ={
};

static struct gpio_info all_gpios_info_280[] ={

};

static struct gpio_info all_gpios_info_283[] ={
        {PINID_AUART0_CTS,   "gpio-DURX",       NULL},
        {PINID_AUART0_RTS,   "gpio-DUTX",       NULL},
        {PINID_AUART0_RX,    "gpio-URX0",       NULL},
        {PINID_AUART0_TX,    "gpio-UTX0",       NULL},
        {PINID_AUART1_RX,    "gpio-URX1",       NULL},
        {PINID_AUART1_TX,    "gpio-UTX1",       NULL},
        {PINID_SSP2_SCK,     "gpio-URX2",       NULL},
        {PINID_SSP2_MOSI,    "gpio-UTX2",       NULL},
        {PINID_SSP2_MISO,    "gpio-URX3",       NULL},
        {PINID_SSP2_SS0,     "gpio-UTX3",       NULL},
        {PINID_SAIF0_BITCLK, "gpio-URX4",       NULL},
        {PINID_SAIF0_SDATA0, "gpio-UTX4",       NULL},
        /* modify by luozhizhuo*/
        {PINID_GPMI_RDY3,    "gpio-CRX0", 	NULL},
        {PINID_GPMI_RDY2,    "gpio-CTX0", 	NULL},
        {PINID_GPMI_CE3N,    "gpio-CRX1", 	NULL},
        {PINID_GPMI_CE2N,    "gpio-CTX1", 	NULL},
        {PINID_LCD_D22,      "gpio-RUN",        NULL},
        {PINID_LCD_D23,      "gpio-ERR",    	NULL},
        /*end modify*/
        {PINID_SSP3_MISO,    "gpio-MISO",       NULL},
        {PINID_SSP3_MOSI,    "gpio-MOSI",       NULL},
        {PINID_SSP3_SCK,     "gpio-CLK",        NULL},
        {PINID_SSP3_SS0,     "gpio-CS",         NULL},
        {PINID_PWM1,         "gpio-SDA",        NULL},
        {PINID_PWM0,         "gpio-SCL",        NULL},
        {PINID_LCD_D17,      "gpio-P1.17",      NULL},
        {PINID_LCD_D18,      "gpio-P1.18",      NULL},
        {PINID_SSP0_DATA4,   "gpio-P2.4",       NULL},
        {PINID_SSP0_DATA5,   "gpio-P2.5",       NULL},
        {PINID_SSP0_DATA6,   "gpio-P2.6",       NULL},
        {PINID_SSP0_DATA7,   "gpio-P2.7",       NULL},
        {PINID_SSP1_SCK,     "gpio-P2.12",      NULL},
        {PINID_SSP1_CMD,     "gpio-P2.13",      NULL},
        {PINID_SSP1_DATA0,   "gpio-P2.14",      NULL},
        {PINID_SSP1_DATA3,   "gpio-P2.15",      NULL},
        {PINID_SAIF0_MCLK,   "gpio-P3.20",      NULL},
        {PINID_SAIF0_LRCLK,  "gpio-P3.21",      NULL},
        {PINID_SAIF1_SDATA0, "gpio-P3.26",      NULL},
        {PINID_SPDIF,        "gpio-P3.27",      NULL},
        {0,                "",          NULL},   //the end
};


/*--------------------------------------------------------------------------------------------------------
*/
static int gpio_open(struct inode *inode, struct file *filp);
static int  gpio_release(struct inode *inode, struct file *filp);
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
static int gpio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg);
static int gpio_init(void);
static void gpio_exit(void);

/*--------------------------------------------------------------------------------------------------------
*/

static int gpio_open(struct inode *inode, struct file *filp)
{
	struct gpio_info *gpio_info_tmp;
	u32 minor = iminor(inode);

	gpio_info_tmp = gpio_info_file[minor];

	gpio_free(MXS_PIN_TO_GPIO(gpio_info_tmp->pin));
	if (gpio_request(MXS_PIN_TO_GPIO(gpio_info_tmp->pin), gpio_info_tmp->pin_name)) {
		printk("request %s gpio faile \n", gpio_info_tmp->pin_name);
		return -1;
	}

	filp->private_data = gpio_info_file[minor];

	return 0;
}

static int  gpio_release(struct inode *inode, struct file *filp)
{
	struct gpio_info *gpio_info_tmp = (struct gpio_info *)filp->private_data;

	gpio_free(MXS_PIN_TO_GPIO(gpio_info_tmp->pin));

	return 0;
}


ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,
                loff_t *f_pos)
{
	struct gpio_info *gpio_info_tmp = (struct gpio_info *)filp->private_data;
	char data[2];

	//printk("make: %s \n", gpio_info_tmp->pin_name);
	copy_from_user(data, buf, 2);

	data[0] = data[0] - '0';

        if (data[0] == 1 || data[0] == 0) {
                gpio_direction_output(MXS_PIN_TO_GPIO(gpio_info_tmp->pin), data[0]);
        }



	return count;
}


static ssize_t gpio_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	struct gpio_info *gpio_info_tmp = (struct gpio_info *)file->private_data;
	int  value = 0;
	char data[3];
	static int flg	= 0;

	if (flg == 1) {
		flg = 0;
		return 0;
	}

	gpio_direction_input(MXS_PIN_TO_GPIO(gpio_info_tmp->pin));
	value = gpio_get_value(MXS_PIN_TO_GPIO(gpio_info_tmp->pin));
	data[0] = value ? 1 : 0;

	data[0] = data[0] + '0';
	data[1] = '\n';
	data[3] = -1;

	copy_to_user(buf, data, 2);
	
	flg = 1;
        return 3;
}

static int gpio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
{
	struct gpio_info *gpio_info_tmp = (struct gpio_info *)flip->private_data;
	int  data = 0;
	
	switch (command) {
	case SET_GPIO_HIGHT: 
		gpio_direction_output(MXS_PIN_TO_GPIO(gpio_info_tmp->pin), 1);
		break;
	
	case SET_GPIO_LOW:
		gpio_direction_output(MXS_PIN_TO_GPIO(gpio_info_tmp->pin), 0);
		break;

	case GET_GPIO_VALUE:
		gpio_direction_input(MXS_PIN_TO_GPIO(gpio_info_tmp->pin));
		data = gpio_get_value(MXS_PIN_TO_GPIO(gpio_info_tmp->pin));
		data = data ? 1 : 0;

		copy_to_user((void *)arg, (void *)(&data), sizeof(int));
		break;
	

	default:
		printk("cmd error \n");
		
		return -1;
	}

	return 0;
}


static struct file_operations gpio_fops={
	.owner		= THIS_MODULE,
	.open 		= gpio_open,
	.write		= gpio_write,
	.read		= gpio_read,
	.release	= gpio_release,
	.ioctl		= gpio_ioctl,
};

	

static int __init gpio_init(void)
{
	int i = 0;
	int ret = 0;

	if (zlg_board_type == ZLG_IMX_283) {
		all_gpios_info = all_gpios_info_283;
	} else if(zlg_board_type == ZLG_IMX_287) {
		all_gpios_info = all_gpios_info_287B;
	} else if(zlg_board_type == ZLG_IMX_280) {
		all_gpios_info = all_gpios_info_280;
	}

	
	for (i = 0; all_gpios_info[i].pin != 0; i++) {
		all_gpios_info[i].pmiscdev = kmalloc(sizeof(struct miscdevice), GFP_KERNEL);
		if (all_gpios_info[i].pmiscdev == NULL) {
			printk("unable to malloc memory \n");
			return -1;
		}

		
		memset(all_gpios_info[i].pmiscdev, 0, sizeof(struct miscdevice));
		all_gpios_info[i].pmiscdev->name  = all_gpios_info[i].pin_name;
		all_gpios_info[i].pmiscdev->fops  = &gpio_fops;	
		all_gpios_info[i].pmiscdev->minor = MISC_DYNAMIC_MINOR;

		ret = misc_register(all_gpios_info[i].pmiscdev);
		if (ret) {
			printk("misc regist faile \n");
			return -1;
		}

		gpio_info_file[all_gpios_info[i].pmiscdev->minor] = &(all_gpios_info[i]);
		
		printk("build device i:%d dev:/dev/%s \n", i, all_gpios_info[i].pmiscdev->name);
	}

	if (zlg_board_type == ZLG_IMX_283) {
		printk("zlg EasyARM-imx283 gpio driver up. \n");
	} else if(zlg_board_type == ZLG_IMX_287) {
		printk("zlg EasyARM-imx287 gpio driver up. \n");
	} else if(zlg_board_type == ZLG_IMX_280) {
		printk("zlg EasyARM-imx280 gpio driver up. \n");
	} 

	return 0;
}

static void __exit gpio_exit(void)
{
	int i = 0;

	for (i = 0; all_gpios_info[i].pin != 0; i++) {
		misc_deregister(all_gpios_info[i].pmiscdev);
	}
	printk("zlg EasyARM-imx28xx gpio driver down.\n");
}

module_init(gpio_init);
module_exit(gpio_exit);


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值