xilinx linux AXI GPIO 驱动学习

vivado工程

vivado 配置一个 AXI GPIO, 全输出,宽度为1
在这里插入图片描述

设备树解读

生成的对应pl.dtsi设备树文件如下

		axi_gpio: gpio@40020000 {
			#gpio-cells = <2>;
			clock-names = "s_axi_aclk";
			clocks = <&clkc 15>;
			compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
			gpio-controller ;
			reg = <0x40020000 0x10000>;
			xlnx,all-inputs = <0x0>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x1>;
			xlnx,all-outputs-2 = <0x1>;
			xlnx,dout-default = <0x00000000>;
			xlnx,dout-default-2 = <0x00000000>;
			xlnx,gpio-width = <0x1>;
			xlnx,gpio2-width = <0x1>;
			xlnx,interrupt-present = <0x0>;
			xlnx,is-dual = <0x1>;
			xlnx,tri-default = <0xFFFFFFFF>;
			xlnx,tri-default-2 = <0xFFFFFFFF>;
		};

根据 compatible = “xlnx,xps-gpio-1.00.a” 找到内核文档 Documentaion/devicetree/bindings/gpio/gpio-xilinx.txt

关注以下部分

- #gpio-cells : Should be two or three. The first cell is the pin number,
  The second cell is used to specify channel offset:
		0 - first channel
		8 - second channel
  The third cell is optional and used to specify flags. Use the macros
  defined in include/dt-bindings/gpio/gpio.h
- gpio-controller : Marks the device node as a GPIO controller.

意思是需要至少两个参数,第一个是引脚号,第二个是用来指定通道,第三个参数可有可无,只是一个flag
而对于刚才生成的双通道axi gpio,引脚号从0开始,而第一个通道号为0,第二个为8

例如,可以这样访问

	name1-gpios = <&axi_gpio 0 0 GPIO_ACTIVE_LOW>;	
	name2-gpios = <&axi_gpio 0 8 GPIO_ACTIVE_HIGH>;

gpio驱动

先去看文档 Documentaion/gpio/consumer.txt
首先要 #include <linux/gpio/consumer.h>,定义了几个flags和重要的函数

The flags parameter is used to optionally specify a direction and initial value
for the GPIO. Values can be:
* GPIOD_IN to initialize the GPIO as input.
* GPIOD_OUT_LOW to initialize the GPIO as output with a value of 0.
* GPIOD_OUT_HIGH to initialize the GPIO as output with a value of 1.

flags 讲的就很清楚,设置flags 可以指定方向和初始值

使用GPIOs 部分解读

按照以前的理解,GPIO肯定要先初始化,再设置方向,再设置高低电平

Obtaining and Disposing GPIOs
=============================
Like many other kernel subsystems, gpiod_get() takes the
device that will use the GPIO and the function the requested GPIO is supposed to
fulfill:

	struct gpio_desc *gpiod_get(struct device *dev, const char *con_id,
				    enum gpiod_flags flags)

也就是可以调用gpiod_get()函数来请求使用GPIO并实现某种功能
然后根据指示,通过 see Documentation/gpio/board.txt 来理解 the con_id parameter in the DeviceTree

假设有个设备树

	foo_device {
		compatible = "acme,foo";
		...
		led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
			    <&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
			    <&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */

		power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
	};

可以使用以下函数访问

struct gpio_desc *red, *green, *blue, *power;

red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);

power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);

但是gpiod_get()还需要其他函数搭配使用吗?继续看

Using GPIOs
===========
Setting Direction
-----------------
The first thing a driver must do with a GPIO is setting its direction. If no
direction-setting flags have been given to gpiod_get*(), this is done by
invoking one of the gpiod_direction_*() functions:

	int gpiod_direction_input(struct gpio_desc *desc)
	int gpiod_direction_output(struct gpio_desc *desc, int value)

但是这里说,如果没有在调用gpiod_get*()函数时给一个 direction-setting flags,那就需要调用gpiod_direction_*() 这两个函数之一

换句话说,如果在调用gpiod_get*()函数时给一个 direction-setting flag,就不需要设置其他函数了

所以,gpiod_get*()函数 完成了三件事:申请使用GPIO,通过flags设置了方向并初始化值

重要函数

struct gpio_desc *devm_gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags)
很多驱动文件里在用,文档里只提到了是一个变体函数,调用关系如下

devm_gpiod_get_optional -> 
 devm_gpiod_get_index_optional -> //index为0 
  devm_gpiod_get_index -> 
   gpiod_get_index

