linux驱动程序--led(tiny6410)

来源:互联网 发布:网络诈骗怎么定罪 编辑:程序博客网 时间:2024/04/28 03:58

Tiny6410的linux驱动程序:

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/ioport.h>
#include<asm/io.h>
#include<asm/uaccess.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>


#define DEVICE_NAME "tiny6410-led"

#define LED_IOC_MAGIC 'l'
#define LED_IOCGETDAT _IOR(LED_IOC_MAGIC,1,int)      //定义ioctl命令从驱动程序当中获取参数
#define LED_IOCSETDAT _IOW(LED_IOC_MAGIC,2,int)     //定义ioctl命令向驱动程序当中传递参数

#define LED_IOC_MAXNR 2

#define GPIOK_CON0_VA GPIOK_VA_BASE
#define GPIOK_CON1_VA GPIOK_VA_BASE+0X4
#define GPIOK_DAT_VA  GPIOK_VA_BASE+0X8
#define GPIOK_PUD_VA  GPIOK_VA_BASE+0XC

#define GPIOK_PA_BASE 0x7f008800

unsigned long GPIOK_VA_BASE;

static struct resource tiny6410_led_resource={
        .name   =  "led io-mem",
        .start  =  GPIOK_PA_BASE,
        .end    =  GPIOK_PA_BASE+0x10,
        .flags  =  IORESOURCE_MEM,
};

static void tiny6410_led_pin_setup(void)
{
        unsigned long start  = tiny6410_led_resource.start;
        unsigned long size   = tiny6410_led_resource.end-start;
        unsigned long tmp;

        request_mem_region(start,size,tiny6410_led_resource.name);//分配I/O内存

        GPIOK_VA_BASE = (unsigned long)ioremap(start,size);            //映射
        printk("<1> [GPIOK_VA_BASE=0x%lx]\n",GPIOK_VA_BASE);

        tmp=readl((void*)GPIOK_CON0_VA);                                             //操作
        tmp=(tmp & ~(0xffffU<<16))|(0x1111U<<16);
        writel(tmp,(void *)GPIOK_CON0_VA);

        tmp=readl((void *)GPIOK_DAT_VA);
        tmp|=(0xF<<4);

        writel(tmp,(void *)GPIOK_DAT_VA);
}

static void tiny6410_led_pin_release(void)
{
        iounmap((void*)GPIOK_VA_BASE);                                                   //解除映射I/O内存
        release_mem_region(tiny6410_led_resource.start,tiny6410_led_resource.end-tiny6410_led_resource.start); //释放I/O内存。
}

static unsigned long tiny6410_led_getdat(void)
{
        return((readl((void *)GPIOK_DAT_VA)>>4)&0xf);
}

static void tiny6410_led_setdat(int dat)
{
        unsigned long tmp;

        tmp = readl((void *)GPIOK_DAT_VA);
        tmp = (tmp&~(0xf<<4))|((dat&0xf)<<4);
        writel(tmp,(void *)GPIOK_DAT_VA);
}



static long led_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)  //实现unlocked_ioctl设备方法
{
        int ioarg,ret;

        if(_IOC_TYPE(cmd)!=LED_IOC_MAGIC)
                return -EINVAL;
        if(_IOC_NR(cmd)>LED_IOC_MAXNR)
                return -EINVAL;

        switch (cmd){
                case LED_IOCGETDAT:
                        ioarg = tiny6410_led_getdat();
                        ret = put_user(ioarg,(int *)arg);
                        break;
                case  LED_IOCSETDAT:
                        ret = get_user(ioarg,(int *)arg);
                        tiny6410_led_setdat(ioarg);
                        break;
                default:
                        return -EINVAL;
                }
        return ret;
}

static  struct file_operations dev_fops = {                                                                 //定义了file_operations dev_fops

        .owner   = ((struct module *)0),
        .unlocked_ioctl   = led_ioctl,
};

static struct miscdevice misc={
        .minor = MISC_DYNAMIC_MINOR,
        .name  = DEVICE_NAME,
        .fops = &dev_fops,
};

static int __init dev_init(void)
{
        int ret;

        tiny6410_led_pin_setup();
        ret=misc_register(&misc);                                                                                 //注册一个混杂设备。

        printk(DEVICE_NAME" initialized minor=%d\n",misc.minor);\
        return ret;
}

static void __exit dev_exit(void)
{
        tiny6410_led_pin_release();
        misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);


Makefile程序编写:

ifneq ($(KERNELRELEASE),)
obj-m :=led.o
else
KDIR := /lib/modules/`uname -r`/build         //指示内核源代码的路径。
all:
        make -C $(KDIR) M=$(PWD) modules
clean:
        rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif

原创粉丝点击