pwm设备驱动--platform总线

文章来源:http://blog.csdn.net/zqixiao_09/article/details/50888795

采用设备模型的概念,总线,设备,驱动。先将设备(驱动)挂载到总线上,等待另一个同名的驱动(设备),用match函数进行匹配。如果找到了就调用driver的probe函数将设备和驱动绑定在一起;当设备拔出时,driver调用remove函数清除一些相关的操作


device.c:

<span style="font-size:18px;">
#include <linux/module.h>  
#include <linux/device.h>  
#include <linux/platform_device.h>  
#include <linux/ioport.h>  

static struct resource beep_resource[] =  
{  
    [0] ={  
        .start = 0x114000a0,  
        .end =  0x114000a0 + 0x4,  
        .flags = IORESOURCE_MEM,  
    },  
  
    [1] ={  
        .start = 0x139D0000,  
        .end =  0x139D0000 + 0x14,  
        .flags = IORESOURCE_MEM,  
    }  
};  
  
static void hello_release(struct device *dev)  
{  
    printk("hello_release\n");  
    return ;  
}  
  
  
/*定义设备结构体*/
static struct platform_device hello_device=  
{  
    .name = "bigbang",  
 	.id = -1,  
    .dev.release = hello_release,  
    .num_resources = ARRAY_SIZE(beep_resource),  
    .resource = beep_resource,  
};  
  
static int hello_init(void)  
{  
    printk("hello_init");  
    return platform_device_register(&hello_device);/*将设备挂到platform总线上*/
}  
  
static void hello_exit(void)  
{  
    printk("hello_exit");
    platform_device_unregister(&hello_device);/*从platform总线上撤销*/
    return;  
}  
  
MODULE_LICENSE("GPL");  
module_init(hello_init);  
module_exit(hello_exit);  </span>

driver.c

<span style="font-size:18px;">
#include <linux/module.h>  
#include <linux/fs.h>  
#include <linux/cdev.h>  
#include <linux/device.h>  
#include <linux/platform_device.h>  
#include <asm/io.h>  
  
static int major = 250;  
static int minor=0;  
static dev_t devno;  
static struct class *cls;  
static struct device *test_device;  
           
#define TCFG0         0x0000                 
#define TCFG1         0x0004                              
#define TCON          0x0008               
#define TCNTB0        0x000C            
#define TCMPB0        0x0010             
  
static unsigned int *gpd0con;  
static void *timer_base;  
  
#define  MAGIC_NUMBER    'k'  
#define  BEEP_ON    _IO(MAGIC_NUMBER    ,0)  
#define  BEEP_OFF   _IO(MAGIC_NUMBER    ,1)  
#define  BEEP_FREQ   _IO(MAGIC_NUMBER   ,2)  
  
static void fs4412_beep_init(void)  
{     
    writel ((readl(gpd0con)&~(0xf<<0)) | (0x2<<0),gpd0con);  
    writel ((readl(timer_base +TCFG0  )&~(0xff<<0)) | (0xff <<0),timer_base +TCFG0);   
    writel ((readl(timer_base +TCFG1 )&~(0xf<<0)) | (0x2 <<0),timer_base +TCFG1 );   
  
    writel (500, timer_base +TCNTB0  );  
    writel (250, timer_base +TCMPB0 );  
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x2 <<0),timer_base +TCON );   
}  

void fs4412_beep_on(void)  
{  
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x9 <<0),timer_base +TCON );  
}  
  
void fs4412_beep_off(void)  
{  
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x0 <<0),timer_base +TCON );  
}  
  
static void beep_unmap(void)  
{  
        iounmap(gpd0con);  
        iounmap(timer_base);  
}  
  
static int beep_open (struct inode *inode, struct file *filep)  
{  
    fs4412_beep_on();  
    return 0;  
}  
  
