匿名
未登录
登录
百问网嵌入式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=== To instantiate a peripheral, several methods exist: see '''instantiating devices'''<ref ="instantiating-devices">{{CodeSource | Linux kernel | Documentation/i2c/instantiating-devices}} How to instantiate I2C devices</ref> for more details. <br/> The below information focuses on '''device tree''', '''sysfs''' and '''Application Code'''. ==== Device tree ==== The device tree is a description of the hardware that is used by the kernel to know which devices are connected. In order to add a slave device on an I2C bus, complete the device tree with the information related to the new device.<br /> '''Example :''' with an 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> The EEPROM is now instantiated on the bus i2c-X (X depends on how many adapters are probed at runtime) at address 0x50 and it is compatible with the driver registered with the same property.<br/> Please note the driver specifies a SCL rising/falling time as input.<br/> Please refer to [[I2C device tree configuration]] for proper configuration and explanation. Be aware the I2C specification reserves a range of addresses for special purposes, see '''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 /> The below figure shows the relation between the device tree and how it is used :<br /> [[File:i2c-overview-dt.png|840 px|center|link=|relation between device tree and kernel]] ====sysfs==== Through sysfs, i2c-core offers the possibility to instantiate and remove a peripheral: <br /><br /> Add a peripheral "myPeripheralName" attached to the bus x at the address 0xAA<br /> '''Note''' that the field "myPeripheralName" should have the same name as the compatible driver string so that they match one another. <pre> echo myPeripheralName 0xAA > i2c-x/new_device </pre> Remove a peripheral attached to the bus x at the address 0xAA <pre> echo 0xAA > i2c-x/delete_device </pre> Into each driver directory ('''/sys/bus/i2c/drivers/at24/''' for the EEPROM peripheral example), it is possible to:<br /> bind a peripheral with a driver <pre> echo 3-0050 > bind </pre> unbind a peripheral with a driver <pre> echo 3-0050 > unbind </pre> ==== Application code ==== Here is a minimalist code to register a new slave device onto I2C adapter without Device Tree usage. <syntaxhighlight lang="c" line highlight="4-6,18,20"> #include <linux/i2c.h> /* Create a device with slave address <0x42> */ static struct i2c_board_info stm32_i2c_test_board_info = { I2C_BOARD_INFO("i2c_test07", 0x42); }; /* Module define creation skipped */ 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 == In Linux<sup>®</sup> kernel, there are standard ways to debug and monitor I2C. The debug can take place at different levels: hardware and software. ===How to trace=== ====Dynamic trace==== Detailed dynamic trace is available here [[How to use the kernel dynamic debug]]<br/> {{Board$}} echo "file i2c-* +p" > /sys/kernel/debug/dynamic_debug/control This command enables all traces related to I2C core and drivers at runtime.<br/><br/> Nonetheless at [[Menuconfig or how to configure kernel | Linux® Kernel menu configuration]] level, it provides the granularity for debugging: Core and/or Bus.<br/> Device Drivers -> [*] I2C support -> [*] I2C Core debugging messages [*] I2C Bus debugging messages * I2C Core debugging messages (CONFIG_I2C_DEBUG_CORE)<br> Compile I2C engine with DEBUG flag. * I2C Bus debugging messages (CONFIG_I2C_DEBUG_BUS)<br> Compile I2C drivers with DEBUG flag. Having both '''I2C Core''' and '''I2C Bus''' debugging messages is equivalent to using the above dynamic debug command: the dmesg output will be the same. ====Bus snooping==== Bus snooping is really convenient for viewing I2C protocol and see what has been exchanged between the STM32 and the devices.<br/> As this debug feature uses [[Ftrace]], please refer to the [[Ftrace]] article for enabling it. In order to access to events for I2C bus snooping, the following kernel configuration is necessary: Kernel hacking -> [*] Tracers -> [*] Trace process context switches and events Depending on the protocol being used, it is necessary to enable i2c and/or smbus tracers as follow: echo 1 > /sys/kernel/debug/tracing/events/i2c/enable echo 1 > /sys/kernel/debug/tracing/events/smbus/enable Then tracing is enabled using the following command: 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 Here is part of the output, and how it looks like when using ''i2cdetect'' command on the i2c-0 bus: ... 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|Notice that i2cdetect, i2cget/i2cput, i2cdump are doing smbus protocol based transactions.}} On the contrary, below output shows the result of a transaction done in I2C protocol mode: ... 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 The utilization of traces of I2C bus is well described here '''I2C bus snooping'''<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===== When a peripheral is instantiated, i2c-core and the kernel export different files through sysfs :<br /> '''/sys/class/i2c-adapter/i2c-x''' shows all instantiated I2C buses with 'x' being the I2C bus number.<br /> '''/sys/bus/i2c/devices''' lists all instantiated peripherals. For example, there is a directory named '''3-0050''' that corresponds to the EEPROM peripheral at address 0x50 on bus number 3.<br /> '''/sys/bus/i2c/drivers''' lists all instantiated drivers. Directory named '''at24/''' is the driver of 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==== If i2c-dev driver is compiled into the kernel, the directory '''dev''' contains all I2C bus names numbered i2c-0 to i2c-n. <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工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志