前言
经过几天的学习,终于linux驱动的基本框架弄清楚了。。。真的很艰辛,,,不过终于还是熬过来了,虽然还是最基础的,,,今晚也完成了我第一个linux驱动,,,心里还是有点小兴奋的,哈哈O(∩_∩)O
一、驱动程序
LED 驱动没有什么好讲的,主要是把设备驱动框架弄清楚就可以了。这里直接上驱动源码。
我的开发板是Smart210,根据原理图,IO口输出0 led亮,输出1 led灭
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#define DEVICE_NAME "leds"
/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
/*the second parameter that application program execute*/
#define IOCTL_GPIO_ON 1
#define IOCTL_GPIO_OFF 0
/* 用来指定LED所用的GPIO引脚 */
/*appoint the pin the LED will use*/
static unsigned long leds_table [] =
{
S5PV210_GPJ2(0),
S5PV210_GPJ2(1),
S5PV210_GPJ2(2),
S5PV210_GPJ2(3),
//arch\arm\mach-s5pv210\include\mach\gpio.h
};
static char leds_name[][4]={{"LED1"},{"LED2"},{"LED2"},{"LED3"}};
#define LED_NUM ARRAY_SIZE(leds_table)
/**
*函数功能:打开/dev/led设备
*fuction:open /dev/leds device
*设备名是:/dev/leds
*devce name: /dev/leds
**/
static int my_led_open(struct inode *inode, struct file *file)
{
int i;
int err;
for (i = 0; i < LED_NUM; i++)
{
err = gpio_request(leds_table[i], leds_name[i]);
//drivers/gpio/gpiolib.c
if(err)
{
printk(KERN_ERR "failed to request S5PV210_GPH2(%d) for LED%d \n",i-1,i);
return err;
}
}
for (i = 0; i < LED_NUM; i++)
{
s3c_gpio_cfgpin(leds_table[i], S3C_GPIO_OUTPUT);//Configuration pin function:input output multiplex
gpio_set_value(leds_table[i], 1);//Set the pin level
//arch\arm\plat-samsung\gpio-config.c
// gpio_direction_output(leds_table[i], 0);//write a value to GPIO port ,also set the port to output mode
// gpio_set_value(leds_table[i], 0);
//drivers/gpio/gpiolib.c
}
printk(KERN_INFO "LEDs driver successfully close\n");
return 0;
}
static long my_led_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
arg -= 1;
if(arg > LED_NUM) {
return -EINVAL;
}
switch(cmd) {
case IOCTL_GPIO_ON:
printk("led light\n");
gpio_set_value(leds_table[arg], 0);
break;
case IOCTL_GPIO_OFF:
printk("led no light\n");
gpio_set_value(leds_table[arg], 1);
break;
default:
printk("led failed\n");
return -EINVAL;
}
return 0;
}
static int my_led_close(struct inode * inode,struct file * file)
{
int i;
for(i= 0; i < LED_NUM; i++)
gpio_free(leds_table[i]);
printk(KERN_EMERG"close success\n");
return 0;
}
struct file_operations my_led_ops = {
.owner = THIS_MODULE,
.open = my_led_open,
.unlocked_ioctl = my_led_ioctl,
.release = my_led_close,
};
static struct miscdevice led_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &my_led_ops,
};
static int __init my_led_init(void)
{
int ret;
ret = misc_register(&led_misc);
if(ret) {
printk(KERN_INFO"misc_register failed\n");
}
printk(KERN_INFO"misc_register sucessed\n");
return 0;
}
static void __exit my_led_exit(void) {
int i;
misc_deregister(&led_misc);
for(i= 0; i < LED_NUM; i++)
gpio_free(leds_table[i]);
printk(KERN_INFO "LEDs driver successfully exit\n");
}
module_init(my_led_init);
module_exit(my_led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("qigaohua");
二、应用程序
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>
#define IOCTL_GPIO_ON 1
#define IOCTL_GPIO_OFF 0
int main(int argc, char **argv)
{
int fd;
fd = open("/dev/leds",0);
if(fd < 0) {
printf("/dev/leds open failed\n");
exit(1);
}
do {
printf("/dev/leds open sucessed\n");
ioctl(fd, IOCTL_GPIO_ON, 1);
ioctl(fd, IOCTL_GPIO_OFF, 2);
ioctl(fd, IOCTL_GPIO_OFF, 3);
ioctl(fd, IOCTL_GPIO_OFF, 4);
sleep(1);
ioctl(fd, IOCTL_GPIO_ON, 1);
ioctl(fd, IOCTL_GPIO_ON, 2);
ioctl(fd, IOCTL_GPIO_OFF, 3);
ioctl(fd, IOCTL_GPIO_OFF, 4);
sleep(1);
ioctl(fd, IOCTL_GPIO_ON, 1);
ioctl(fd, IOCTL_GPIO_ON, 2);
ioctl(fd, IOCTL_GPIO_ON, 3);
ioctl(fd, IOCTL_GPIO_OFF, 4);
sleep(1);
ioctl(fd, IOCTL_GPIO_ON, 1);
ioctl(fd, IOCTL_GPIO_ON, 2);
ioctl(fd, IOCTL_GPIO_ON, 3);
ioctl(fd, IOCTL_GPIO_ON, 4);
sleep(1);
ioctl(fd, IOCTL_GPIO_OFF, 1);
ioctl(fd, IOCTL_GPIO_OFF, 2);
ioctl(fd, IOCTL_GPIO_OFF, 3);
ioctl(fd, IOCTL_GPIO_OFF, 4);
}while(0);
close(fd);
return 0;
}
三、实例测试
经过测试OK
关注公众号"小败日记",搬砖过程遇到的问题,大家一起探讨,资源共享