字符设备驱动-----控制mini2440开发板的4个led灯
2013-03-16 20:50
387 查看
正在看韦东山的教程,他写了一个控制led灯的驱动。
我也写了一个。
总结:
1)copy_from_user的用法
2)alloc_chrdev_region(&devno, 0, 4, DEVNAME); 此函数指明设备的个数。然后调用多次cdev_add创建多个字符设备。这些字符设备使用同一套函数,即struct file_operations变量中的函数:
3)为了自动创建字符设备文件,so.....(一个类,多个设备)
myclass = class_create(THIS_MODULE, "ctlled"); //create /sys/class/ctlled
for(i = 1; i <= 4; i++){//create for devices
device_create(myclass, NULL, MKDEV(MAJOR(devno), i - 1), NULL, "led%d", i); //auto create /dev/led1~4
}
源代码:
测试程序:(与韦老师提供的有点小小的改动)
我也写了一个。
总结:
1)copy_from_user的用法
//测试程序,即用户空间 char val; ... write(fd, &val, sizeof(val)); //驱动程序,即内核空间 copy_from_user(&val, (char *)buf, sizeof(char));注意:要明确val的类型,否则,可能取到的数值不正确。比如用户空间的val是int类型,而驱动部分却误写成了char类型的,就可能得不到正确数值了。(说可能,是因为不 知道目标机器是大端模式,还是小端模式);
2)alloc_chrdev_region(&devno, 0, 4, DEVNAME); 此函数指明设备的个数。然后调用多次cdev_add创建多个字符设备。这些字符设备使用同一套函数,即struct file_operations变量中的函数:
for(i = 1; i <= 4; i++){//register char device cdev_add(&firstcdev, MKDEV(MAJOR(devno), i - 1), 1); }
3)为了自动创建字符设备文件,so.....(一个类,多个设备)
myclass = class_create(THIS_MODULE, "ctlled"); //create /sys/class/ctlled
for(i = 1; i <= 4; i++){//create for devices
device_create(myclass, NULL, MKDEV(MAJOR(devno), i - 1), NULL, "led%d", i); //auto create /dev/led1~4
}
源代码:
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <linux/device.h>
//device name
#define DEVNAME "ledctl"
//cdev
struct cdev firstcdev;
dev_t devno;
//for auto creata device file
struct class *myclass;
static int first_drv_open(struct inode *inode, struct file *file)
{
//printk("first_cdrv_open\n");
int i;
int ledno = 0;
//int minor = MINOR(file->f_dentry->d_inode->i_rdev);
int minor = MINOR(inode->i_rdev);
printk("open:minor is %d\n", minor);
s3c2410_gpio_cfgpin(S3C2410_GPB(5 + minor), S3C2410_GPIO_OUTPUT); //GPBx out mode
s3c2410_gpio_setpin(S3C2410_GPB(5 + minor), 1); //ledx off
return 0;
}
static int first_drv_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos)
{
//printk("first_cdrv_write\n");
char val;
int ledno = 0;
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
printk("write:minor is %d\n", minor);
copy_from_user(&val, (char *)buf, sizeof(char));
printk("val from user is %d\n", val);
ledno = minor + 5; //led1's pin number is 5
printk("write:ledno is %d\n", minor);
s3c2410_gpio_setpin(S3C2410_GPB(ledno), (val == 0 ? 1 : 0)); //val=1 led1 on
return 0;
}
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,
};
static int first_drv_init(void)
{
int i;
cdev_init(&firstcdev, &first_drv_fops); //init cdev
alloc_chrdev_region(&devno, 0, 4, DEVNAME); //alloc char device number
printk("devno = %d\nmajor = %d\nminor = %d\n", devno, MAJOR(devno), MINOR(devno));//devno contains major and minor
for(i = 1; i <= 4; i++){//register char device cdev_add(&firstcdev, MKDEV(MAJOR(devno), i - 1), 1); }
myclass = class_create(THIS_MODULE, "ctlled"); //create /sys/class/ctlled
for(i = 1; i <= 4; i++){//create for devices
device_create(myclass, NULL, MKDEV(MAJOR(devno), i - 1), NULL, "led%d", i); //auto create /dev/led1~4
}
printk("firstdrvcdev initialized.\n");
return 0;
}
static void first_drv_exit(void)
{
int i;
unregister_chrdev_region(devno, 1); //release dev number
for(i = 0; i < 4; i++){
device_destroy(myclass, MKDEV(MAJOR(devno), i)); //del device
}
class_destroy(myclass); //del class
cdev_del(&firstcdev); //del char device
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
测试程序:(与韦老师提供的有点小小的改动)
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> /* * ledtest <dev> <on|off> */ void print_usage(char *file) { printf("Usage:\n"); printf("%s <dev> <on|off>\n",file); printf("eg. \n"); printf("%s /dev/led1 on\n", file); printf("%s /dev/led1 off\n", file); printf("%s /dev/led2 on\n", file); printf("%s /dev/led3 off\n", file); printf("%s /dev/led4 off\n", file); } int main(int argc, char **argv) { int fd; char* filename; char val; if (argc != 3) { print_usage(argv[0]); return 0; } filename = argv[1]; fd = open(filename, O_RDWR); if (fd < 0) { printf("error, can't open %s\n", filename); return 0; } if (0 == strcmp("on", argv[2])) { // ÁÁµÆ val = 1; write(fd, &val, sizeof(val)); } else if (0 == strcmp("off", argv[2])) { // ÃðµÆ val = 0; write(fd, &val, sizeof(val)); } else { print_usage(argv[0]); return 0; } return 0; }
相关文章推荐
- Linux设备驱动开发基础---字符设备驱动程序开发之mini2440_LED驱动
- 嵌入式Linux驱动开发(二)——字符设备驱动之控制LED
- 字符设备驱动控制led灯
- 基于TQ2440的led字符设备驱动
- s3c2440基于linux的gpio led字符设备驱动实践
- 11.LED驱动程序设计(1)-字符设备控制
- 嵌入式Linux字符设备入门之--LED驱动详解
- led灯实验之字符设备驱动poll操作
- linux高级字符设备驱动(一 设备Ioctl控制)
- linux-3.0.1下ok6410的led字符设备驱动
- real6410开发板Uboot中添加控制LED驱动
- LED字符设备驱动调试笔记
- 简单字符设备驱动——LED驱动
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- FL2440字符设备驱动之LED
- Linux设备驱动开发基础---字符设备驱动程序开发之mini2440_ADC驱动
- Tiny6410 LED字符设备驱动
- 手把手教你学linux驱动开发:模块编程、虚拟字符设备编程、LED字符设备驱动
- arm 驱动基础:通过次设备号精确控制led亮灭
- linux驱动开发--字符设备:通过cdd_cdev结构中的led变量区分是哪个节点,private_data使用