mercredi 9 avril 2014

Linux - l'initialisation du pilote périphérique bras char n'est pas créer/dev / fichier - Stack Overflow


I am writing a driver for the GPIO pins on an ARM platform. My driver works correctly and I've avoided the problem until now by manually mknod'ing a device file.


my initialization code:


static int __init gpio_init (void) {


    void *ptr_error;
if (register_chrdev(249, "gpio_device", &fops) < 0){
printk(KERN_INFO "Registering device failed\n");
return -EINVAL;
}

if ((device_class = class_create(THIS_MODULE, "gpio_device"))
== NULL){
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Class creation failed\n");
return -EINVAL;
}
ptr_error = device_create(device_class, NULL, DEV_T, NULL, "gpio_device");
if (IS_ERR(ptr_error)){
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Device creation failed\n");
return -EINVAL;
}

cdev_init(&c_dev, &fops);

if (cdev_add(&c_dev, DEV_T, 1)){
device_destroy(device_class, DEV_T);
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Cdev add failed\n");
return -EINVAL;
}
printk(KERN_INFO "Guten tag, GPIO driver initialized\n");
return SUCCESS;

}


This runs with no errors, except no file "gpio_device" is created in /dev.


I'm cross compiling for ARM onto kernel 2.6.39.4. (using arm-linux-gcc)


As I understand it, device_create should be creating the /dev file.




I tried running your code and found a few mistakes:



  • When you register with register_chrdev(), you should unregister with unregister_chrdev(). unregister_chrdev_region() is used to unregister a registration done with alloc_chrdev_region() or register_chrdev_region().


  • A call to register_chrdev() registers minor numbers 0-255 for the given major, and sets up a default cdev structure for each, therefore, you do not need to deal with the cdev_init() & cdev_add().


  • You should check the error using IS_ERR & PTR_ERR for class_create() & device_create() as PTR_ERR will turn the return pointer to the error code with a cast.



You can read more here: Char Device Registration.


After applying the modification I mentioned, the /dev/gpio_device is created without mknod:


int init_module(void)
{
void *ptr_error;
struct cdev* c_dev;
int result=0;

/* register_chrdev */
result=register_chrdev(my_major, "gpio_device", &fops);
if (result < 0)
{
printk(KERN_INFO "Registering device failed\n");
return result;
}

DEV_T = MKDEV(my_major, my_minor);

/* class_create */
device_class = class_create(THIS_MODULE, "gpio_device");
if (IS_ERR(device_class))
{
unregister_chrdev(my_major, "gpio_device");
printk(KERN_INFO "Class creation failed\n");
return PTR_ERR(device_class);
}

/* device_create */
ptr_error = device_create(device_class, NULL, DEV_T, NULL, "gpio_device");
if (IS_ERR(ptr_error))
{
class_destroy(device_class);
unregister_chrdev(my_major, "gpio_device");
printk(KERN_INFO "Device creation failed\n");
return PTR_ERR(ptr_error);
}

/* //removed
cdev_init(&c_dev, &fops);
if (cdev_add(&c_dev, DEV_T, 1)){
device_destroy(device_class, DEV_T);
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Cdev add failed\n");
return -EINVAL;
}*/

printk(KERN_INFO "Guten tag, GPIO driver initialized\n");
return SUCCESS;
}



I just figured out what was going on here. We are using BuildRoot to create our custom linux, and the it turns out we had compiled out the udev device file management system.


So that's why this doesn't work.



I am writing a driver for the GPIO pins on an ARM platform. My driver works correctly and I've avoided the problem until now by manually mknod'ing a device file.


my initialization code:


static int __init gpio_init (void) {


    void *ptr_error;
if (register_chrdev(249, "gpio_device", &fops) < 0){
printk(KERN_INFO "Registering device failed\n");
return -EINVAL;
}

if ((device_class = class_create(THIS_MODULE, "gpio_device"))
== NULL){
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Class creation failed\n");
return -EINVAL;
}
ptr_error = device_create(device_class, NULL, DEV_T, NULL, "gpio_device");
if (IS_ERR(ptr_error)){
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Device creation failed\n");
return -EINVAL;
}

cdev_init(&c_dev, &fops);

if (cdev_add(&c_dev, DEV_T, 1)){
device_destroy(device_class, DEV_T);
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Cdev add failed\n");
return -EINVAL;
}
printk(KERN_INFO "Guten tag, GPIO driver initialized\n");
return SUCCESS;

}


This runs with no errors, except no file "gpio_device" is created in /dev.


I'm cross compiling for ARM onto kernel 2.6.39.4. (using arm-linux-gcc)


As I understand it, device_create should be creating the /dev file.



I tried running your code and found a few mistakes:



  • When you register with register_chrdev(), you should unregister with unregister_chrdev(). unregister_chrdev_region() is used to unregister a registration done with alloc_chrdev_region() or register_chrdev_region().


  • A call to register_chrdev() registers minor numbers 0-255 for the given major, and sets up a default cdev structure for each, therefore, you do not need to deal with the cdev_init() & cdev_add().


  • You should check the error using IS_ERR & PTR_ERR for class_create() & device_create() as PTR_ERR will turn the return pointer to the error code with a cast.



You can read more here: Char Device Registration.


After applying the modification I mentioned, the /dev/gpio_device is created without mknod:


int init_module(void)
{
void *ptr_error;
struct cdev* c_dev;
int result=0;

/* register_chrdev */
result=register_chrdev(my_major, "gpio_device", &fops);
if (result < 0)
{
printk(KERN_INFO "Registering device failed\n");
return result;
}

DEV_T = MKDEV(my_major, my_minor);

/* class_create */
device_class = class_create(THIS_MODULE, "gpio_device");
if (IS_ERR(device_class))
{
unregister_chrdev(my_major, "gpio_device");
printk(KERN_INFO "Class creation failed\n");
return PTR_ERR(device_class);
}

/* device_create */
ptr_error = device_create(device_class, NULL, DEV_T, NULL, "gpio_device");
if (IS_ERR(ptr_error))
{
class_destroy(device_class);
unregister_chrdev(my_major, "gpio_device");
printk(KERN_INFO "Device creation failed\n");
return PTR_ERR(ptr_error);
}

/* //removed
cdev_init(&c_dev, &fops);
if (cdev_add(&c_dev, DEV_T, 1)){
device_destroy(device_class, DEV_T);
class_destroy(device_class);
unregister_chrdev_region(DEV_T, 1);
printk(KERN_INFO "Cdev add failed\n");
return -EINVAL;
}*/

printk(KERN_INFO "Guten tag, GPIO driver initialized\n");
return SUCCESS;
}


I just figured out what was going on here. We are using BuildRoot to create our custom linux, and the it turns out we had compiled out the udev device file management system.


So that's why this doesn't work.


0 commentaires:

Enregistrer un commentaire