驱动开发platform传地址,led点灯

除了platform传地址,其他的跟指定入口地址和指定出口地址没区别

platform和指定入口地址不能同时存在,一直报错模块初始化重定义,半个小时搞完程序没问题,这个重复定义因为代码太多没看懂错误,删了又加没试出来怎么改错。

1.myled.h

#ifndef __MYLED_H__
#define __MYLED_H__enum{LED1, //0LED2, //1LED3, //2
};
typedef struct {volatile unsigned int MODER;   // 0x00volatile unsigned int OTYPER;  // 0x04volatile unsigned int OSPEEDR; // 0x08volatile unsigned int PUPDR;   // 0x0Cvolatile unsigned int IDR;     // 0x10                                                                        volatile unsigned int ODR;     // 0x14volatile unsigned int BSRR;    // 0x18volatile unsigned int LCKR;    // 0x1C volatile unsigned int AFRL;    // 0x20 volatile unsigned int AFRH;    // 0x24volatile unsigned int BRR;     // 0x28volatile unsigned int res;volatile unsigned int SECCFGR; // 0x30
}gpio_t;#define LED_ON  _IOW('a',1,int) //封装灯亮命令码
#define LED_OFF _IOW('a',0,int) //封装灯灭命令码
#define GET_CMD_SIZE(cmd) (cmd >> 16 & 0x3fff)  //封装命令码大小#endif

