当前位置:首页 > 编程笔记 > 正文
已解决

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

来自网友在路上 182882提问 提问时间:2023-09-19 07:37:34阅读次数: 82

最佳答案 问答题库828位专家为你答疑解惑

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

  • device
  • driver
  • app
  • 操作指令

平台总线模式,将设备和驱动进行了区分,据说可以优化代码的可移植性
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);//设置GPIOprintk(" kbuff  = 1\n");}else if(kbuf[0] == 0){*GPIO5_DR &= ~(1<<3);//设置GPIOprintk(" 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 用于 GPIOval = *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;}
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"【Linux】【驱动】平台总线模式platform模型的编写,操作LED灯":http://eshow365.cn/6-9190-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!