匿名
未登录
登录
百问网嵌入式Linux wiki
搜索
查看“I2C overview”的源代码
来自百问网嵌入式Linux wiki
名字空间
页面
讨论
更多
更多
页面选项
Read
查看源代码
历史
←
I2C overview
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
本文提供有关I2C系统以及如何插入I2C STM32驱动程序的基本信息。 ==Framework purpose== 本文旨在解释如何更准确地使用I2C: * 如何在 Linux<sup>®</sup> BSP 上激活I2C接口 * 如何从内核空间访问I2C * 如何从用户空间访问I2C。 本文介绍了在'''master''' 和 '''slave'''模式下的 Linux<sup>®</sup> I<sup>2</sup>C<ref name="More about I2C">http://www.i2c-bus.org/</ref>接口。 通过该外部资源,提出了I<sup>2</sup>C<ref name="I2C introduction">https://bootlin.com/doc/training/linux-kernel/</ref> 的简介。 有关 '''slave''' 接口的说明,请参见'''slave-interface'''<ref>{{CodeSource | Linux kernel | Documentation/i2c/slave-interface}} slave interface description</ref>.<br /> ==System overview== I<sup>2</sup>C 是“ IC间总线”的缩写,“ Inter-IC”总线是一种简单的总线协议,广泛用于低数据速率通信就足够了。<br /> I2C是微处理器 I<sup>2</sup>C 外围设备接口的缩写。 在微处理器设备周围,用户可以添加许多 I<sup>2</sup>C 外部设备来创建定制板。 可以通过I2C从用户空间或内核空间访问每个外部设备。 {{ImageMap| Image: i2c-overview-new.png {{!}} frame {{!}} center {{!}} Implementation architecture rect 430 114 548 157 [[I2C overview#i2c-tools | I2C Tools]] rect 641 113 759 156 [[I2C overview#Application | Application ]] circle 489 183 10 [[I2C overview#libi2c | I2C Library]] rect 430 205 548 248 [[I2C overview#i2c-tools | I2C Tools]] circle 489 309 10 [[I2C overview#User_space_application | User Space Application]] rect 312 332 430 375 [[I2C overview#Board_peripheral_drivers | Board peripheral drivers]] rect 548 332 666 375 [[I2C overview#Board_peripheral_drivers | Board peripheral drivers]] rect 747 363 865 406 [[I2C overview#Board_peripheral_drivers | Board peripheral drivers]] rect 361 406 615 452 [[I2C overview#i2c-core | I2C core engine]] circle 489 408 10 [[I2C overview#Kernel_space_peripheral_driver | Kernel space peripheral driver]] rect 430 469 548 512 [[I2C overview#i2c-stm32 | STM32 I2C driver]] rect 430 550 548 593 [[I2C_overview#STM32_I2C_internal_peripheral_controller | STM32 I2C peripheral]] rect 746 550 863 593 [[I2C_overview#STM32_I2C_internal_peripheral_controller | STM32 I2C peripheral]] rect 312 642 430 687 [[I2C_overview#Board_external_I2C_devices | Board peripheral]] rect 548 642 666 687 [[I2C_overview#Board_external_I2C_devices | Board peripheral]] rect 747 642 865 687 [[I2C_overview#Board_external_I2C_devices | Board peripheral]] }} ===Component description=== ====Board external I<sup>2</sup>C devices==== * 从设备X是相对于STM32表现为从设备的物理设备(通过 I<sup>2</sup>C 总线连接到STM32)。<br/> STM32仍是 I<sup>2</sup>C 总线上的主机。 * 主设备X是相对于STM32充当主设备的物理设备 (通过 I<sup>2</sup>C 总线连接到STM32) 。<br/> 在这种情况下,STM32充当 I<sup>2</sup>C 总线上的从设备。 ====STM32 I2C internal peripheral controller==== 它对应于STM32 I2C适配器,该适配器处理与同一总线上连接的任何外部设备的通信。 <br/>它管理从设备(如果有的话),并且如果连接了外部主设备,则可以充当从设备。 STM32微处理器设备通常嵌入 [[I2C internal peripheral]] 的多个实例,以管理多个I2C总线。 提供了一个驱动程序,用于控制硬件。 ====i2c-stm32==== 内部STM32 I2C控制器驱动程序向基于i2c-core-base的ST I2C内部外围控制器抽象层提供了支持。<br/> 它定义了I2C核心基础要使用的所有I2C传输方法算法,其中包括I2C和SMBus<ref name="More about SMBus">https://www.i2c-bus.org/smbus/</ref> 传输API ,注册/注销从属API和功能检查。<br/> 即使I2C Core可以在整个标准I2C消息中模拟SMBus协议,所有SMBus功能都在驱动程序中实现。 ====i2c-core==== 这是通信的大脑:它实例化和管理所有总线和外围设备。 * 如其名称所述,为'''{{Highlight|i2c-core}}''' ,它是I2C核心引擎,但它也负责解析适配器和/或设备的设备树条目 * '''{{Highlight|i2c-core-smbus}}'''处理所有与SMBus相关的API。 * '''{{Highlight|i2c-core-slave}}''' 管理充当STM32中的从设备的I2C设备。 * '''{{Highlight|i2c-smbus}}'''处理特定的协议SMBus警报。 (由I2C核心库处理的SMBus主机通知) ====Board peripheral drivers==== 该层表示与物理外围设备关联的所有驱动程序。<br/> 外围设备驱动程序可以编译为内核模块,也可以直接编译为内核(也称为内置). ====i2c-dev==== i2c-dev是用户与外围设备之间的接口。 它是一个内核驱动程序,它使用此dev-interface API提供对用户空间应用程序的I2C总线访问。 请参见示例[[I2C overview#API_description|API Description]]. ====i2c-tools==== [[I2C_i2c-tools | I2C Tools]]软件包提供了: * shell命令通过i2c-dev通过SMBus协议访问I2C * library 将SMBus函数用于用户空间应用程序,所有这些函数都在这个SMBus协议API中进行了描述。<br/> '''Note''' : 某些外围设备无需SMBus协议即可工作。 ====Application==== 应用程序可以使用 [[I2C_i2c-tools | I2C Tools]], libI2C ([[I2C_i2c-tools|I2C Tools]]), i2c-dev. ===API description=== ====libi2c==== I2C工具<ref name="I2C tools">https://i2c.wiki.kernel.org/index.php/I2C_Tools</ref> 软件包提供了一组Shell命令,这些命令主要使用SMBus协议访问I2C和API, 开发一个应用程序(libi2c)。<br/> 所有工具和libi2c均依赖SMBus API,但[[I2C_i2c-tools#I2C_Transfer| i2ctransfer]]不是,因为它依赖于标准I2C协议。<br/> 工具和libi2c通过'''devfs'''读/写/ ioctl调用访问SMBus和I2C API。<br/><br/> SMBus协议构成 I<sup>2</sup>C 规范中定义的数据传输格式的子集。 <br/> SMBus规范中定义的标准方法无法访问不符合这些协议的I2C外设。 <br/> 有关 '''I<sup>2</sup>C'''<ref name="I2C summary">{{CodeSource | Linux kernel | Documentation/i2c/summary}} I2C and SMBus summary</ref> 和'''SMBus协议'''<ref name="SMBus protocol">{{CodeSource | Linux kernel | Documentation/i2c/smbus-protocol}} SMBus protocol summary</ref>的更多详细信息,请参见外部参考。 libi2c API模拟“SMBus协议”<ref name="SMBus protocol">{{CodeSource | Linux kernel | Documentation/i2c/smbus-protocol}} SMBus protocol summary</ref> ,但在用户空间级别。<br/> 此库中的API与 ''SMBus protocol''<ref name="SMBus protocol">{{CodeSource | Linux kernel | Documentation/i2c/smbus-protocol}} SMBus protocol summary</ref>中的API相同。除了特定的SMBus协议API(例如SMBus Host Notify和SMBus Alert)外,所有SMBus API均在此处重复。 ====User space application==== [[#user_space_application| User space application]] 正在使用内核驱动程序(i2c-dev),该驱动程序通过devfs提供I2C访问。<br /> '''支持的系统调用: '''open(), close(), read(), write(), ioctl(), llseek(), release().<br /> {| |+ Supported ioctls commands |- !Constant !Description |- |I2C_SLAVE/I2C_SLAVE_FORCE |Sets slave address for read/write operations |- |I2C_FUNCS |Gets bus functionalities |- |I2C_TENBIT |10bits address support |- |I2C_RDWR |Combined R/W transfer (one STOP only) |- |I2C_SMBUS |Perform an SMBus transfer instead of standard I<sup>2</sup>C |} 以上命令是主要命令(框架中定义了更多命令): 请参见'''dev-interface API'''<ref name="dev-interface API">{{CodeSource | Linux kernel | Documentation/i2c/dev-interface}} dev-interface API</ref> 获取完整列表。 ====Kernel space peripheral driver==== [[#Kernel_space_driver| Kernel space peripheral driver]] 同时访问 I<sup>2</sup>C 和SMBus设备,并使用以下 '''I2C核心API'''<ref name="I2C core API">https://www.kernel.org/doc/html/latest/driver-api/i2c.html</ref> ==Configuration== ===Kernel configuration=== 使用Linux Menuconfig工具在内核配置中激活I2C: [[Menuconfig or how to configure kernel]]. [x] Device Drivers [x] I2C support [x] I2C device interface [ ] I2C Hardware Bus support [x] STMicroelectronics STM32F7 I2C support 这可以在您的内核中手动完成: CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_STM32F7=y 如果软件需要SMBus特定协议,例如SMBus Alert协议和SMBus Host Notify协议,则添加: [x] Device Drivers [x] I2C support [x] I2C device interface [ ] Autoselect pertinent helper modules [x] SMBus-specific protocols [ ] I2C Hardware Bus support [x] STMicroelectronics STM32F7 I2C support 这可以在您的内核中手动完成: CONFIG_I2C_SMBUS=y ===Device tree configuration=== 请参考[[I2C device tree configuration]]. ==How to use the framework== 本节介绍如何使用框架访问I2C外设。 ===i2c-tools package=== 在用户空间中将[[I2C_i2c-tools | I2C Tools]] 与基于'''SMBus API协议'''<ref name="SMBus protocol">{{CodeSource | Linux kernel | Documentation/i2c/smbus-protocol}} SMBus protocol summary</ref> 的shell命令配合使用,可以轻松快速地访问I2C,而无需编写任何代码。<br /> '''用例''' 许多外壳命令允许检测I2C总线并通过SMBus协议访问I2C外设。 该软件包包括一个库,以便在C程序中使用SMBus协议。<br /> 有关详细说明,请访问[[I2C_i2c-tools| link]]。 [[File:i2c-tools-overview.png|800px|center|link=|Using i2c-tools overview]] === User space application === 允许在用户空间中使用带有此 '''device interface'''的i2c-dev内核驱动程序来开发应用程序。<ref name="dev-interface API">{{CodeSource | Linux kernel | Documentation/i2c/dev-interface}} dev-interface API</ref>.<br /> '''用例:'''通过加载i2c-dev模块,用户可以通过'''/dev'''接口访问I2C。 通过函数open()、ioctl()、read()、write()和lose()可以非常轻松地访问I2C。 如果外围设备兼容,则也可以使用 [[I2C_i2c-tools | I2C Tools]] 库。<br /> [[File:i2c-dev-overview.png|800px|center|link=|Using i2c-dev overview]] === Kernel space driver === 允许使用'''I2C core API'''开发已编译到内核或作为模块插入的驱动程序<ref name="I2C core API"/><br /> Linux内核提供了有关如何编写I2C客户端驱动程序的示例 <ref>https://www.kernel.org/doc/html/latest/i2c/writing-clients.html</ref><br /> '''用例''' : 使用内核空间内的特定驱动程序控制I2C外设。 例如,驱动程序在系统引导时初始化所有参数,并通过sysfs创建对外围数据的访问。<br /> [[File:i2c-driver-overview.png|800 px|center|link=|Using driver i2c overview]] ===Board description=== 要实例化外围设备,存在几种方法:更多细节,请参见 '''实例化设备'''<ref ="instantiating-devices">{{CodeSource | Linux kernel | Documentation/i2c/instantiating-devices}} How to instantiate I2C devices</ref> 。 <br/> 下列资料主要介绍 '''device tree''', '''sysfs''' 和 '''Application Code'''. ==== Device tree ==== 设备树是对内核用来了解连接哪些设备的硬件的描述。为了在I2C总线上添加从设备,请使用与新设备相关的信息来完成设备树。<br /> '''例子:''' 带有EEPROM <syntaxhighlight lang="c" line highlight="10-14"> &i2c4 { status = "okay"; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; dmas = <&mdma1 36 0x0 0x40008 0x0 0x0 0>, <&mdma1 37 0x0 0x40002 0x0 0x0 0>; dma-names = "rx", "tx"; eeprom@50 { compatible = "at,24c256"; pagesize = <64>; reg = <0x50>; }; }; </syntaxhighlight> EEPROM现在在地址为0x50的总线i2c-X上实例化(X取决于运行时探测的适配器数量),并且它与使用相同属性注册的驱动程序兼容。<br/> 请注意,驱动程序指定SCL上升/下降时间作为输入。<br/> 有关正确的配置和说明,请参考 [[I2C device tree configuration]]。 请注意,I2C规范为特殊目的保留了一系列地址,请参阅 '''slave addressing'''<ref name="slave addressing">http://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing Slave addressing</ref>.<br /> 下图显示了设备树及其用法之间的关系:<br /> [[File:i2c-overview-dt.png|840 px|center|link=|relation between device tree and kernel]] ====sysfs==== 通过sysfs,i2c-core提供了实例化和删除外围设备的可能性:<br /><br /> 在地址0xAA上添加附加到总线x的外围设备“ myPeripheralName”<br /> '''注意''' 字段 "myPeripheralName" 应该与兼容的驱动程序字符串具有相同的名称,以便它们彼此匹配。 <pre> echo myPeripheralName 0xAA > i2c-x/new_device </pre> 卸下连接到总线x的地址0xAA的外围设备 <pre> echo 0xAA > i2c-x/delete_device </pre> 进入每个驱动程序目录('''/sys/bus/i2c/drivers/at24/''' for the EEPROM peripheral example), it is possible to:<br /> 将外围设备与驱动器绑定 <pre> echo 3-0050 > bind </pre> 取消外围设备与驱动程序的绑定 <pre> echo 3-0050 > unbind </pre> ==== Application code ==== 这是用于在不使用设备树的情况下将新的从设备注册到I2C适配器的极简代码。 <syntaxhighlight lang="c" line highlight="4-6,18,20"> #include <linux/i2c.h> /* 创建具有从属地址的设备 <0x42> */ static struct i2c_board_info stm32_i2c_test_board_info = { I2C_BOARD_INFO("i2c_test07", 0x42); }; /* 跳过模块定义创建 */ static int __init i2c_test_probe(void) { struct i2c_adapter *adap; struct i2c_client *client; /* Get I2C controller */ adap = i2c_get_adapter(i); /* Build new devices */ client = i2c_new_device(adap,&stm32_i2c_test_board_info); } </syntaxhighlight> ==How to trace and debug the framework == 在 Linux<sup>®</sup> 内核中,有调试和监视I2C的标准方法。调试可以在不同的级别进行:硬件和软件。 ===How to trace=== ====Dynamic trace==== 此处提供了详细的动态跟踪 [[How to use the kernel dynamic debug]]<br/> {{Board$}} echo "file i2c-* +p" > /sys/kernel/debug/dynamic_debug/control 此命令在运行时启用与I2C内核和驱动程序有关的所有跟踪。<br/><br/> 尽管如此,在 [[Menuconfig or how to configure kernel | Linux® Kernel menu configuration]] 级,它提供了调试的粒度:核心和/或总线。<br/> Device Drivers -> [*] I2C support -> [*] I2C Core debugging messages [*] I2C Bus debugging messages * I2C核心调试消息 (CONFIG_I2C_DEBUG_CORE)<br> 使用DEBUG标志编译I2C引擎。 * I2C总线调试消息(CONFIG_I2C_DEBUG_BUS)<br> 用DEBUG标志编译I2C驱动程序。 同时具有 '''I2C Core''' 和 '''I2C Bus'''调试消息等同于使用上述动态调试命令:dmesg输出将相同。 ====Bus snooping==== 总线侦听对于查看I2C协议以及查看STM32和设备之间交换的内容非常方便。<br/> 由于此调试功能使用 [[Ftrace]],因此请参考[[Ftrace]] 文章以启用它。 为了访问事件以进行I2C总线侦听,必须进行以下内核配置: Kernel hacking -> [*] Tracers -> [*] Trace process context switches and events 根据所使用的协议,有必要启用i2c和/或smbus跟踪器,如下所示: echo 1 > /sys/kernel/debug/tracing/events/i2c/enable echo 1 > /sys/kernel/debug/tracing/events/smbus/enable 然后使用以下命令启用跟踪: echo 1 > /sys/kernel/debug/tracing/tracing_on After a transaction, trace can be read by looking at the trace file: cat /sys/kernel/debug/tracing/trace 这是输出的一部分,以及在i2c-0总线上使用“ i2cdetect”命令时的外观: ... smbus_write: i2c-0 a=003 f=0000 c=0 QUICK l=0 [] ... smbus_result: i2c-0 a=003 f=0000 c=0 QUICK wr res=-6 ... smbus_write: i2c-0 a=004 f=0000 c=0 QUICK l=0 [] ... smbus_result: i2c-0 a=004 f=0000 c=0 QUICK wr res=-6 {{Info|请注意,i2cdetect,i2cget / i2cput,i2cdump正在执行基于smbus协议的事务.}} 相反,以下输出显示了以I2C协议模式完成的事务的结果: ... i2c_write: i2c-1 #0 a=042 f=0000 l=1 [45] ... i2c_result: i2c-1 n=1 ret=1 ... i2c_write: i2c-2 #0 a=020 f=0000 l=1 [45] ... i2c_result: i2c-2 n=1 ret=1 I2C总线走线的使用在此处进行了很好的描述 '''I2C 总线监听'''<ref name="I2C bus snooping">https://linuxtv.org/wiki/index.php/Bus_snooping/sniffing#i2c I2C Bus Snooping</ref>. ===How to debug=== ====Detect I2C configuration==== =====sysfs===== 实例化外围设备后,i2c-core和内核会通过sysfs导出不同的文件:<br /> '''/sys/class/i2c-adapter/i2c-x''' 显示所有实例化的I2C总线,其中“ x”为I2C总线号。<br /> '''/sys/bus/i2c/devices'''列出所有实例化的外围设备。例如,有一个名为'''3-0050'''的目录,它对应于总线号3上地址0x50的EEPROM外设。<br /> '''/sys/bus/i2c/drivers''' 列出所有实例化的驱动程序。 名为'''at24 /'''的目录是EEPROM的驱动程序。<br /> <pre> /sys/bus/i2c/devices/3-0050/ / / / /i2c-3/3-0050/ / /drivers/at24/3-0050/ </pre> <pre> /sys/class/i2c-adapter/i2c-0/ /i2c-1/ /i2c-2/ /i2c-3/3-0050/ /i2c-4/ /i2c-5/ </pre> ====devfs==== 如果将i2c-dev驱动程序编译到内核中,则目录'''dev'''包含所有编号为i2c-0至i2c-n的I2C总线名称。 <pre> /dev/i2c-0 /i2c-1 /i2c-2 /i2c-3 /i2c-4 /i2c-n </pre> ====i2c-tools==== Check all I2C instantiated adapters: {{Board$}}i2cdetect -l See [[I2C_i2c-tools| i2c-tools]] for full description. ==Source code location== * I2C Framework driver is in {{CodeSource | Linux kernel | drivers/i2c drivers/i2c}} * I2C STM32 Driver is in {{CodeSource | Linux kernel | drivers/i2c/busses/i2c-stm32f7.c}} * User API for I2C bus is in {{CodeSource | Linux kernel | include/uapi/linux/i2c.h}} and I2C dev is {{CodeSource | Linux kernel | include/uapi/linux/i2c-dev.h}}. ==To go further== Bootlin has written a nice walkthrough article: ''Building a Linux system for the STM32MP1: connecting an I2C sensor''<ref name="Building a Linux system for the STM32MP1: connecting an I2C sensor">https://bootlin.com/blog/building-a-linux-system-for-the-stm32mp1-connecting-an-i2c-sensor/</ref> ==References== <references />
该页面使用的模板:
模板:Board$
(
查看源代码
)
模板:CodeSource
(
查看源代码
)
模板:Highlight
(
查看源代码
)
模板:ImageMap
(
查看源代码
)
模板:Info
(
查看源代码
)
模板:STDarkBlue
(
查看源代码
)
返回至
I2C overview
。
导航
导航
WIKI首页
官方店铺
资料下载
交流社区
所有页面
所有产品
MPU-Linux开发板
MCU-单片机开发板
Linux开发系列视频
单片机开发系列视频
所有模块配件
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志