本质就是 gpiod_get_index

因此,对于我们的设备树

	name1-gpios = <&axi_gpio 0 0 GPIO_ACTIVE_LOW>;	
	name2-gpios = <&axi_gpio 0 8 GPIO_ACTIVE_HIGH>;

可以这么用

struct i2c_client *client;
struct gpio_desc name1_gpio;
name1_gpio = devm_gpiod_get_optional(&client->dev, "name1", GPIOD_OUT_HIGH);
if(IS_ERR(name1_gpio)){
	dev_err(&client->dev, "can't get %s name1 GPIO in DT\n", "name1");
	return PTR_ERR(name1_gpio);
}

做了几件事:

  1. 寻找设备树中有没有 name1-gpios
  2. 申请GPIO使用
  3. 通过 flag 初始化方向并设置高低电平

结束语

多看内核文档,多看参考驱动代码,多理解

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

海外盲盒App开发:探索惊喜与乐趣的跨国新体验

在全球化日益加速的今天&#xff0c;人们对新鲜、有趣、充满惊喜的体验需求不断增长。盲盒作为一种充满神秘与乐趣的玩法&#xff0c;正迅速在全球范围内走红。为了满足广大海外用户的盲盒体验需求&#xff0c;我们致力于开发一款海外盲盒App&#xff0c;为用户带来跨国界的惊喜…

C#,图论与图算法,计算无向连通图中长度为n环的算法与源代码

1 无向连通图中长度为n环 给定一个无向连通图和一个数n,计算图中长度为n的环的总数。长度为n的循环仅表示该循环包含n个顶点和n条边。我们必须统计存在的所有这样的环。 为了解决这个问题,可以有效地使用DFS(深度优先搜索)。使用DFS,我们可以找到特定源(或起点)的长度…

高精度AI火灾烟雾检测算法,助力打造更加安全的楼宇环境

一、方案背景 近日&#xff0c;南京居民楼火灾事故导致15人死亡的新闻闹得沸沸扬扬&#xff0c;这一事件又激起了大家对楼宇火灾隐患的进一步担忧。事后我们除了思考政府、消防及物业部门应对此事的解决办法&#xff0c;我们还应该思考如何利用现有的技术帮助人们减少此类事情的…

手撕算法-无重复字符的最长子串

描述 分析 滑动窗口&#xff0c;记录窗口中的所有出现的字符&#xff0c;然后窗口左边界固定&#xff0c;右边界右滑&#xff0c;如果&#xff0c;窗口中不存在新的字符&#xff0c;则右滑成功&#xff0c;否则左边界右滑&#xff0c;直到窗口中不存在右边界的值。 描述感觉不…

Linux初学(八)磁盘管理

一、磁盘管理 1.1 简介 磁盘的工作原理&#xff1a; 添加磁盘对磁盘进行分区格式化磁盘挂载和使用磁盘 磁盘的类型&#xff1a; 固态机械 磁盘的接口类型&#xff1a; IDESTSTSCSI 磁盘工作的原理&#xff1a; 磁盘&#xff0c;特别是硬盘&#xff0c;和内存不同&#xff0c;…

【网络基础】网络层基本协议介绍

目录 一、IP数据包 1.1 网络层的功能 1.2 IP数据包格式 二、ICMP协议介绍 2.1 作用 2.2 常用命令 2.2.1 Ping命令 2.2.2 tracert命令 2.3 广播域 三、ARP协议介绍 3.1 作用 3.2 原理 一、IP数据包 1.1 网络层的功能 定义了基于IP协议的逻辑地址&#xff0c;就是I…

IDEA使用手册

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

优化选址问题 | 基于禁忌搜索算法求解基站选址问题含Matlab源码

目录 问题代码问题 禁忌搜索算法(Tabu Search)是一种局部搜索算法的扩展,它通过引入一个禁忌列表来避免陷入局部最优解,并允许在一定程度上接受较差的解来跳出局部最优。在基站选址问题中,我们可以使用禁忌搜索算法来寻找满足覆盖要求且基站数量最少的选址方案。 以下是…

无人机采集图像的相关知识

1.飞行任务规划 一般使用飞行任务规划软件进行飞行任务的设计&#xff0c;软件可以自动计算相机覆盖和图像重叠情况。比如ArduPilot (ArduPilot - Versatile, Trusted, Open) 和UgCS (http://www.ugcs.com)是两个飞行任务规划软件&#xff0c;可以适用大多数无人机系统。 2.图…

Java 模拟Spring,实现IOC和AOP的核心(二)

