1, LED drive realization principle,
2. Write LED Driver
(1) Create LED-driven device files
First step: Initialize the Cdev with the Cdev_init function
Step Two: Specify the device number
Step three: Use the Cdev_add function to add a character device to the character device array in the kernel
Fourth step: Create a struct class using the Class_create macro
Fifth step: Create a device file using the Device_create function
#define DEVICE_NAME "S3c6410_leds"//define Device file name
#define DEVICE_COUNT 1//number of created device files
#define S3C6410_LEDS_MAJOR 0//default main device number
#define S3c6410_leds_minor 234//default secondary device number
static int major = S3c6410_leds_major; Main device number
static int minor = S3c6410_leds_minor; Secondary device number
Static dev_t Dev_number; Device number
static struct Class *leds_class = NULL; struct class
static struct File_operations Dev_ops =
{
. Owner = This_modules,
. Unlocked_ioctl = S3c6410_leds_ioctl,
. write = S3c6410_leds_write
};
static struct Cdev Led_cdev; struct Cdev describing the character device
Create a device file
static int leds_create_device (void)
{
int ret = 0;
int err = 0;
Cdev_init (&leds_cdev, &dev_fops);
Leds_cdev.owner = This_modules;
if (Major > 0)
{
Dev_number = MKDEV (major, minor);
Err = Register_chrdev_region (Dev_number, Device_count, devoce_name);
if (Err < 0)
{
PRINTK (kern_warning "register_chrdev_region () failed\n");
return err;
}
}
Else
{
Err = Alloc_chrdev_region (&leds_cdev.dev, ten, Device_count, device_name);
if (Err < 0)
{
PRINTK (kern_warning "alloc_chrdev_region () failed\n");
return err;
}
Major = Major (Leds_cdev.dev);
Minor = minor (Leds_cdev.dev);
Dev_number = Leds_cev.dev;
}
ret = Cdev_add (&leds_cdev, Dev_number, Device_count);
Leds_class = Class_create (This_module, device_name);
Device_create (Leds_class, NULL, Dev_number, NULL, device_name);
return ret;
}
(2) LED driver initialization function
static int leds_init (void)
{
int ret;
ret = Leds_crerate_device ();
PRINTK (device_name "\tinitialized\n");
return ret;
}
Module_init (Leds_init);
(3) LED drive unload function
static void Leds_destroy_device (void)
{
Device_destory (Led_class, Dev_number); Remove the character device created by the Device_create function
if (Leds_class)//Destroy struct class
Class_destroy (Leds_class);
Unregister_chrdev_region (Dev_number, Device_number);
}
static void Leds_exit (void)
{
Leds_destroy_device ();
PRINTK (device_name "\texit!\n");
}
Module_exit (Leds_exit);
(4) Set register and initialize led driver
static int leds_state = 1;
static void leds_init_gpm (int leds_default)
{
Initialize S3c64xx_gpmcon
int tmp = 0;
TMP = IOREAD32 (S3c64xx_gpmcon);
TMP &= (~0XFFFF);
TMP |= 0x1111;
IOWRITE32 (TMP, S3c64xx_gpmcon);
Initialize S3c64xx_gpmpud
TMP = IOREAD32 (S3C64XX_GPMPUD);
TMP &= (~0XFF);
TMP |= 0xAA;
IOWRITE32 (TMP, S3C64XX_GPMPUD);
Initialize S3c64xx_gpmdat
TMP = IOREAD32 (S3c64xx_gpmdat);
TMP &= (~0XF);
TMP |= Leds_default;
IOWRITE32 (TMP, S3C64XX_GPMDAT);
}
static int leds_init (void)
{
int ret;
ret = Leds_create_device ();
LEDS_INIT_GPM (~leds_state);
return ret;
}
(5) Control LED
Controlling LEDs with strings
static unsigned char mem[4];
Static ssize_t s3c6410_leds_write (struct file *file, const char _user *buf, size_t count, loff_t *ppos)
{
unsigned tmp = count;
unsigned long i = 0;
memset (Mem, 0, 4);
if (Count > 4)
{
TMP = 4;
}
Copy_from_user (MEM, BUF, TMP)
for (i = 0; i < 4; i++)
{
TMP = IOREAD32 (S3c64xx_gpmdat);
if (mem[i] = = ' 1 ')
{
TMP &= (~ (1 << i));
}
Else
{
TMP |= (1 << i);
}
IOWRITE32 (TMP, S3C64XX_GPMDAT);
}
return count;
}
Controlling LEDs with I/O commands
Static long s3c6410_leds_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
{
Switch (CMD)
{
unsigned tmp;
Case 0:
Case 1:
if (Arg > 4)
Return-einval;
TMP = IOREADE32 (tmp, S3C64XX_GPMDAT);
if (cmd = = 1)
TMP &= (~ (1 << arg));
Else
TMP |= (1 << Arg);
IOWRITE32 (TMP, S3C64XX_GPMDAT);
return 0;
Default
Return-einval;
}
}
LED: Control Light Emitting diode