example driver module:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <linux/cdev.h>
#define GPIO_NUMBER 149 //User LED 0. GPIO number 149. Page 71 of BB-xM Sys Ref Manual.
static dev_t first; // Global variable for the first device number
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class
static int init_result;
static ssize_t gpio_read( struct file* F, char *buf, size_t count, loff_t *f_pos )
{
char buffer[10];
int temp = gpio_get_value(GPIO_NUMBER);
sprintf( buffer, "%1d" , temp );
count = sizeof( buffer );
if( copy_to_user( buf, buffer, count ) )
{
return -EFAULT;
}
if( *f_pos == 0 )
{
*f_pos += 1;
return 1;
}
else
{
return 0;
}
}
static ssize_t gpio_write( struct file* F, const char *buf, size_t count, loff_t *f_pos )
{
printk(KERN_INFO "Executing WRITE.\n");
switch( buf[0] )
{
case '0':
gpio_set_value(GPIO_NUMBER, 0);
break;
case '1':
gpio_set_value(GPIO_NUMBER, 1);
break;
default:
printk("Wrong option.\n");
break;
}
return count;
}
static int gpio_open( struct inode *inode, struct file *file )
{
return 0;
}
static int gpio_close( struct inode *inode, struct file *file )
{
return 0;
}
static struct file_operations FileOps =
{
.owner = THIS_MODULE,
.open = gpio_open,
.read = gpio_read,
.write = gpio_write,
.release = gpio_close,
};
static int init_gpio(void)
{
//init_result = register_chrdev( 0, "gpio", &FileOps );
init_result = alloc_chrdev_region( &first, 0, 1, "gpio_drv" );
if( 0 > init_result )
{
printk( KERN_ALERT "Device Registration failed\n" );
return -1;
}
//else
//{
// printk( KERN_ALERT "Major number is: %d\n",init_result );
// return 0;
//}
if ( (cl = class_create( THIS_MODULE, "chardev" ) ) == NULL )
{
printk( KERN_ALERT "Class creation failed\n" );
unregister_chrdev_region( first, 1 );
return -1;
}
if( device_create( cl, NULL, first, NULL, "gpio_drv" ) == NULL )
{
printk( KERN_ALERT "Device creation failed\n" );
class_destroy(cl);
unregister_chrdev_region( first, 1 );
return -1;
}
cdev_init( &c_dev, &FileOps );
if( cdev_add( &c_dev, first, 1 ) == -1)
{
printk( KERN_ALERT "Device addition failed\n" );
device_destroy( cl, first );
class_destroy( cl );
unregister_chrdev_region( first, 1 );
return -1;
}
return 0;
}
void cleanup_gpio(void)
{
//unregister_chrdev( init_result, "gpio" );
cdev_del( &c_dev );
device_destroy( cl, first );
class_destroy( cl );
unregister_chrdev_region( first, 1 );
printk(KERN_ALERT "Device unregistered\n");
}
module_init(init_gpio);
module_exit(cleanup_gpio);
MODULE_AUTHOR("Sanchayan");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Beagleboard-xM GPIO Driver");
example user space app:
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
int fd;
char gpio_buffer[10];
char choice[10];
fd = open( "/dev/gpio_drv", O_RDWR );
printf( "Value of fd is: %d", fd );
if( fd < 0 )
{
printf("Cannot open device \t");
printf(" fd = %d \n",fd);
return 0;
}
printf("\nPlease enter choice: \t");
scanf( "%s", choice );
printf("Your choice is: %s \n", choice );
write( fd, choice, 1 );
read( fd, gpio_buffer, 1);
printf("GPIO value is: %s \n", gpio_buffer );
if( 0 != close(fd) )
{
printf("Could not close device\n");
}
return 0;
}
example Makefile:
# Cross compilation Makefile for ARM
KERN_SRC=/home/vm/buildroot/output/build/linux-3.2.8
KERN_COMPILER=/opt/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin
obj-m := gpio.o
all:
make -C $(KERN_SRC) ARCH=arm CROSS_COMPILE=$(KERN_COMPILER)/arm-none-linux-gnueabi- M=`pwd` modules
clean:
make -C $(KERN_SRC) ARCH=arm CROSS_COMPILE=$(KERN_COMPILER)/arm-none-linux-gnueabi- M=`pwd` clean
Link: https://coherentmusings.wordpress.com/2012/12/22/device-node-creation-without-using-mknod/
-
Put module.ko in /lib/modules/$(uname -r)/kernel/drivers/ - You may need to create the "module" directory for the first time
-
Write Udev rules file for device (in directory /etc/udev/rules.d for Debian):
example /etc/udev/rules.d/50-xpdma.rules:
KERNEL=="xpdma", GROUP="users", MODE="0666"
-
$> sudo depmod -a This will update the dependencies of the drivers
-
Check /lib/modules/$(uname -r)/modules.dep file and search for modules.ko . It should list the dependencies on other modules if any
-
add module to /etc/modules (for Debian)
-
$> sudo /sbin/reboot OR sudo udevadm trigger