I2C 验证
===============

Horizon Robotics
J6X芯片提供了标准的I2C总线，I2C总线控制器通过串行数据线（SDA）和串行时钟（SCL）线在连接到总线的器件间传递信息。

每个器件都有一个唯一的地址（无论是微控制器——MCU、LCD控制器、存储器或键盘接口），而且都可以作为一个发送器和一个接收器（由器件的功能决定）。

在进行I2C芯片的bringup时，关键点包括以下几个方面:

   1. 确保I2C设备的基地址设置正确，避免误配置为其他设备

   2. 确认pinmux寄存器配置为I2C工作模式，确保工作在I2C模式

   3. 确认时钟频率值，设备树dts需要根据时钟值配置

   4. 确认硬件SCL、SDA上拉电阻已正常连接，某些硬件存在未贴上拉电阻的情况

I2C控制器支持以下功能：

- 支持四种速度模式：

   standard mode(0-100Kb/s)

   fast mode(100-400Kb/s)

   fast mode plus(400-1000Kb/s)

   high-speed mode(1000Kb/s-3.4Mb/s)

- 支持主从模式配置

- 支持7位和10位寻址模式

Acore说明
^^^^^^^^^^^^

**代码路径**

.. code:: c

   drivers/i2c/i2c-dev.c # I2C字符设备接口代码
   drivers/i2c/i2c-core-base.c  # I2C框架代码
   drivers/i2c/busses/i2c-designware-platdrv.c   # I2C驱动代码源文件

**内核配置**

.. code:: c

   /*hobot-drivers/configs/hobot_j6e_matrix_defconfig*/
   CONFIG_I2C_CHARDEV=y # i2c驱动应用层配置宏
   CONFIG_I2C_DESIGNWARE_PLATFORM=y # dw i2c驱动配置宏

**基地址说明**

+-------+---------------+--------------+------+
| Name  | Start Address | End Address  | Size |
+=======+===============+==============+======+
|| i2c0 || 0x3942_0000  || 0x3942_FFFF || 64K |
|| i2c1 || 0x3943_0000  || 0x3943_FFFF || 64K |
|| i2c2 || 0x3944_0000  || 0x3944_FFFF || 64K |
|| i2c3 || 0x3945_0000  || 0x3945_FFFF || 64K |
|| i2c4 || 0x3946_0000  || 0x3946_FFFF || 64K |
|| i2c5 || 0x3947_0000  || 0x3947_FFFF || 64K |
+-------+---------------+--------------+------+

**DTS设备节点配置**

.. code:: c

   /*hobot-drivers/kernel-dts/hobot-j6e-matrix.dts*/
   i2c0: i2c@39420000 {
         #address-cells = <1>;
         #size-cells = <0>;
         compatible = "snps,designware-i2c";
         reg = <0x0 0x39420000 0x0 0x10000>;
         clocks = <&clk_240m>;
         clock-names = "apb_pclk";
         interrupts = <GIC_SPI PERISYS_I2C0_INTR PERISYS_I2C0_INTR_TRIG_TYPE>;
         clock-frequency = <400000>;  //接口速率配置,支持100000/400000/1000000/3400000
         pinctrl-names = "default", "gpio";
         pinctrl-0 = <&cam_i2c0>;
         pinctrl-1 = <&cam_i2c0_gpio>;
         scl-gpios = <&cam_port0 8 GPIO_ACTIVE_HIGH>;
         sda-gpios = <&cam_port0 9 GPIO_ACTIVE_HIGH>;
         status = "okay";
   };

**I2C使用**

对于I2C的使用说明在kernel/Documentation/i2c目录下有详细的说明，本文主要列出J6X I2C驱动接口特殊的部分。

Kernel Space
----------------

接口速率配置
~~~~~~~~~~~~~~~~

默认的I2C速率为400K，支持100k/400k/1M/3.4M四种速率，可通过修改dts中相应i2c节点的clock-frequency完成速率修改。

User Space
--------------

通常，I2C设备由内核驱动程序控制，但也可以从用户态访问总线上的所有设备，例如，可以通过/dev/i2c-0来访问i2c0，kernel/Documentation/i2c/dev-interface文件里有详细的介绍。

i2c-tools
~~~~~~~~~~~~~

i2c-tools是一套开源工具，该工具已经被交叉编译并包含在J6X系统软件的rootfs中，客户可以直接使用：

-  i2cdetect — 用来列举I2C bus及该bus上的所有设备

-  i2cdump — 显示i2c设备的所有register值

-  i2cget — 读取i2c设备某个register的值

-  i2cset — 写入i2c设备某个register的值

