【学习分享】全志平台TWI子系统源码分析(1)从设备树到寄存器

2024-01-24


前言

这次开坑主要是想把全志平台TWI子系统在源码层面上彻底理清楚,由于篇幅较大,分成多次讲解。此篇基于T507 kernel-4.9内核,ARM64位操作系统。


一、名词解释

I2C
Inter-Integrated Circuit,用于CPU与外设通信的一种串行总线。
TWI
Normal Two Wire Interface,全志Sunxi平台中的I2C控制器名称。
I2C Adapter
I2C Core将所有I2C控制器称作I2C适配器,可以理解成控制器的软件名称。
I2C Client
指I2C从设备。
Smbus
System Management Bus,系统管理总线,SMBus是基于I2C协议的,要求更严格。SMBus是I2C协议的子集,通过它各设备之间以及设备与系统的其他部分之间可以互相通信。
从以上名词介绍来看,TWI是全志平台的I2C总线控制器。首先理解下,设备是不是都挂在总线上,那么I2C设备则是挂载在I2C总线上的。你要在全志平台上操作I2C设备,那是不是要遵循这颗芯片的规则?TWI跟其他平台的区别,归根结底就是寄存器配置的区别。基本概念需要了解下,才能更好的理解源码的意思。


二、从设备树入手看源码

1.TWI设备树

从设备树入手的原因是,对新手比较友好,简单易懂。Linux很多配置都是在设备树和宏控制上,真正需要修改的源码并不多,不是新手可以直接上手的。这也是为什么有些公司只需要招一个技术主管,其他人找些个刚毕业的小白搬砖就可以了。。。好了,废话不多说了,进入正题。
找一下twi的节点,以twi0为例:

路径:kernel\linux-4.9\arch\arm64\boot\dts\sunxi\sun50iw9p1.dtsi
		twi0: twi@0x05002000{
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "allwinner,sun50i-twi";
			device_type = "twi0";
			reg = <0x0 0x05002000 0x0 0x400>;
			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_twi0>;
			clock-frequency = <400000>;
			pinctrl-names = "default", "sleep";
			pinctrl-0 = <&twi0_pins_a>;
			pinctrl-1 = <&twi0_pins_b>;
			status = "disable";
		};

为了在I2C总线驱动代码中区分每一个TWI控制器,需要在Device Tree中的aliases节点中为每一个TWI节点指定别名。

	aliases: aliases {
		...
		twi0 = &twi0;
		...
		};

我们要操作的TWI0寄存器地址

reg = <0x0 0x05002000 0x0 0x400>;

这个寄存器地址从何而来?从T507规格书上可以查找到,Soc给TWI0分配了一块内存,用来存储TWI0的寄存器配置值。大小是0x400,刚好是1k。

在这里插入图片描述
这就是设备树存在的原因,可以更好的管理各个芯片的设备,对应到芯片真正操作的其实就是寄存器的操作。


2.TWI源码位置

要通过设备树去操作寄存器,那还是要通过代码的运行逻辑去实现的。
通过compatible关键字,Twi0总线设备可以匹配到相对应的设备驱动。

compatible = "allwinner,sun50i-twi";

匹配的过程是在平台总线上实现的,这就是有名的驱动–设备–总线模型。

对应驱动在kernel\linux-4.9\drivers\i2c\i2c-sunxi.c,关键字得到了匹配。

static const struct of_device_id sunxi_i2c_match[] = {
	{ .compatible = "allwinner,sun8i-twi", },
	{ .compatible = "allwinner,sun50i-twi", },
	{},
};

然后看同目录下的Makefile文件,要编译到此文件,需要打开宏控CONFIG_I2C_SUNXI

obj-$(CONFIG_I2C_SUNXI)		+= i2c-sunxi.o

如何打开这个宏呢?在路径linux4.9下执行如下命令

Make ARCH=arm64 menuconfig

在Device Drivers > I2C support > I2C Hardware Bus support中需要勾选SUNXI I2C controller,这部分一般是默认都已经支持的,但是我们要知道原理是怎么样的。
在这里插入图片描述

3.TWI总线相关寄存器

对应路径在kernel\linux-4.9\drivers\i2c\i2c-sunxi.h,定义了TWI的寄存器(截取了前三个)

/* TWI Register Offset */
#define TWI_ADDR_REG		(0x00)	/*  31:8bit reserved,7-1bit for slave addr,0 bit for GCE */
#define TWI_XADDR_REG		(0x04)	/*  31:8bit reserved,7-0bit for second addr in 10bit addr */
#define TWI_DATA_REG		(0x08)	/*  31:8bit reserved, 7-0bit send or receive data byte */

跟规格书也是可以一一对应起来的
在这里插入图片描述


总结

