驱动程序开发--AT91SAM9260的GPIO驱动笔记

驱动学习,字符驱动例程。在AT91SAM9260开发板上的驱动开发

1 驱动编写

#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/atmel_pdc.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/semaphore.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/input.h>
#include <linux/errno.h>
#include <linux/irq.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/list.h>

#include <mach/board.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/at91_pio.h>

#define MY_LED_MAJOR	250

#define LED_ON 		0
#define LED_OFF 	1

struct global_dev{
	struct cdev cdev;
};
struct global_dev *global_devp;

static int led_open(struct inode *inode, struct file *filp)
{
	filp->private_data = global_devp;
	return 0;
}

static int led_release(struct inode *inode, struct file *file)
{
	return 0;
}

static int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data)
{
	switch(cmd)
	{
		case LED_ON:
			at91_set_gpio_value(AT91_PIN_PA29, 0);
			break;
		case LED_OFF:
			at91_set_gpio_value(AT91_PIN_PA29, 1);
			break;
		default:
			printk("no valid cmd input!\n");
			break;
	}
	return 0;
}

struct file_operations my_led_ctl_ops ={
	.owner = THIS_MODULE,
	.open = led_open,
	.release = led_release,
	.ioctl = led_ioctl,
};

static void led_setup(struct global_dev *dev, int index)
{
	int err;
	int devno = MKDEV(MY_LED_MAJOR, index);
	cdev_init(&dev->cdev, &my_led_ctl_ops);
	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &my_led_ctl_ops;
	err = cdev_add(&dev->cdev, devno, 1);
	if(err)
		printk("add my led setup failed!\n");
}

static int led_init(void)
{
	int ret;
	dev_t devno = MKDEV(MY_LED_MAJOR, 0);
	printk("my first driver--led!\n");
	
	at91_set_GPIO_periph(AT91_PIN_PA29, 1);
	at91_set_gpio_output(AT91_PIN_PA29, 1);
	
	ret = register_chrdev_region(devno, 1, "my_led");
	if( ret < 0) {
		printk("my_led init_module failed with %d\n", ret);
		return ret;
	}
	else
		printk("my_led init_module success!\n");


	global_devp = kmalloc(sizeof(struct global_dev), GFP_KERNEL);

	memset(global_devp, 0, sizeof(struct global_dev));

	led_setup(global_devp, 0);

	return ret;
}
static void led_exit(void)
{
	cdev_del(&global_devp->cdev);
	kfree(global_devp);
	unregister_chrdev_region(MKDEV(MY_LED_MAJOR, 0), 1);
}


MODULE_LICENSE("MYGPL");
MODULE_AUTHOR("WHF");


module_init(led_init);
module_exit(led_exit);
2 驱动程序部分编写完毕后,就是在内核中添加相应的驱动配置点击打开链接 ,并进行编译,下载

3 添加完毕后,编写相应的测试程序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

#define DEVICE_NAME "/dev/leds"
#define LED_ON	0
#define LED_OFF 1

int main(void)
{
	int fd;
	int ret;
	int i;
	printf("led_driver test!\n");

	fd = open(DEVICE_NAME, O_RDONLY);
	if(fd == -1)
		printf("open device %s error!\n", DEVICE_NAME);

	printf("fd = %d\n", fd);
	for(i = 0; i < 50; i++)
	{
		ioctl(fd, LED_OFF);
		sleep(1);
		ioctl(fd, LED_ON);
		sleep(1);
	}

	ret = close(fd);
	printf("ret = %d\n", ret);
	printf("Close led_driver!\n");
	return 0;
}
4编写Makefile文件

ARCH=arm
CROSS_COMPILE=arm-none-linux-gnueabi-

all:leds
	$(CROSS_COMPILE)gcc -o leds leds.c
	$(CROSS_COMPILE)strip leds
clean:
	@rm -vf leds *.o *~
5 编译生成可执行文件

以上是在网络资料的基础是对简单驱动开发的笔记整理,中在学习驱动的基本框架。

你可能感兴趣的:(struct,cmd,Module,File,makefile,程序开发)