mini2440中提供的内核自带了LED的驱动程序,但该驱动是以杂项设备的形式编写,不太适合初学者,作者因为教学工作需要,花了一点时间,根据LDD3第三章内容将代码进行了修改,希望对一些初学者有所帮助。
注意:本案例中采用了mdev设备文件管理系统以自动生成设备节点,有兴趣的同仁可以参考本博客关于mdev的相关介绍,对于初学者,不理解的可以手动创建设备节点进行本程序的测试。
硬件连接如下,依次对应CPU上的GPB5~GPB8引脚:
驱动程序:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include //用于mdev操作
- #define DEVICE_NAME "leds"
- unsigned int gpio_major_number=0;
- struct cdev gpio_dev;
- struct class *gpio_class;
- dev_t dev_nr;
- static unsigned long led_table [] = {
- S3C2410_GPB(5),
- S3C2410_GPB(6),
- S3C2410_GPB(7),
- S3C2410_GPB(8),
- };
- static unsigned int led_cfg_table [] = {
- S3C2410_GPIO_OUTPUT,
- S3C2410_GPIO_OUTPUT,
- S3C2410_GPIO_OUTPUT,
- S3C2410_GPIO_OUTPUT,
- };
- static int sbc2440_leds_ioctl(
- struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
- {
- switch(cmd) {
- case 0:
- case 1:
- if (arg > 4) {
- return -EINVAL;
- }
- s3c2410_gpio_setpin(led_table[arg], !cmd);
- return 0;
- default:
- return -EINVAL;
- }
- }
- static struct file_operations gpio_fops = {
- .owner = THIS_MODULE,
- .ioctl = sbc2440_leds_ioctl,
- };
- static int __init dev_init(void)
- {
- int ret,i;
- for (i = 0; i < 4; i++) { //引脚初始化
- s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
- s3c2410_gpio_setpin(led_table[i], 0);
- }
- ret = alloc_chrdev_region(&dev_nr,0,1,DEVICE_NAME); //动态分配设备号
- gpio_major_number = MAJOR(dev_nr);
- printk(KERN_INFO "Major Num ->%d\n",gpio_major_number);
- if (ret<0)
- {
- printk(KERN_WARNING "gpio:can't get major number %d/n",gpio_major_number);
- return ret;
- }
- cdev_init(&gpio_dev,&gpio_fops); //初始化并向系统添加字符设备
- gpio_dev.owner = THIS_MODULE;
- // gpio_dev.ops = &gpio_fops;
- ret = cdev_add(&gpio_dev,dev_nr,1);
- if (ret)
- {
- unregister_chrdev_region(dev_nr,1);
- printk(KERN_NOTICE "Error %d adding gpio device/n",ret);
- return ret;
- }
-
- gpio_class = class_create(THIS_MODULE, "gpio_class"); //mdev相关,用于自动创建设备节点
- if(IS_ERR(gpio_class))
- {
- printk("Err: failed in creating class./n");
- return -1;
- }
- /* register your own device in sysfs, and this will cause mdev to create corresponding device node */
- device_create(gpio_class,NULL,dev_nr, NULL, "gpio_dev%d" ,0);//设备节点名称gpio_dev0
- return 0;
- }
- static void __exit dev_exit(void)
- {
- cdev_del(&gpio_dev);
- device_destroy(gpio_class,dev_nr);
- class_destroy(gpio_class);
- unregister_chrdev_region(dev_nr,1);
- }
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Allein.Cao");
测试程序:
- #include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <sys/ioctl.h>
-
-
int main(int argc, char **argv)
-
{
-
int on;
-
int led_no;
-
int fd;
-
if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 ||
-
on < 0 || on > 1 || led_no < 0 || led_no > 3) {
-
fprintf(stderr, "Usage: leds led_no 0|1\n");
-
exit(1);
-
}
-
fd = open("/dev/gpio_dev0", 0); //打开设备节点,需与驱动程序对应起来
- if (fd < 0) {
-
perror("open device leds");
-
exit(1);
-
}
-
ioctl(fd, on, led_no);
-
close(fd);
-
return 0;
-
}
阅读(1597) | 评论(0) | 转发(2) |