linux驱动platform平台设备总线

platform总线:是由许多AX2,AHB,APB等总线的总称,是相对于linux操作系统来说的

而AHB,APB,AX2那些是相对于硬件底层来说。

实例:

pdev.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/device.h>
#include <linux/platform_device.h>

void led_dev_release(struct device *dev)
{
	printk("led device release\n");
}

//设备基础资源信息
static struct resource s3c_led_resource[] = {
	[0] = {
		.start = 0xe0200280,
		.end   = 0xe0200280 + 0x1000,
		.flags = IORESOURCE_MEM,
	},
};

//平台设备结构体
struct platform_device led_platdev ={
	.name 	= "led-dev-drv",
	.dev 	= {
		.release = led_dev_release,
	},
	.num_resources	  = ARRAY_SIZE(s3c_led_resource),
	.resource	  = s3c_led_resource,
};


int __init led_platdev_init()
{
	printk("usb dev mouse init \n");
	platform_device_register(&led_platdev);
	return 0;
}

void __exit led_platdev_exit()
{
	printk("usb dev mouse exit \n");
	platform_device_unregister(&led_platdev);
}


module_init(led_platdev_init);
module_exit(led_platdev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("GEC210");
MODULE_DESCRIPTION("just a driver test,134xxxxx;qq:3455..");
pdrv.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>		// copy_to_user/copy_form_user
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/delay.h>

#define LED_ON	0
#define LED_OFF 1

struct resource *ptr = NULL;
unsigned long *gpj2con = NULL;

static dev_t dev_num;
static struct cdev *cdev_p;
static struct class *myclass = NULL;
struct device *mydev = NULL;

//led初始化定义
int led_open(struct inode *inode, struct file *file)
{
	printk("led init ....\n");
	int val;
	/* led init */
	val = ioread32(gpj2con);
	val &=~(0xF<<0);
	val |=(0x1<<0);
	iowrite32(val,gpj2con);

	val = ioread32(gpj2con+1);
	val |=(0x1<<0);
	iowrite32(val,gpj2con+1);
	printk("debug_001\n");
	
	return 0;
}

int led_close(struct inode *inode, struct file *file)
{
	printk("led close ....\n");
	
	return 0;
}

void led_on()
{
	int val;
	val = ioread32(gpj2con+1);
	val &=~(0x1<<0);
	iowrite32(val,gpj2con+1);	
}

void led_off()
{
	int val;
	val = ioread32(gpj2con+1);
	val |=(0x1<<0);
	iowrite32(val,gpj2con+1);	
}
//led操作
int led_ioctl(struct inode *inode,struct file *file,int cmd,int arg)
{
	switch(cmd){
		case LED_ON:
			led_on();
			break;
		case LED_OFF:
			led_off();
			break;
	}
}
//led表
struct file_operations led_fops ={
	.open 		= led_open,
	.release 	= led_close,
	.ioctl 		= led_ioctl,
};

//设备名匹配成功后
int led_platdev_probe(struct platform_device *pdev)
{
	printk("led driver entry>>>>>>>\n");
	int val;
	//从pdev.c传过来的*dev指针里resource获取基本的资源信息
	int phys_addr = pdev->resource[0].start;  // =0xe0200280
	
	//端口申请
	ptr = request_mem_region(phys_addr,0x1000,"led-drv");
	if(ptr == NULL)
	{
		printk("request_mem_region\n");
		return -1;
	}
	//端口绑定
	gpj2con = (unsigned long*)ioremap(phys_addr,0x1000);
	if(gpj2con == NULL)
	{
		printk("ioremap fail\n");
		return -1;
	}

	//设备号动态分配
	val = alloc_chrdev_region(&dev_num,0,1,"led-drv");
	if(val < 0)
	{
		printk("all chrdev num fail\n");
		return -1;
	}
	printk("dev number =  %d ; major = %d ; minor = %d\n",dev_num,MAJOR(dev_num),MINOR(dev_num));
	// 动态内存定义申请初始化
	cdev_p = cdev_alloc();
	cdev_init(cdev_p,&led_fops);
	
	val = cdev_add(cdev_p,dev_num,1);
	if(val)
	{
		printk("cdev add fail\n");
		return -1;
	}
	//类创建
	myclass = class_create(THIS_MODULE,"my-class");
	if(myclass == NULL)
	{
		printk("cleate class fail\n");
		return -1;
	}
	//设备创建和,这里也就不需要mknod挂设备节点了,insmod之后直接可以运行app应用程序
	mydev = device_create(myclass,NULL,dev_num,NULL,"my-drv");
	if(mydev == NULL)
	{
		printk("cleate device fail\n");
		return -1;
	}
	
	return 0;
}

int led_platdev_remove(struct platform_device *pdev)
{
	printk("led driver exit\n");
	
	device_destroy(myclass,dev_num);
	class_destroy(myclass);
	
	cdev_del(cdev_p);
	unregister_chrdev_region(dev_num,1);
	
	iounmap(gpj2con);
	release_mem_region(0xe0200280,0x1000);
	return 0;
}
//注册的设备信息
struct platform_driver led_platdrv ={
	.driver = {
		.name 	= "led-dev-drv",
	},
	.probe 	= led_platdev_probe, 
	.remove = led_platdev_remove,
};

int __init led_platdrv_init()
{
	printk("led plat drv init \n");
	//平台设备注册
	platform_driver_register(&led_platdrv);	
	return 0;
}

void __exit led_platdrv_exit()
{
	printk("usb drv mouse exit \n");
	platform_driver_unregister(&led_platdrv);
}


module_init(led_platdrv_init);
module_exit(led_platdrv_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("GEC210");
MODULE_DESCRIPTION("just a driver test,134xxxxx;qq:3455..");


//平台设备注册platform_driver_register
//定义设备结构体struct platform_driver led_platdrv ={
//结构体里写好要match的设备名,退出等,然后写退出对应函数,释放掉端口映射,设备卸装等
//匹配成功后的函数int led_platdev_probe()
//probe函数里定义动态分配设备号,端口映射、绑定等。
//也可以创建类class_create(
app.c

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

#define LED_ON	0
#define LED_OFF 1

int main()
{
	int fd = open("/dev/my-drv",O_RDWR);
	if(fd < 0)
	{
		printf("open fail\n");
		return -1;
	}
	ioctl(fd,LED_OFF);
	sleep(1);
	ioctl(fd,LED_ON);
	
	close(fd);
	return 0;
}

makefile

obj-m += pdev.o pdrv.o 

KERNEL_DIR := /usr/mkdrv/src/android-kernel-samsung-dev

all:
	make modules -C $(KERNEL_DIR) M=`pwd`
	arm-linux-gcc app.c -o app
	cp pdev.ko pdrv.ko app /nfs  
	make clean
clean:
	make modules clean -C $(KERNEL_DIR) M=`pwd` 
	rm -rf app 
由于这里还使用了类,所以不需要mknod。

加载完设备和驱动之后,就可以运行app应用程序测试。

也可以把设备动态注册platform-device改成静态注册

在内核里对应的修改,让他启动的时候自动注册pdev.c设备。

参考:

http://blog.chinaunix.net/uid-27664726-id-3334981.html

附:

类的创建

class.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>		// copy_to_user/copy_form_user
#include <linux/device.h>

static struct class *myclass = NULL;
struct device *mydev = NULL;
static dev_t dev_num;

int __init class_init()
{
	printk("usb dev mouse init \n");
	int val;
	myclass = class_create(THIS_MODULE,"my-class");
	if(myclass == NULL)
	{
		printk("cleate class fail\n");
		return -1;
	}
	
	val = alloc_chrdev_region(&dev_num,0,1,"led-drv");
	if(val < 0)
	{
		printk("all chrdev num fail\n");
		return -1;
	}
	printk("dev number =  %d ; major = %d ; minor = %d\n",dev_num,MAJOR(dev_num),MINOR(dev_num));
	
	mydev = device_create(myclass,NULL,dev_num,NULL,"my-drv");
	if(mydev == NULL)
	{
		printk("cleate device fail\n");
		return -1;
	}
	
	return 0;
}

void __exit class_exit()
{
	printk("usb dev mouse exit \n");
	device_destroy(myclass,dev_num);
	class_destroy(myclass);
}


module_init(class_init);
module_exit(class_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("GEC210");
MODULE_DESCRIPTION("just a driver test,134xxxxx;qq:3455..");
cat /sys/class查看创建的类
自动挂在驱动文件节点mknod
/dev/xx查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值