内核版本为 2.6.38
贴上代码:
#include <linux/module.h>
#include <linux/init.h>#include <linux/cdev.h>//alloc_chrdev_region ,etc
#include <linux/types.h>//dev_t
#include <linux/kdev_t.h>//MKDEV MAJOR MINOR Macro
#include <linux/fs.h>//fops alloc_chrdev_region,etc
#include <linux/ioport.h>//request_mem_region
#include <asm/io.h>//ioremap iounmap
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anfo");
#define GPKBASE_ADDR ((unsigned long)0x7F008800)
#define GPKCON0 ((unsigned long)iores)
#define GPKCON1 ((unsigned long)iores+4)
#define GPKDAT ((unsigned long)iores+8)
#define GPKPUD ((unsigned long)iores+12)
#define led_all_on() iowrite8(0,GPKDAT)//clear
#define led_all_off() iowrite8(0xFF,GPKDAT)//clear
void* iores;
struct cdev* ledDev;
struct resource* res;
dev_t dev_no;
#define DEVICE_NAME "Anfo_Led"
int ledDev_open(struct inode* ind,struct file* filp){
printk(KERN_ALERT"ledDev_open\n");
return 0;
}
int ledDev_release(struct inode* ind,struct file* filp){
printk(KERN_ALERT"ledDev_release\n");
return 0;
}
long ledDev_ioctl(struct file* filp,unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case 0:
led_all_off();
break;
case 1:
led_all_on();
break;
default:
break;
}
return 0;
}
struct file_operations ledDev_fops={
.owner=THIS_MODULE,
.open=ledDev_open,
.release=ledDev_release,
.unlocked_ioctl=ledDev_ioctl,
};
static inline void led_gpio_init(void){
iowrite16(0x1111,GPKCON0+2);//high GPK4 5 6 7 set to 0001 0001 0001 0001 for output
iowrite8(0,GPKDAT);//clear
}
int __init ledDev_init(void){
//request for the device no.
if(alloc_chrdev_region(&dev_no,0,1,DEVICE_NAME)){
printk(KERN_ALERT"alloc_chrdev_region error!\n");
goto error_alloc_chrdev_region;
}
printk(KERN_ALERT"alloc_chrdev_region done!\n");
//request for the io resource
res=request_mem_region(GPKBASE_ADDR,16,DEVICE_NAME);
if(res==NULL){
printk(KERN_ALERT"request_mem_region error! io ports were taken up!\n");
goto error_request_mem_region;
}
printk(KERN_ALERT"request_mem_region done!\n");
//ioremap!
iores=ioremap(GPKBASE_ADDR,16);
if(iores==NULL){
printk(KERN_ALERT"ioremap error!\n");
goto error_request_mem_region;
}
led_gpio_init();
printk(KERN_ALERT"ioremap done!\n");
//create the cdev struct
ledDev=cdev_alloc();
cdev_init(ledDev,&ledDev_fops);
ledDev->owner=THIS_MODULE;
//add the cdev struct
if(cdev_add(ledDev,dev_no,1))
{
printk(KERN_ALERT"cdev_add error!\n");
goto error_cdev_add;
}
printk(KERN_ALERT"cdev_add done!\n");
printk(KERN_ALERT"ledDev_init over!\n");
return 0;
error_cdev_add:
cdev_del(ledDev);
error_request_mem_region:
release_mem_region(GPKBASE_ADDR,16);
error_alloc_chrdev_region:
unregister_chrdev_region(dev_no,1);
return -1;
}
void __exit ledDev_exit(void){
cdev_del(ledDev);
printk(KERN_ALERT"cdev_del done!\n");
iounmap(iores);
printk(KERN_ALERT"iounmap done!\n");
release_mem_region(GPKBASE_ADDR,16);
printk(KERN_ALERT"release_mem_region done!\n");
unregister_chrdev_region(dev_no,1);
printk(KERN_ALERT"unregister_chrdev_region done!\n");
printk(KERN_ALERT"ledDev_exit over!\n");
}
module_init(ledDev_init);
module_exit(ledDev_exit);
在/dev文件夹下mknod之后
编写程序进行测试
#include <stdio.h>
#include <fcntl.h>
void main(){
unsigned int cmd;
int fd=open("/dev/Anfo_Led",O_RDONLY);
if(fd==-1){
printf("error!\n");
}
else printf("done!\n");
while(1){
scanf("%d",&cmd);
if(cmd==2)break;
else if(cmd==1)ioctl(fd,1);
else if(cmd==0)ioctl(fd,0);
}
close(fd);
}