本文从设备树开始讲解,逐步扩展到源码,对于刚入门的开发者更容易理解。后续章节会继续源码的讲解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【学习分享】全志平台TWI子系统源码分析(1)从设备树到寄存器 的相关文章

  • CMake:不要为链接中使用的单个库设置 rpath

    我想要做的是配置我的 CMakeLists 文件 以便在构建我的项目时 链接器使用驻留在我的构建树中的共享库 so 的副本来链接可执行文件 但不会在中设置 rpath链接的可执行文件 以便系统必须在加载程序请求时提供该库 具体来说 我想在构
  • 打印堆栈指针的值

    如何在 Linux Debian 和 Ubuntu 中用 C 打印堆栈指针的当前值 我尝试谷歌但没有找到结果 一个技巧是简单地将本地地址作为指针打印出来 但它不可移植 甚至无法保证有效 void print stack pointer vo
  • Bash 变量:区分大小写?

    Bash shell 脚本区分大小写吗 是可变的date与DATE 是的 它区分大小写 就像 UNIX 的其余部分一样 date and DATE是两个不同的变量 makefile and Makefile是两个不同的文件 h and H是
  • POSIX:FreeBSD 与 Linux 中的管道系统调用

    在 Linux 2 6 35 22 generic 中 man pipe指出 pipeline 创建一个管道 一个可用于进程间通信的单向数据通道 在 FreeBSD 6 3 RELEASE p5 中 man pipe指出 pipeline
  • 将尾部输出重定向到程序中

    我想使用 tail 作为标准输入向程序发送文本文件中的最新行 首先 我向程序回显一些每次都相同的输入 然后从输入文件发送尾部输入 该输入文件应首先通过 sed 处理 以下是我期望工作的命令行 但是当程序运行时 它只接收回显输入 而不接收尾部
  • /etc/php5/conf.d 文件夹中的 .ini 文件有什么用?

    我知道 ini 文件位于 etc php5 cli与 PHP 的 CLI 使用有关 文件位于 etc php5 fpm是关于 PHP 的 FastCGI FPM 方面 但是位于以下位置的 ini 文件又如何呢 etc php5 conf d
  • Linux 中不使用 C++ 的 C 异常处理

    Linux 是否提供了 C 语言的异常处理而不求助于 C 或者 实现此类异常处理的最佳方法是什么 目标是避免检查每个调用的函数的返回码 而是执行类似于 C 的线程安全且易于移植的操作 您可以通过为其编写信号处理程序来处理信号 GNU 记录的
  • 为什么我的 Java 代码执行 bash 命令不正确?

    我试图让我的 Java 程序与 Linux bash 交互 但出了问题 我有一个简单的可执行文件prog从中读取一个整数stdin并输出其平方 执行中 echo 5 prog 从 bash 本身打印正确答案25 in stdout但运行 i
  • 配置错误:无法链接到 boost_system

    我正在尝试在 Debian 上安装一个软件包 足球模拟器 2d 当我进入目录并运行时 configure 我得到以下信息 reza debian soccer rcssserver 15 0 1 configure checking for
  • vm.dirty_ratio 和 vm.dirty_background_ratio 之间的区别?

    我目前正在试验中找到的内核参数 proc sys vm 尤其dirty ratio and dirty background ratio 内核文档对两者都有以下解释 脏背景比例 包含 以包含空闲页面的总可用内存的百分比表示 和可回收页 后台
  • Linux 中如何获取内存修改通知

    在Linux的用户空间程序中 我通过从堆中分配来获取一块内存 然后将指针分发给在其他线程中运行的许多其他组件来使用 当上述内存被修改时我想收到通知 我当然可以开发一个自定义用户空间解决方案 供其他组件在尝试修改内存时使用 我的情况的问题是这
  • 在 Linux 中使用仅限 CLI 的工具生成磁盘使用情况图/图表

    在这个问题中 https stackoverflow com questions 32230 tracking down where disk space has gone on linux有人询问如何在 Linux 中显示磁盘使用情况 我
  • 如何在 Linux 上调用 Python 中的内联机器代码?

    我正在尝试从 Linux 上的纯 Python 代码调用内联机器代码 为此 我将代码嵌入到字节文字中 code b x55 x89 xe5 x5d xc3 然后打电话mprotect http www kernel org doc man
  • 使用正在运行的进程的共享内存收集核心转储

    核心转储仅收集进程空间 而不收集为进程间通信创建的共享内存 如何使核心转储也包含正在运行的进程的共享内存 设置核心文件过滤器 proc PID coredump filter per http man7 org linux man page
  • 在 Unix 中,我可以在目录中运行“make”而无需先 cd 到该目录吗?

    在 Unix 中 我可以运行make在没有的目录中cd首先进入该目录 make C path to dir
  • Web 本地应用程序 Apache:运行 shell 脚本

    我开发了一个 shell 脚本 我想用它创建一个 UI 我决定使用带有本地服务器的 Web 界面 因为我对 HTML PHP 的了解很少 比 QT 或 Java 的了解更多 我只是希望我的 html 可以在我的计算机上运行 shell 脚本
  • 数百个空闲线程的影响

    我正在考虑使用可能数百个线程来实现通过网络管理设备的任务 这是一个在带有 Linux 内核的 powerpc 处理器上运行的 C 应用程序 在每个任务进行同步以将数据从设备复制到任务的初始阶段之后 任务变得空闲 并且仅在收到警报或需要更改一
  • Linux 的 gcc __attribute__((selectany)) 替代方案?

    我想知道是否有替代方案 attribute selectany 在Linux中 我想定义这样的东西 char a qwe zxc 并将其包含在许多链接在一起的 c 文件中 因此链接器将看到 a 的多个定义 因此不会链接 我读过这个属性 se
  • 使用 WGET 运行 cronjob PHP

    我尝试执行一个 cron 并每 5 分钟运行一个 url 我尝试使用 WGET 但我不想下载服务器上的文件 我只想运行它 这是我使用的 crontab 5 wget http www example com cronit php 除了 wg
  • 从命名管道读取

    我必须实现一个 打印服务器 我有 1 个客户端文件和 1 个服务器文件 include

随机推荐