终于在理解虚拟地址与物理地址后写好了第一个linux驱动——led驱动

内核版本为 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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值