接着上一篇&#xff0c;在上一篇完成了有关IOC的注解实现&#xff0c;这一篇用XML的方式实现IOC&#xff0c;并且完成AOP。 简易的IOC框图 注解的方式实现了左边的分支&#xff0c;那么就剩下右边的XML分支&#xff1a; XmlContext&#xff1a; 这个类是也是AbstractApplicat…

海量数据处理项目-技术Leader必备方法论-SMART衡量需求-工作的利器

海量数据处理项目-技术Leader必备方法论-SMART衡量需求-工作的利器

阿里的库存秒杀是如何实现的?

一、阿里的库存秒杀的实现 阿里有很多业务&#xff0c;几十上百个业务线&#xff0c;各自都有一些需要做抢购、秒杀、热点扣将的场景。他们都用哪些方案呢? 我看了很多资料&#xff0c;也找了很多人做交流&#xff0c;最终得到的结论是啥都有&#xff0c;主要总结几个主流的&…

STM32 ESP8266模块的曲折探索

这是本文的配套资料&#xff0c;最终工程请参考 新_ESP8266资料\stm32f103成功移植的项目 【免费】stm32f103c8t6esp8266资料资源-CSDN文库 一、等到了ready 产品参数 我使用的是ai-thinker的esp8266-01s&#xff0c;以下为产品规格书 引脚定义&#xff1a; 依据引脚定义&…

【深度学习目标检测】二十四、基于深度学习的疲劳驾驶检测系统-含数据集、GUI和源码(python,yolov8)

设计一个疲劳驾驶检测系统的重要性主要体现在以下几个方面&#xff1a; 提高道路安全&#xff1a;疲劳驾驶是引发交通事故的重要因素之一。驾驶员在长时间驾驶或缺乏休息的情况下&#xff0c;反应速度和判断能力会显著下降&#xff0c;从而增加事故风险。通过实时检测驾驶员的疲…

金三银四面试题(一):JVM类加载与垃圾回收

面试过程中最经典的一题&#xff1a; 请你讲讲在JVM中类的加载过程以及垃圾回收&#xff1f; 加载过程 当Java虚拟机&#xff08;JVM&#xff09;启动时&#xff0c;它会通过类加载器&#xff08;ClassLoader&#xff09;加载Java类到内存中。类加载是Java程序运行的重要组成…

AI视频风格转换动漫风:Stable Diffusion+TemporalKit

话不多说&#xff0c;直接开干。 基本方法 首先通过 Temporal-Kit 这个插件提取视频中的关键帧图片&#xff0c;然后使用 Stable Diffusion WebUI 重绘关键帧图片&#xff0c;然后再使用 Temporal-Kit 处理转换后的关键帧图片&#xff0c;它会自动补充关键帧之间的图片&#…

Karmada 管理有状态应用 Xline 的早期探索与实践

背景与动机 目前随着云原生技术和云市场的不断成熟&#xff0c;越来越多的 IT 厂商开始投入到跨云多集群的怀抱当中。以下是 flexera 在 2023 年中关于云原生市场对多云多集群管理的接受程度的调查报告&#xff08;http://info.flexera.com&#xff09; 从 flexera 的报告中可…

优化选址问题 | 基于灰狼算法求解基站选址问题含Matlab源码

目录 问题代码问题 灰狼优化算法(Grey Wolf Optimizer, GWO)是一种基于自然界中灰狼群体狩猎行为的优化算法。这种算法通过模拟灰狼的社会等级和狩猎行为来寻找问题的最优解。 基站选址问题通常是一个多目标优化问题,涉及到覆盖范围、信号质量、成本等多个因素。使用灰狼算…

拌合楼管理软件开发(十一) 海康威视车牌识别摄像头安装调试,记录犯经验主义错误不断自己打脸过程

前言: 从小白开始 海康威视的摄像头接触过,包括前面也都开发了调用sdk开发拍照和视频预览,以及通过事件警报获取数据的。接触到的像头都是12v或者24v电源&#xff0c;或者是POE供电的&#xff0c;先入为主了觉得都是这样&#xff0c;结果打脸了。 一、设备选型&#xff1a; 最开…

glibc内存管理ptmalloc - largebin

前言 上节《glibc内存管理ptmalloc》我们讲了fastbin/unsortedbin/smallbin, 有意避开了largebin, 因为largebin稍微复杂一点点&#xff0c;需要单独一节讲解。 largebin的特点 chunk size 大于等于1024字节largebin共有63个链表largebin每个链表中的chunk size不固定largeb…