【Linux】【驱动】平台总线模式platform模型的编写,操作LED灯

【Linux】【驱动】平台总线模式platform模型的编写,操作LED灯

平台总线模式,将设备和驱动进行了区分,据说可以优化代码的可移植性
device:实现对设备寄存器的申明
dirver: 则从总线中取数据,取的时候可以检验是否被使用过,取完在去操作

主要就是三个文件

device

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>


void beep_release(struct device *dev)
{
	printk("beep_release\n");

}


struct resource beep_res[] = {
	
	[0] ={
		.start = 0x20AC000,
		.end = 0x20AC003,
		.flags = IORESOURCE_MEM,
		.name = "GPIO5_DR"
	},
	
	[1] ={
		.start = 0x20AC000 + 0x04,
		.end = 0x20AC000 + 0x04 + 0x03,
		.flags = IORESOURCE_MEM,
		.name = "GPIO5_GDIR"
	},
	[2] ={
		.start = 0x2290014,
		.end = 0x2290017,
		.flags = IORESOURCE_MEM,
		.name = "IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3"
	},
	[3] ={
		.start = 0x20C406C,
		.end = 0x20C406C + 0x03,
		.flags = IORESOURCE_MEM,
		.name = "CCM_CCGR1"
	}
};

struct platform_device beep_device =
{
	.name          	= "beep_test",
	.id 			= -1,
	.resource 		= beep_res,
	.num_resources 	= ARRAY_SIZE(beep_res),
	.dev ={
		.release = beep_release
	}
};



//drivers for init
static int device_init(void)
{
	printk("device_init \n");
	return platform_device_register(&beep_device);
	
}

//drivers for exit 
static void device_exit(void)
{

	printk("device_exit \n");
	return platform_device_unregister(&beep_device);;
}

module_init(device_init);
module_exit(device_exit);

MODULE_LICENSE("GPL");

driver

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





struct resource *beep_mem;
struct resource *beep_mem_tmp;
struct resource *beep_GDIR;
struct resource *beep_GDIR_tmp;
struct resource *beep_CCM_CCGR1;
struct resource *beep_CCM_CCGR1_tmp;
struct resource *beep_IOMUXC;
struct resource *beep_IOMUXC_tmp;


static volatile unsigned int *GPIO5_DR ;
static volatile unsigned int *GPIO5_GDIR ;
static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 ;
static volatile unsigned int *CCM_CCGR1 ;



int misc_open(struct inode *inode, struct file *file)
{
	printk("misc_open\n");

	return 0;
}

int misc_release(struct inode *inode, struct file *file)
{
	printk("misc_release\n");
	return 0;

}

ssize_t misc_read(struct file *file,char __user *ubuf,size_t size,loff_t *loff_t)
{
	char kbuf[512] = "haha";

	if(copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
	{
		printk("error copying\n");
		return -1;
	}

	return 0;

}

ssize_t misc_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loff_t)
{

	char kbuf[512] = {0};	
	if(copy_from_user(kbuf,ubuf,size)!= 0)
	{
		printk("misc_write error\n");
		return -1;

	}

	printk("kbuf = %d\n",kbuf[0]);
	if(kbuf[0] == 1)
		{
			*GPIO5_DR |=(1<<3);//设置GPIO
			printk(" kbuff  = 1\n");
		}
	else if(kbuf[0] == 0)
	{
		*GPIO5_DR &= ~(1<<3);//设置GPIO
		printk(" kbuff  = 0\n");
	}


	return 0;

}

struct file_operations misc_fops = {
	.owner	= THIS_MODULE,
	.open	= misc_open,
	.release = misc_release,
	.read	= misc_read,
	.write	= misc_write
};


struct miscdevice misc_dev = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = "hello_misc",
	.fops = &misc_fops
};



