驱动学习,字符驱动例程。在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);</span>
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;
- }
- 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 *~
以上是在网络资料的基础是对简单驱动开发的笔记整理,中在学习驱动的基本框架。