一、根据下面的应用程序代码,试写出对应的LED灯的字符设备驱动程序。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc,char *argv[]){
int fd;
int value[10];
fd=open(“/dev/chr2”,O_RDWR);
if(fd<0){
perror(“open error”);
exit(1);
}
while(1)
{ value="LED_ON";
write(fd,&value,strlen(value));
sleep(1);
value="LED_OFF";
write(fd,&value,strlen(value));
sleep(1);
}
close(fd);
return 0;
}
二、程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <string.h>
#define GPX2_CON 0x11000C40
#define GPX2_SIZE 8
struct cha_dev{
unsigned int dev_major;
struct class *cls;
struct device *devs;
unsigned int *virt_base;
};
struct cha_dev *c_dev;
int led_open(struct inode *fnod, struct file *filp)
{
printk("%s\n",__FUNCTION__);
return 0;
}
char kernel_value[10];
ssize_t led_write(struct file *filp, const char *buff, size_t count, loff_t *offp)
{
copy_from_user(&kernel_value,buff,count);
if(strcmp(kernel_value,"LED_ON")==0){
writel(readl(c_dev->virt_base+1)|(0x1<<7),c_dev->virt_base+1);
}else if(strcmp(kernel_value,"LED_OFF")==0){
writel(readl(c_dev->virt_base+1)&(~(0x1<<7)),c_dev->virt_base+1);
}
return 0;
}
struct file_operations myops={
.open=led_open,
.write=led_write,
};
static int __init led_init(void){
int ret=0;
c_dev=kmalloc(sizeof(struct cha_dev),GFP_KERNEL);
if(c_dev==NULL)
{
printk(KERN_ERR "malloc error\n");
return -ENOMEM;
}
c_dev->dev_major=register_chrdev(0, "led", &myops);
if(c_dev->dev_major<0)
{
printk(KERN_ERR "register_chrdev error\n");
ret = -ENODEV;
goto err_0;
}
c_dev->cls=class_create(THIS_MODULE,"mycls");
if(IS_ERR(c_dev->cls))
{
printk(KERN_ERR "class_create error\n");
ret = PTR_ERR(c_dev->cls);
goto err_1;
}
c_dev->devs=device_create(c_dev->cls,NULL,MKDEV(c_dev->dev_major,0),NULL,"chr2");
if(IS_ERR(c_dev->devs))
{
printk(KERN_ERR "device_create error\n");
ret = PTR_ERR(c_dev->devs);
goto err_2;
}
c_dev->virt_base=ioermap(GPX2_CON,GPX2_SIZE);
if(c_dev->virt_base== NULL)
{
printk(KERN_ERR "ioremap error\n");
ret = -ENOMEM;
goto err_3;
}
writel((readl(c_dev->virt_base)&(~0xf<<4*7)|(0x1<<4*7)),c_dev->virt_base);
return ret;
err_3:
device_destroy(c_dev->cls, MKDEV(c_dev->dev_major, 0));
err_2:
class_destroy(c_dev->cls);
err_1:
unregister_chrdev(c_dev->dev_major, "chr2");
err0:
kfree(c_dev);
return ret;
}
static int __exit led_exit(void){
iounmap(c_dev->virt_base);
device_destroy(c_dev->cls, MKDEV(c_dev->dev_major, 0));
class_destroy(c_dev->cls);
unregister_chrdev(c_dev->dev_major, "chr2");
kfree(c_dev);
}
module _init(led_init);
module _exit(led_exit);
MODULE_LICENSE(“GPL”);