static int beep_release(struct inode *inode, struct file *filep)  
{  
     fs4412_beep_off();  
     return 0;  
}  
#define BEPP_IN_FREQ 100000  
static void beep_freq(unsigned long arg)  
{  
    writel(BEPP_IN_FREQ/arg, timer_base +TCNTB0  );  
    writel(BEPP_IN_FREQ/(2*arg), timer_base +TCMPB0 );  
  
}  
  
static long beep_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)  
{  
    switch(cmd)  
    {  
        case BEEP_ON:  
            fs4412_beep_on();  
            break;  
        case BEEP_OFF:  
            fs4412_beep_off();  
            break;  
        case BEEP_FREQ:  
            beep_freq( arg );  
            break;  
        default :  
            return -EINVAL;  
    }  
    return 0;  
}  

/*操作*/
static struct file_operations beep_ops=  
{  
    .open     = beep_open,  
    .release = beep_release,  
    .unlocked_ioctl      = beep_ioctl,  
};  

/*在platform总线上找到同名的设备,调用该函数
 *对设备资源进行初始化以及注册驱动生成设备文件 
 */
static int beep_probe(struct platform_device *pdev)  
{  
    int ret;      
    printk("match ok!");  
      
    gpd0con = ioremap(pdev->resource[0].start,pdev->resource[0].end - pdev->resource[0].start);  
    timer_base = ioremap(pdev->resource[1].start, pdev->resource[1].end - pdev->resource[1].start);  
  
    devno = MKDEV(major,minor);  
    ret = register_chrdev(major,"beep",&beep_ops);  
  
    cls = class_create(THIS_MODULE, "myclass");  
    if(IS_ERR(cls))  
    {  
        unregister_chrdev(major,"beep");  
        return -EBUSY;  
    }  
  
    test_device = device_create(cls,NULL,devno,NULL,"beep");
    if(IS_ERR(test_device))  
    {  
        class_destroy(cls);  
        unregister_chrdev(major,"beep");  
        return -EBUSY;  
    }  
      
    fs4412_beep_init();  
      
    return 0;  
}  
/*设备拔出时调用该函数*/
static int beep_remove(struct platform_device *pdev)  
{  
    beep_unmap();  
    device_destroy(cls,devno);  
    class_destroy(cls);   
    unregister_chrdev(major,"beep");  
  
    return 0;  
}  
  
/*定义驱动结构体
 *probe和remove函数的入口
 */
static struct platform_driver beep_driver=  
{  
    .driver.name = "bigbang",  
    .probe = beep_probe,  
    .remove = beep_remove,  
};  
  
static int beep_init(void)  
{  
    printk("beep_init");  
    /*将驱动挂到platform总线上*/
    return platform_driver_register(&beep_driver);  
}  
  
static void beep_exit(void)  
{  
    printk("beep_exit");
	/*从platform总线上撤销*/  
    platform_driver_unregister(&beep_driver);  
      
    return;  
}  
MODULE_LICENSE("GPL");  
module_init(beep_init);  
module_exit(beep_exit);  </span>

test.c

<span style="font-size:18px;">
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<sys/ioctl.h>

#define MAGIC_NUMBER 'k'
#define BEEP_ON _IO(MAGIC_NUMBER  ,0)
#define BEEP_OFF _IO(MAGIC_NUMBER ,1)
#define BEEP_FREQ _IO(MAGIC_NUMBER ,2)

int main(void)
{
	int fd;
	fd=open("/dev/beep",O_RDWR);
	if(fd<0)
	{
		perror("open fail\n");
		return 0;
	}

	ioctl(fd,BEEP_ON);

	sleep(6);
	ioctl(fd,BEEP_OFF);

	close(fd);
	return 0;
}
</span>

Makefile:

<span style="font-size:18px;">
ifneq ($(KERNELRELEASE),)
obj-m:=driver.o device.o
else
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
	gcc -Wall -o test test.c
clean:
	make -C $(KDIR) M=$(PWD) clean
endif</span>



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值