linux内核下点亮led(未使用中断版本)

来源:互联网 发布:男人必看网站知乎 编辑:程序博客网 时间:2024/05/23 07:25

头文件:

#ifndef _LED_CONFIG_H
#define _LED_CONFIG_H
#define LED_CON 0
#define LED_ON  1
#define LED_OFF 2
#endif

 

内核下面的驱动模块:


#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include "../led_config.h"
#include <linux/errno.h>



#define PHYS_BASE   0x56000040
#define SIZE   12

#define setbit(data,pos,len,val)  do{/
    data &=~((~(~0<<len))<<pos);/
    data |=val<<pos;/
}while(0) 

struct led_driver{
              unsigned long    gpecon;
              unsigned long    gpedat;
              unsigned long    gpeup;
              unsigned long    virt_base;
             
              struct cdev led_dev;
              unsigned long    major;
              unsigned long    minor;
              dev_t  devno;

          void (*conf)(struct led_driver *);
          void (*on)(struct led_driver *);
          void (*off)(struct led_driver *);
};

struct led_driver *md;
void con_led(struct led_driver *led)
{
    unsigned long tmp;
 
    tmp=ioread32(led->gpecon);
    setbit(tmp,24,2,1);
    iowrite32(tmp,led->gpecon);
  
   
    tmp=ioread32(led->gpeup);
    setbit(tmp,12,1,0);
    iowrite32(tmp,led->gpeup);
    printk("init config led/n");
 
}
void on_led(struct led_driver *led)
{
    unsigned long tmp;
    tmp=ioread32(led->gpedat);
    setbit(tmp,12,1,0);
    iowrite32(tmp,led->gpedat);
}
void off_led(struct led_driver *led)
{
    unsigned long tmp;
    tmp=ioread32(led->gpedat);
    setbit(tmp,12,1,1);
    iowrite32(tmp,led->gpedat);
}
int init_led_device(struct led_driver *led)
{

    led->virt_base=ioremap(PHYS_BASE,SIZE);
    led->gpecon=led->virt_base+0x0;
    led->gpedat=led->virt_base+0x04;
    led->gpeup=led->virt_base+0x08;
   
    led->conf=con_led;
    led->on=on_led;
    led->off=off_led;

    printk("init suceess/n");

    return 0;

}

int led_ioctl(struct inode *inod,struct file *filp,unsigned int cmd,unsigned long args )
{
     switch(cmd)
        {
        case LED_ON:
            md->on(md);
            break;
        case LED_OFF:
            md->off(md);
            break;
        case LED_CON:
            md->conf(md);
            break;
         default:
            printk("<kernel > don't know the cmd/n");
            return -EINVAL;
        }

     return 0;           
           

}
struct file_operations f_ops={
      .owner=THIS_MODULE,
      .ioctl=led_ioctl,
};

int init_led(void)
{
    md=kmalloc(sizeof(struct led_driver),GFP_KERNEL);
    if(NULL==md){
     printk("the kernel has no enough space/n");
         goto ERROR1;
    }
    md->major=0;
    md->minor=0;
    if(md->major){
      md->devno=MKDEV(md->major,md->minor);
      register_chrdev_region(md->devno,1,"led driver");   
    }else{
      alloc_chrdev_region(&md->devno,md->minor,1,"led driver");
      printk("<kernel>%d,%d/n",MAJOR(md->devno),MINOR(md->devno)); 
    }
    cdev_init(&md->led_dev,&f_ops);
    if(init_led_device(md)){
        printk("init the led device  failed/n");
        goto ERROR2;   
    }
    if(cdev_add(&md->led_dev,md->devno,1)){
         printk("add the led device failed/n");
                goto ERROR2;
        }

    printk("the led device been ready/n");       
    return 0;
 
ERROR2:
    unregister_chrdev_region(md->devno,1);
    kfree(md);
    return -ENODEV;
ERROR1:
    return -ENOMEM;
}

void exit_led(void)
{
    cdev_del(&md->led_dev);
    unregister_chrdev_region(md->devno,1);
    kfree(md);

}

module_init(init_led);
module_exit(exit_led);

MODULE_LICENSE("GPL");

 

 

应用层调用:

 

#include <stdio.h>
#include "../led_config.h"
#include <error.h>
#include <strings.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc ,char **argv)
{
    int fd;
    fd=open("/dev/test",O_RDWR);
    if(fd<0){
        perror("open the device");
    return -1;
    }
    if(argc!=2){
         printf("has no parment/n");
         return -1;  
    }
    ioctl(fd,LED_CON);
    if(strncasecmp(argv[1],"on",2)==0){
            printf("LED ON/n");
        ioctl(fd,LED_ON);
     }   
    if(strncasecmp(argv[1],"off",3)==0){
           printf("LED OFF/n");
       ioctl(fd,LED_OFF);
    }
    close(fd);
    return 0;
}

原创粉丝点击