已解决
【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%的人还看了
相似问题
- 基于STC12C5A60S2系列1T 8051单片机的IIC总线器件24C02记录单片机上电次数应用
- 电子电器架构 —— 车载网关边缘节点总线转换
- FPGA与STM32_FSMC总线通信实验
- LabVIEW在OPC中使用基金会现场总线
- 【CAN总线】从数字设计的角度分析CAN协议1—CAN概述
- CCLINK IEFB总线转ETHERNET/IP网络的协议网关使欧姆龙和三菱的数据互通的简单配置方法
- CAN(Controller Area Network)是一种用于在汽车和工业领域中进行通信的串行总线系统(附加案例)
- 企业服务总线ESB有什么作用?和微服务有什么区别?会如何发展?
- 传统汽车总线CAN(FD) LIN学习大纲
- 国产CAN总线收发芯片DP1042 兼容替换TJA1042
猜你感兴趣
版权申明
本文"【Linux】【驱动】平台总线模式platform模型的编写,操作LED灯":http://eshow365.cn/6-9190-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: 【Spring使用三级缓存解决循环依赖的过程】
- 下一篇: 卷积神经网络实现咖啡豆分类 - P7