驱动
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#define DEVICENAME "myled"
#define gpfcon_addr 0x56000050
#define gpfdat_addr 0x56000054
static unsigned int major=0 ;
static struct class *myclass=NULL;
static struct class_device *mydev;
static volatile unsigned long *gpfcon=NULL;
static volatile unsigned long *gpfdat=NULL;
#define GPFCON *gpfcon
#define GPFDAT *gpfdat
#define LED_NUM 3
static int my_dev_open(struct inode *inode, struct file *file)
{
GPFCON &=~( (3 <<8 )|(3 <<10 )|(3 <<12 ) );
GPFCON |= ((1 <<8 ) | (1 <<10 ) | (1 <<12 ));
GPFDAT |= ((7 <<4 ));
return 0 ;
}
static ssize_t my_dev_read (struct file *pfile, char __user *buf, size_t count, loff_t *ppos)
{
loff_t cur_pos =*ppos;
unsigned char i=0 ,ledbuf[10 ];
if (count<0 )
return 0 ;
if (cur_pos>=LED_NUM)
return 0 ;
if (cur_pos+count>LED_NUM)
count=LED_NUM-cur_pos;
for (i=0 ;i<LED_NUM;i++)
{
if (GPFDAT &(1 <<(i+4 )))
ledbuf[i]='1' ;
else
ledbuf[i]='0' ;
}
copy_to_user(buf,&ledbuf[cur_pos],count);
*ppos+=count;
return count;
}
static ssize_t my_dev_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
loff_t cur_pos =*ppos;
unsigned char i=0 ,ledbuf[10 ];
if (count<0 )
return 0 ;
if (cur_pos>=LED_NUM)
return 0 ;
if (cur_pos+count>LED_NUM)
count=LED_NUM-cur_pos;
copy_from_user(&ledbuf[cur_pos], buf,count);
for (i=0 ;i<count;i++)
{
if (ledbuf[i+cur_pos]=='0' )
GPFDAT &= ~(1 <<(i+3 +cur_pos));
else
GPFDAT |= (1 <<(i+3 +cur_pos));
}
*ppos+=count;
return count;
}
static loff_t my_dev_llseek (struct file *pfile, loff_t loft, int whence)
{
loff_t tmp;
switch (whence)
{
case SEEK_SET:
tmp=loft;
break ;
case SEEK_CUR:
tmp=pfile->f_pos+loft;
break ;
case SEEK_END:
tmp=LED_NUM+loft;
break ;
default :
return -EINVAL;
break ;
}
if (tmp<0 || tmp>LED_NUM)
return -EINVAL;
pfile->f_pos = tmp;
return tmp;
}
static struct file_operations my_dev_fops = {
.owner = THIS_MODULE,
.open = my_dev_open,
.write = my_dev_write,
.read = my_dev_read,
.llseek = my_dev_llseek,
};
static int my_dev_init(void )
{
major = register_chrdev(0 ,DEVICENAME, &my_dev_fops);
myclass = class_create(THIS_MODULE,DEVICENAME);
mydev=class_device_create(myclass, NULL, MKDEV(major,0 ), NULL, "led" );
gpfcon=(volatile unsigned long *)ioremap(gpfcon_addr,4 );
gpfdat=(volatile unsigned long *)ioremap(gpfdat_addr,4 );
printk("led is init...\n" );
return 0 ;
}
static void my_dev_exit(void )
{
iounmap(gpfcon);
iounmap(gpfdat);
class_device_unregister(mydev);
class_destroy(myclass);
unregister_chrdev(major, DEVICENAME);
printk("led is exit\n" );
}
module_init(my_dev_init);
module_exit(my_dev_exit);
MODULE_LICENSE("GPL" );
app
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main()
{
unsigned char rdbuf[4 ]={"0000" },wrbuf[3 ]={"110" };
int fd,tmp=0 ;
char tmp1='0' ,tmp2;
fd = open("/dev/led" ,O_RDWR);
if (fd<0 )
printf ("led open is fail\n" );
else
printf ("led open success\n" );
lseek(fd,2 ,SEEK_SET);
write(fd,&tmp1,1 );
lseek(fd,0 ,SEEK_SET);
read(fd,rdbuf,3 );
printf ("buf is %s\n" ,rdbuf);
while (1 )
{
sleep(2 );
close(fd);
return 0 ;
}
}
效果
[root@JZ2440 002 led]
led is init...
[root@JZ2440 002 led]
led open success
buf is 0110
[root@JZ2440 002 led]
led open success
buf is 1010
[root@JZ2440 002 led]
led open success
buf is 1100