2.pdrv.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "myled.h"
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/device.h>struct cdev* cdev;
#if 1
unsigned int major = 0; 
#else
unsigned int major = 500;
#endif
unsigned int minor = 0;
unsigned int count = 3;
#define CNAME "myled"
struct class *cls;
struct device *device;unsigned int* rcc_virt = NULL;
gpio_t* gpioe_virt = NULL;
gpio_t* gpiof_virt = NULL;#define LED1_ON (gpioe_virt->ODR |= (0x1 << 10))
#define LED1_OFF (gpioe_virt->ODR &= (~(0x1 << 10)))#define LED2_ON (gpiof_virt->ODR |= (0x1 << 10))
#define LED2_OFF (gpiof_virt->ODR &= (~(0x1 << 10)))#define LED3_ON (gpioe_virt->ODR |= (0x1 << 8))
#define LED3_OFF (gpioe_virt->ODR &= (~(0x1 << 8)))
struct resource* res;#define  GPIOE   res[0].start
#define RCC_MP_AHB4ENSETR_PHY  res[1].startint myled_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);printk("美妙的时光总有尽头\n");return 0;
}long myled_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{int ret;int whitch;switch(cmd) //判断命令码{case LED_ON: //灯亮命令码ret = copy_from_user(&whitch,(void*)args,GET_CMD_SIZE(LED_ON));if(ret){printk("copy from user is error\n");return -EIO;}switch (whitch) //判断哪一盏灯点亮{case LED1:LED1_ON; //LED1点亮break;                        }break;case LED_OFF: //灯灭命令码ret = copy_from_user(&whitch,(void*)args,GET_CMD_SIZE(LED_OFF));if(ret){printk("copy from user is error\n");return -EIO;}switch (whitch) //判断哪一盏灯熄灭{case LED1:LED1_OFF; //LED1熄灭break;                        }        break;}return 0;
}
int myled_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);printk("还起床了\n");return 0;     
}//操作方法结构体
const struct file_operations fops = {.open = myled_open,.unlocked_ioctl = myled_ioctl,.release = myled_close,
};//当设备信息端和设备驱动端匹配成功时,执行probe函数
int pdrv_probe(struct platform_device *pdev)
{int ret;int i;dev_t devno;printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);printk("name = %s id = %ld\n",pdev->id_entry->name,pdev->id_entry->driver_data);//获取设备信息端地址信息res = platform_get_resource(pdev,IORESOURCE_MEM,0);if(res == NULL){printk("platform get resource is error\n");return -EIO;}//打印获取到的地址信息 中断号printk("GPIOEaddress = %#x RCCaddress = %#x\n",res[0].start,res[1].start);//分配对象cdev = cdev_alloc(); if(cdev == NULL){printk("cdev alloc is error\n");ret = -ENOMEM;goto ERR1;        }//对象初始化cdev_init(cdev,&fops);if(major > 0){ //静态指定设备号ret = register_chrdev_region(MKDEV(major,minor),count,CNAME);if(ret){printk("register chrdev region is error\n");ret =  -EIO;goto ERR2;            }}else{ //动态指定设备号ret = alloc_chrdev_region(&devno,minor,count,CNAME);if(ret){printk("alloc chrdev region is error\n");ret =  -EIO;goto ERR2;            }major = MAJOR(devno);//通过设备号,获取到主设备号的值minor = MINOR(devno);//通过设备号,获取到次设备号的值}  //注册ret = cdev_add(cdev,MKDEV(major,minor),count); if(ret){printk("cdev add is error\n");ret =  -EIO;goto ERR3;            }//向上层提交目录信息cls = class_create(THIS_MODULE,CNAME);if(IS_ERR(cls)){ret = PTR_ERR(cls);goto ERR4;}for(i=0;i<count;i++){//向上层提交设备节点信息device = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);if(IS_ERR(device)){ret = PTR_ERR(device);goto ERR5;}  }//rcc物理地址映射rcc_virt = ioremap(RCC_MP_AHB4ENSETR_PHY,4);if(rcc_virt == NULL){printk("rcc ioremap is error\n");return -EIO;}//GPIOE组寄存器物理地址映射gpioe_virt = ioremap(GPIOE,sizeof(gpio_t));if(gpioe_virt == NULL){printk("gpioe ioremap is error\n");return -EIO;}//LED1灯初始化 PE10*rcc_virt |= (0x1 << 4); //使能GPIOE组控制器 gpioe_virt->MODER &= (~(0x3 << 20)); //设置PE10引脚为输出模式gpioe_virt->MODER |= (0x1 << 20);gpioe_virt->ODR &= (~(0x1 << 10)); //设置PE10引脚输出低电平return 0; ERR5://创建三个设备节点时,第一个设备节点和第二个设备节点创建成功,第三个设备节点创建失败//需要将第一个设备节点和第二个设备节点创建成功,需要进行释放for(--i;i>=0;i--){device_destroy(cls,MKDEV(major,i));}class_destroy(cls);
ERR4:cdev_del(cdev);
ERR3:unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:kfree(cdev);
ERR1:return ret;
}//当任意一方卸载,执行remove函数
int pdrv_remove(struct platform_device *pdev)
{int i = 0;printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);//取消地址映射iounmap(rcc_virt);iounmap(gpioe_virt);for(i=0;i<count;i++){device_destroy(cls,MKDEV(major,i));}class_destroy(cls);cdev_del(cdev);unregister_chrdev_region(MKDEV(major,minor),count);kfree(cdev);return 0;
}const struct platform_device_id idtable[] = {{"hello1",1},{},/*防止数组越界*/
};//初始化设备驱动端结构体
struct platform_driver pdrv = {.probe = pdrv_probe,.remove = pdrv_remove,.driver = {.name = "hello DC23111", //通过名字进行匹配},.id_table = idtable,
};
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

3.pdev.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>//描述设备信息结构体
struct resource res[2] = {[0] = {.start = 0x50006000, //起始地址.end = 0x50006000 + 31, //终止地址.flags = IORESOURCE_MEM, //资源类型},[1] = {.start = 0x50000A28, .end = 0x50000A28 + 31,.flags = IORESOURCE_MEM,},
};
void pdev_release(struct device *dev)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
}
//初始化设备信息端结构体
struct platform_device pdev = {.name = "hello1", //通过名字进行匹配.id = PLATFORM_DEVID_AUTO, //自动分配.dev = {.release = pdev_release,},.num_resources = ARRAY_SIZE(res),.resource = res,
};static int __init demo_init(void)
{//注册设备信息端return platform_device_register(&pdev);
}static void __exit demo_exit(void)
{//注销设备信息端platform_device_unregister(&pdev);
}module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");

4.test.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include "myled.h"int main(int argc, const char *argv[])
{int fd = -1;int whitch;char buf[128] = "";fd = open("/dev/myled0",O_RDWR);if(fd == -1){perror("open is error");return -1;}while(1){whitch = LED1;ioctl(fd,LED_ON,&whitch);sleep(1);ioctl(fd,LED_OFF,&whitch);sleep(1);}close(fd);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/371.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

气象观测站点数据下载与处理

一、下载途径 全国400多个气象站气候数据&#xff08;1942-2022&#xff09; 王晓磊&#xff1a;中国空气质量/气象历史数据 | 北京市空气质量历史数据 气象数据免费下载网站整理 中国气象站观测的气象数据怎么下载 二、R语言处理 2.1 提取站点文件 library(dplyr) library(…

集成智能楼宇的微网系统多时间尺度MPC调度方法(附带Matlab代码)

含多智能楼宇的微网示意图如图所示&#xff0c;包括多个智能楼宇、微网可控分布式电源 、储能系统以及通信链路。其中&#xff0c;每个智能楼宇系统包括制冷设备、常规用电设备以及屋顶光伏系统。各单元功能介绍如下 针对含多智能楼宇的微网系统&#xff0c;提出一种基于模型预…

gpt能生成ppt吗

gpt能生成ppt吗 GPT是一个高度通用的工具&#xff0c;适用于多种场景和领域&#xff0c;制作ppt只是它强大功能的冰山一角&#xff0c;具体包括&#xff1a; 信息查询与解释&#xff1a; 提供科学、技术、历史、文化等领域的详细解释和背景信息。 解答疑问&#xff0c;帮助…

制作带有中文字体的 jdk 17 镜像

1. 准备中文字体 将所有需要添加的中文字体放进一个文件夹内&#xff0c;例如 fonts 2. 创建 Dockerfile 文件 Dockefile 文件与 fonts 文件夹放在同一目录下 # 使用 slim 版本的 jdk 17 镜像作为基础镜像 FROM openjdk:17-slim# 安装字体工具 RUN apt-get update &&a…

Xilinx 7系列FPGA 高性能(HP)接口与2.5V/3.3V 外设IO接口设计考虑

引言&#xff1a;Xilinx 7系列FPGA IO Bank分为HP Bank和HR Bank&#xff0c;HP IO接口电压范围为1.2V~1.8V&#xff0c;可以实现高性能&#xff0c;HR IO接口电压范围为1.2V~3.3V。当HR Bank与2.5V或者3.3V外设互联时&#xff0c;需要考虑接口电平的兼容性。根据性能需求、功能…

模拟相机拍照——对文档进行数据增强

一. 背景 假如我们有一个标准文件&#xff0c;我们对其进行文字识别、版面分析或者其他下游任务就比较容易。然而&#xff0c;当图片是手机拍照获取的&#xff0c;图片中往往有阴影、摩尔纹、弯曲。 那么&#xff0c;如何通过标准的文档&#xff0c;获得类似相机拍照的图片呢&…

更新kubeadm创建的集群的证书

需要熟悉的知识&#xff1a; 官网更新证书参考&#xff1a;https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/ 静态Pod:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/#static-pods 如何创建静态Pod&#xff1a;https://kuberne…

家庭营销广告Criteo公司首次获得MRC零售媒体测量认证

家庭营销广告Criteo公司首次获得零售媒体测量MRC认证 商业媒体公司Criteo2024年3月28日宣布&#xff0c;它首次获得媒体评级委员会&#xff08;MRC&#xff09;的认证&#xff0c;在其企业零售媒体平台commerce Max和commerce Yield上&#xff0c;在桌面、移动网络和移动应用内…

数据库函数ABS详解

ABS函数的语法是&#xff1a;ABS(number)&#xff0c;其中number是要计算绝对值的数字或表达式。例如&#xff0c;如果要计算-5的绝对值&#xff0c;可以使用以下查询&#xff1a; SELECT ABS(-5) FROM dual&#xff1b;这将返回结果为5。 在Oracle中&#xff0c;ABS是一个内置…

4-Java方法详解

目录 Java方法详解 1、什么是方法 2、方法的定义及调用 3、方法重载 4、命令行传参 5、可变参数 6、递归 例题&#xff1a;代码实现一个计算机 Java方法详解 1、什么是方法 2、方法的定义及调用 形参&#xff1a;用来定义作用的 实参&#xff1a;实际调用传递给他的参数…

java | junit | 基本+技巧

1.参考链接 1.1 单测概念 https://medium.com/lathasreeseeni/junit-2d9857773e8 1.2 高级技巧 https://symflower.com/en/company/blog/2023/how-to-write-junit-test-cases-advanced-techniques/ assertThrows&#xff1a; 有时候&#xff0c;我们的方法&#xff0c;需要抛出…

ES系列之相似度模型

概述 ES作为一款搜索引擎&#xff0c;搜索结果如何排序&#xff0c;即什么条目或内容更靠前&#xff0c;是一个很核心的问题。排序通常是通过计算语料库中的文档和用户查询之间的相关性或相似度评分来进行。 相似性&#xff08;得分/排名模型&#xff09;定义匹配文档如何进行…

C#基于SSE传递消息给Vue前端实现即时单向通讯

一、简述 通常前端调用后端的API&#xff0c;调用到了&#xff0c;等待执行完&#xff0c;拿到返回的数据&#xff0c;进行渲染&#xff0c;流程就完事了。如果想要即时怎么办&#xff1f;如果你想问什么场景非要即时通讯&#xff0c;那可就很多了&#xff0c;比如在线聊天、实…

libwebsockets 简介

文章目录 1. 前言2. libwebsockets 的 编译 和 使用2.1 编译2.2 使用2.2.1 构建运行上下文2.2.2 事件处理循环 3. websocket 协议 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. libwebsockets…

EASERVER管理密码忘记的处理方式

一个多年的老客户&#xff0c;EASERVER的管理员密码忘记了&#xff0c;查了一些资料&#xff0c;把它重置了&#xff0c;做个记录 This is a really quick tip on how to reset password for the administrator id “jagadmin” used in EA Server. We use this id for everyt…

Java 笔记 01:Java 概述,MarkDown 常用语法整理

一、前言 记录时间 [2024-04-18] 昨天整理完 Docker 基础后略微思索了一下&#xff0c;还是决定把 Java 捡起来&#xff0c;系统地学习一遍&#xff0c;参考的学习课程是狂神说 Java 零基础&#xff0c;真诚感激此系列视频对笔者的帮助。 零基础可以学 Java 吗&#xff1f;只要…

JVS低代码平台表单引擎:字符串拼接与逻辑函数的完美结合

字符串拼接使用逻辑函数配置 示例场景&#xff1a;通过按钮触发逻辑使用函数将两个日期字段组合为范围时间类型。 选择开始日期和结束日期后&#xff0c;点击【合并】按钮自动处理回显至起止日期字段。在【合并】按钮上设置逻辑。 注意&#xff1a;这里【起止日期】组件是数组…

【web开发02】后端开发Maven

后端开发Maven 1 Maven是什么&#xff1f;1.1 Maven基础概念1.1.2 仓库1.1.3 坐标 2 配置maven环境3 创建maven项目4 导入maven项目4 依赖管理4.1 依赖配置4.2 依赖传递4.2.1 排除依赖 4.3 依赖范围4.4 生命周期4.4.1 运行生命周期 1 Maven是什么&#xff1f; Maven本质是项目…

无梯度计算模式

无梯度计算模式是指在进行优化、求解或模型训练时&#xff0c;不依赖于目标函数或其相关组件&#xff08;如损失函数、约束函数等&#xff09;的梯度信息来指导搜索或更新过程的方法。这种模式适用于以下几种情况&#xff1a; 梯度不可用或难以计算&#xff1a; 目标函数可能包…

android和java 线程Tread

1。线程的生命周期。 可以分为创建,就绪,运行,阻塞,死亡 5个状态。 1.1 创建 new :当程序new了一个线程后,线程就处于新建状态,这时候他和其他 java对象一样,被java虚拟机分配了内存,但没有线程的特性。 …