int  beep_probe (struct platform_device *pdev)
{
	int ret = 0;
	unsigned int val;
	printk("beep_probe \n");
	
	//方案1,直接读取device中的数据
	//printk ("beep_res is %s\n", pdev->resource[0].name);

	//方案2 使用函数去读取
	beep_mem = platform_get_resource (pdev,IORESOURCE_MEM,0); 
	if(beep_mem == NULL){
		printk("platform_get_resource null \n");
		return -EBUSY;
	}
	beep_GDIR = platform_get_resource (pdev,IORESOURCE_MEM,1); 
	if(beep_GDIR == NULL){
		printk("platform_get_resource beep_GDIR null\n");
		return -EBUSY;
	}


	beep_IOMUXC = platform_get_resource (pdev,IORESOURCE_MEM,2); 
	if(beep_IOMUXC == NULL){
		printk("platform_get_resource beep_IOMUXC null\n");
		return -EBUSY;
	}

	beep_CCM_CCGR1 = platform_get_resource (pdev,IORESOURCE_MEM,3); 
	if(beep_CCM_CCGR1 == NULL){
		printk("platform_get_resource beep_IOMUXC null\n");
		return -EBUSY;
	}


/***********************************************************************/
	printk(" platform_get_resource is ok \n");
	printk(" beep_res start is 0x%x \n",beep_mem->start);
	printk(" beep_res end is 0x%x \n",beep_mem->end);

	// //有用过则会声明失败
	// beep_mem_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep");
	// if( beep_mem_tmp == NULL){
	// 	printk("request_mem_region is error \n");
	// 	goto err_region;
	// }
	// beep_GDIR_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep_GPIO5_GDIR");
	// if( beep_GDIR_tmp == NULL){
	// 	printk("request_mem_region is error \n");
	// 	goto err_region;
	// }	
	// beep_CCM_CCGR1_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep_CCM_CCGR1");
	// if( beep_CCM_CCGR1_tmp == NULL){
	// 	printk("request_mem_region is error \n");
	// 	goto err_region;
	// }	
	
	// beep_IOMUXC_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep_IOMUXC");
	// if( beep_IOMUXC_tmp == NULL){
	// 	printk("request_mem_region is error \n");
	// 	goto err_region;
	// }

/***********************************************************************/
	GPIO5_DR = ioremap(beep_mem->start,4);
	if(GPIO5_DR == NULL)
	{
		printk("GPIO5_DR is error \n");
		return -EBUSY;
	}
	printk("GPIO5_DR ioremap OK \n");

	GPIO5_GDIR = ioremap(beep_GDIR->start,4);
	if(GPIO5_GDIR == NULL)
	{
		printk("GPIO5_GDIR is error \n");
		return -EBUSY;
	}
	printk("GPIO5_GDIR ioremap OK \n");

	IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(beep_IOMUXC->start,4);
	if(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 == NULL)
	{
		printk("IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 is error \n");
		return -EBUSY;
	}
	printk("IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 ioremap OK \n");

	
	CCM_CCGR1 = ioremap(beep_CCM_CCGR1->start,4);
	if(CCM_CCGR1 == NULL)
	{
		printk("CCM_CCGR1 is error \n");
		return -EBUSY;
	}
	printk("CCM_CCGR1 ioremap OK \n");


	*CCM_CCGR1 |= (3<<30);//使能 GPIO5
	//设置 GPIO5_IO03 用于 GPIO
	val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
	val &= ~(0xf);
	val |= (5);
	*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = val;

	//设置 GPIO5_IO03 作为 output 引脚
	*GPIO5_GDIR |= (1<<3);
/***********************************************************************/

	ret = misc_register(&misc_dev);
	if(ret<0){
		printk("misc_register is error \n");
		return -1;
	}
	printk("misc registe is successed \n");

	return 0;


// err_region:
// 	release_mem_region(beep_mem->start,beep_mem->end - beep_mem->start + 1);
// 	return -EBUSY;



}

int  beep_remove (struct platform_device *pdev)
{
	printk("beep_remove \n");
	return 0;

}

const struct platform_device_id beep_id_table= {
	.name = "beep_test",

};


struct platform_driver beep_device =
{
	/* data */
	.probe = beep_probe,
	.remove = beep_remove,
	.driver = {
		.owner = THIS_MODULE,
		.name = "123"
	},
	.id_table = &beep_id_table

};



//drivers for init
static int beep_driver_init(void)
{
	int ret = 0;
	ret = platform_driver_register(&beep_device);
	if(ret < 0){
		printk("platform_driver_register ERROR \n");
		return ret;

	}
	printk("platform_driver_register OK\n");
	return 0;
}


//drivers for exit 
static void beep_driver_exit(void)
{
	printk("beep_driver_exit exit \n");
	platform_driver_unregister(&beep_device);
	misc_deregister(&misc_dev);
	iounmap(CCM_CCGR1);
	iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3);
	iounmap(GPIO5_GDIR);
	iounmap(GPIO5_DR);
}

module_init(beep_driver_init);
module_exit(beep_driver_exit);

MODULE_LICENSE("GPL");

app

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"


/*
 * @description		: main主程序
 * @param - argc 	: argv数组元素个数
 * @param - argv 	: 具体参数
 * @return 			: 0 成功;其他 失败
 */
int main(int argc, char *argv[])
{
	int fd;
	char buf[64] = {0};

	//fd = open(argv[1], O_RDONLY);
	fd = open("/dev/hello_misc", O_RDWR);

	if(fd < 0)
	{
		perror("open error");
		return fd;

	}
	buf[0] = atoi(argv[1]);

	write(fd,buf,sizeof(buf));
	close(fd);
	return 0;
}

操作指令

编译app代码

arm-buildroot-linux-gnueabihf-gcc -o app app.c

移动文件

cp misc.ko /home/book/nfs_rootfs/

允许printk

echo "7 4 1 7"> /proc/sys/kernel/printk

输入值到app中

./app 1

PS :待修正
文中使用了request_mem_region代码的位置,可能由于已经在系统中声明过,所以会出现报错的问题,后面需要寻找方式去消除

 beep_mem_tmp = request_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep");
 if( beep_mem_tmp == NULL){
 	printk("request_mem_region is error \n");
 	goto err_region;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值