I2C测试
-----------

检查i2cdev节点
~~~~~~~~~~~~~~~~~~

查看是否产生i2c-dev节点，以下设备均配置为主设备

.. code:: shell

   root@hobot:~# ls /sys/class/i2c-dev/
   i2c-0  i2c-1  i2c-2  i2c-3  i2c-4  i2c-5

   root@hobot:~# cat /sys/class/i2c-dev/i2c-0/name
   Synopsys DesignWare I2C adapter

查看i2c设备节点是否产生

.. code:: shell

   root@hobot:~# ls /sys/class/i2c-dev/i2c-0/device/
   delete_device  device  i2c-dev  name  new_device  of_node  power  subsystem  uevent

测试步骤
~~~~~~~~~~~~

| 测试命令：i2cdetect
| 测试示例如下

.. code:: shell

   root@hobot:~# i2cdetect -r -y 3
        0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
   00:          -- -- -- -- -- -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   40: 40 41 42 43 44 45 -- 47 -- -- -- -- -- 4d -- --
   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   70: -- -- -- -- -- -- UU --

| 测试命令：i2cset
| 测试示例如下：

.. code:: shell

   root@hobot:~# i2cset -f -y 0 0x28 0x01 0x1e

| 测试命令: i2cget
| 测试示例如下：

.. code:: shell

   root@hobot:~# i2cget -f -y 0 0x28 0x01
   0x1e

MCU说明
^^^^^^^^^^^^

**代码路径**

.. code:: c

   McalCdd/I2c/src/I2c.c   # 驱动代码
   McalCdd/I2c/src/I2c_Lld.c # 底层驱动代码
   McalCdd/I2c/inc/I2c.h  # 驱动头文件
   McalCdd/I2c/inc/I2c_Lld.h # 底层驱动头文件
   Config/McalCdd/gen_matrix_A/I2c/src/I2c_PBcfg.c  # PB配置文件，gen_matrix_A为样例，根据具体板块类型确定目录
   Config/McalCdd/gen_matrix_A/I2c/inc/I2c_PBcfg.h  # PB配置头文件

**基地址说明**

+-------+---------------+--------------+------+
| Name  | Start Address | End Address  | Size |
+=======+===============+==============+======+
|| i2c6 || 0x2344_0000  || 0x2344_FFFF || 64K |
|| i2c7 || 0x2345_0000  || 0x2345_FFFF || 64K |
|| i2c8 || 0x2346_0000  || 0x2346_FFFF || 64K |
|| i2c9 || 0x2347_0000  || 0x2347_FFFF || 64K |
+-------+---------------+--------------+------+

**I2C使用**

驱动层面配置
----------------
默认的I2C速率为400K，支持100k/400k/1M/3.4M四种速率，可通过I2c_PBcfg.c修改中相应i2c代码完成主从模式配置和速率修改。

.. code:: c

   const I2c_ConfigType I2cConfig[2] =
   {

      {
         6,
         MASTER_MODE,   //Master模式，或者配置为SLAVE_MODE
         ADDRESS_7_BITS,
         I2C_STANDARD_MODE, //标准速率，也可以配置为I2C_FAST_MODE等
         0
      },

      {
         7,
         SLAVE_MODE,
         ADDRESS_7_BITS,
         I2C_FAST_MODE,
         52 //如果为slave模式，需要配置slave地址，供其他master访问
      },

   };


使用层面配置
--------------

使用方面，mcu提供了三个i2cset、i2cget和i2cdetect命令用于调试和验证i2c是否工作正常

.. code:: shell

   i2cdetect             CMD   --------  i2cdetect Channel
   i2cget                CMD   --------  i2cget ch SlaveAddr Reg
   i2cset                CMD   --------  i2cset ch SlaveAddr Reg Val

| 测试命令：i2cdetect + 通道名字(0-3)
| 测试示例如下

.. code:: shell

   horizon:/$ i2cdetect 0
      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
   00:    -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   40: 40 41 42 -- -- -- -- -- -- -- -- -- -- -- -- --
   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   60: -- -- 62 -- -- -- -- -- -- -- -- -- -- -- -- --
   70: -- -- -- -- -- -- -- --

| 测试命令：i2cset + 通道名字(0-3) + Slave地址 + 寄存器地址 + 配置值
| 测试示例如下

.. code:: shell

   horizon:/$ i2cset 0 0x40 0x00 0xde

| 测试命令：i2cget + 通道名字(0-3) + Slave地址 + 寄存器地址
| 测试示例如下

.. code:: shell

   horizon:/$ i2cget 0 0x40 0x00
   de
