This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[J6] transfer data between two I2C master interface

We are going to transfer data by I2C interface between two J6 SoC. I set OA(Own-Address) for both side without doing slave configuration. Then, i start transfer data from one side to the other, and it work, the other side can receive I2C data without configuring to I2C salve mode. Is this normal?

As i know, I2C transfer should happend from "master to slave" or "slave to master", can it happend in "master to master"?

  • Hi,

    I2C bus being open-drain eliminates bus driver contention what would happen with 2 masters trying to control the bus.

    Additionally, the way I2C was integrated, allows for clock flowing in to I2C even it is in master mode.

    You are right – there cannot be two masters at the same time on the bus.
    That’s why:
    If you are implementing multi-master system, software must implement the master negotiation.
    If you are implementing single-master system, software should set all nodes accordingly at startup.

    Regards,
    Mariya
  • Hi Mariya,

    Thanks for your reply.

    In i2c-omap.c, i add response for receiving AAS IRQ. So, if one master(master-A) trying to send data to the other master(master-B), master-B will get AAS IRQ and response ACK to master-A, then master-A will start transfer data to master-B. While transferring, master-B will receive RRDY IRQ, and i can get data from data register of master-B.

    What i'm trying to figure out is, all these process seems to be a normal I2C transfer process, only without slave configuration for master-B. So may i treat these process still a normal I2C transfer? After all, i get all data from master-A. 

  • Hi Shawn,

    TI I2C modules support multi-master bus. It is ok to communicate between two masters.
    As I understood, you configured Own addresses for both masters, and this is the address of the node regardless of being master or slave.
    Note that if you plan to use several masters on the bus, then all masters must support multi-master function.
    Regards,
    Stan
  • Hi Stanislav,

    Recently, i found my I2C test program could cause system crash probablistic. Could you help me to verify my test steps, is there something wrong with it. Here it is
    1.I2C-A set it's own address
    2.Use command "i2cget -y 3 0x33" to let I2C-A wake-up from suspend. Without wake it up, I2C-A can't get AAS IRQ while I2C-B sending message to I2C-A
    3.Before I2C-A enter suspend, I2C-B start sending message(1024 bytes) to I2C-A.
    4.I2C-A will ack for AAS IRQ. Then, while I2C-A get RRDY IRQ, will get data from data register.
    5.After that, I2C-A will enter suspend mode automatically.

    The test program will start over again and again. Sometimes system crash after test 100 times, but sometimes less than 10 times. I think step-2 may be is the reason, beccause i let I2C-A to read data from non-existence device(0x33). But if i didn't do this, I2C-A will stay in suspend mode and can't get AAS IRQ. Could you help me to clarify what's the reason to cause system crash?

    Below is log data while sysem crash
    ----------------------------------------------------------------------------------------------
    Unable to handle kernel paging request at virtual address 53fd3378
    pgd = c0004000
    [53fd3378] *pgd=00000000
    Internal error: Oops: 5 [#1] PREEMPT SMP ARM
    Modules linked in: dwc3_omap
    CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W O 3.14.63 #2
    task: c06dcd28 ti: c06d2000 task.ti: c06d2000
    PC is at task_waking_fair+0x1c/0xb4
    LR is at try_to_wake_up+0x11c/0x248
    pc : [<c005d800>] lr : [<c005a7bc>] psr: a00f0193
    sp : c06d3dc0 ip : c06d3dd8 fp : c06d3dd4
    r10: 00000000 r9 : ea760430 r8 : a00f0193
    r7 : ea36087c r6 : ea760390 r5 : 00000001 r4 : ea3604c0
    r3 : c06cf9c0 r2 : c06da7f4 r1 : e4e3e2e1 r0 : ea3604c0
    Flags: NzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel
    Control: 10c5387d Table: a968406a DAC: 00000015
    Process swapper/0 (pid: 0, stack limit = 0xc06d2240)
    Stack: (0xc06d3dc0 to 0xc06d4000)
    3dc0: ea3604c0 00000001 c06d3e04 c06d3dd8 c005a7bc c005d7f0 ea3604c0 e9787b40
    omap_i2c_runtime_suspend
    3de0: ea7603c8 ea760390 c005205c ea760390 ea760430 ea760468 c06d3e14 c06d3e08
    3e00: c005a918 c005a6ac c06d3e24 c06d3e18 c0052084 c005a90c c06d3e44 c06d3e28
    3e20: c0052314 c0052068 d0f1a0a3 0000000f ffffffff 7fffffff c06d3eac c06d3e48
    3e40: c0052ca8 c00522c8 d0f1a0a3 0000000f 00000000 ea7603c8 cff557d6 0000000f
    3e60: ea7604a0 00000003 d0f1a0a3 0000000f d0f1a0a3 0000000f d0f1a0a3 0000000f
    3e80: 00000000 ea02f0c0 c0700444 ea02e580 00000013 ea764140 412fc0f2 00000000
    3ea0: c06d3ebc c06d3eb0 c03e91cc c0052b84 c06d3ee4 c06d3ec0 c0071d60 c03e91a8
    3ec0: c0071cf0 00000013 00000000 c06da978 c06d3f6c eb7ff580 c06d3efc c06d3ee8
    3ee0: c006e478 c0071cfc 0000018f 00000013 c06d3f14 c06d3f00 c000ec08 c006e45c
    3f00: fa212000 c06d3f38 c06d3f34 c06d3f18 c0008504 c000eba8 c00261e4 c000ef24
    3f20: a00f0013 ffffffff c06d3f8c c06d3f38 c04cb740 c00084cc ffffffed 00000000
    3f40: 2a092000 c0026630 c06d2000 c07269c0 ffffffff c06c1ad0 eb7ff580 412fc0f2
    3f60: 00000000 c06d3f8c c06d3f80 c06d3f80 c00261e4 c000ef24 a00f0013 ffffffff
    3f80: c06d3f9c c06d3f90 c006e1f8 c000eef8 c06d3fb4 c06d3fa0 c04c2450 c006e148
    3fa0: 60000053 c06da600 c06d3ff4 c06d3fb8 c068db4c c04c23e4 ffffffff ffffffff
    3fc0: c068d5cc 00000000 00000000 c06c1ad0 00000000 10c5387d c06da4ac c06c1acc
    3fe0: c06dddd0 8000406a 00000000 c06d3ff8 80008074 c068d848 00000000 00000000
    Backtrace:
    [<c005d7e4>] (task_waking_fair) from [<c005a7bc>] (try_to_wake_up+0x11c/0x248)
    r5:00000001 r4:ea3604c0
    [<c005a6a0>] (try_to_wake_up) from [<c005a918>] (wake_up_process+0x18/0x1c)
    r10:ea760468 r9:ea760430 r8:ea760390 r7:c005205c r6:ea760390 r5:ea7603c8
    r4:e9787b40 r3:ea3604c0
    [<c005a900>] (wake_up_process) from [<c0052084>] (hrtimer_wakeup+0x28/0x30)
    [<c005205c>] (hrtimer_wakeup) from [<c0052314>] (__run_hrtimer+0x58/0xd0)
    [<c00522bc>] (__run_hrtimer) from [<c0052ca8>] (hrtimer_interrupt+0x130/0x290)
    r7:7fffffff r6:ffffffff r5:0000000f r4:d0f1a0a3
    [<c0052b78>] (hrtimer_interrupt) from [<c03e91cc>] (arch_timer_handler_virt+0x30/0x38)
    r10:00000000 r9:412fc0f2 r8:ea764140 r7:00000013 r6:ea02e580 r5:c0700444
    r4:ea02f0c0
    [<c03e919c>] (arch_timer_handler_virt) from [<c0071d60>] (handle_percpu_devid_irq+0x70/0x8c)
    [<c0071cf0>] (handle_percpu_devid_irq) from [<c006e478>] (generic_handle_irq+0x28/0x38)
    r8:eb7ff580 r7:c06d3f6c r6:c06da978 r5:00000000 r4:00000013 r3:c0071cf0
    [<c006e450>] (generic_handle_irq) from [<c000ec08>] (handle_IRQ+0x6c/0x94)
    r4:00000013 r3:0000018f
    [<c000eb9c>] (handle_IRQ) from [<c0008504>] (gic_handle_irq+0x44/0x68)
    r5:c06d3f38 r4:fa212000
    [<c00084c0>] (gic_handle_irq) from [<c04cb740>] (__irq_svc+0x40/0x70)
    Exception stack(0xc06d3f38 to 0xc06d3f80)
    3f20: ffffffed 00000000
    3f40: 2a092000 c0026630 c06d2000 c07269c0 ffffffff c06c1ad0 eb7ff580 412fc0f2
    3f60: 00000000 c06d3f8c c06d3f80 c06d3f80 c00261e4 c000ef24 a00f0013 ffffffff
    r6:ffffffff r5:a00f0013 r4:c000ef24 r3:c00261e4
    [<c000eeec>] (arch_cpu_idle) from [<c006e1f8>] (cpu_startup_entry+0xbc/0x124)
    [<c006e13c>] (cpu_startup_entry) from [<c04c2450>] (rest_init+0x78/0x90)
    [<c04c23d8>] (rest_init) from [<c068db4c>] (start_kernel+0x310/0x36c)
    r4:c06da600 r3:60000053
    [<c068d83c>] (start_kernel) from [<80008074>] (0x80008074)
    Code: e5902004 e59f3090 e5921014 e59f208c (e7921101)
    ---[ end trace 86e6a61e795e1862 ]---
    Kernel panic - not syncing: Fatal exception in interrupt
    CPU1: stopping
    CPU: 1 PID: 0 Comm: swapper/1 Tainted: G D W O 3.14.63 #2
    Backtrace:
    [<c001169c>] (dump_backtrace) from [<c0011838>] (show_stack+0x18/0x1c)
    r6:00000000 r5:200f0193 r4:00000000 r3:00200040
    [<c0011820>] (show_stack) from [<c04c664c>] (dump_stack+0x78/0x98)
    [<c04c65d4>] (dump_stack) from [<c0013130>] (handle_IPI+0xc4/0x150)
    r5:00000005 r4:00000001
    [<c001306c>] (handle_IPI) from [<c0008520>] (gic_handle_irq+0x60/0x68)
    r7:ea141fac r6:c06da978 r5:ea141f78 r4:fa212000
    [<c00084c0>] (gic_handle_irq) from [<c04cb740>] (__irq_svc+0x40/0x70)
    Exception stack(0xea141f78 to 0xea141fc0)
    1f60: ffffffed 00000000
    1f80: 2a09a000 c0026630 ea140000 00000015 10c0387d c0726c40 8000406a 412fc0f2
    1fa0: 00000000 ea141fcc ea141fc0 ea141fc0 c00261e4 c000ef24 a00f0013 ffffffff
    r6:ffffffff r5:a00f0013 r4:c000ef24 r3:c00261e4
    [<c000eeec>] (arch_cpu_idle) from [<c006e1f8>] (cpu_startup_entry+0xbc/0x124)
    [<c006e13c>] (cpu_startup_entry) from [<c0012e08>] (secondary_start_kernel+0x11c/0x138)
    [<c0012cec>] (secondary_start_kernel) from [<800085c4>] (0x800085c4)
    r4:aa12806a r3:c00085ac
  • Hi Shawn,

    Can you please dump the i2c registers when issue occurs.

    Thanks,
    Stan
  • Hi Stan,

    Suddently, i can't duplicate the crash, so i will update to you if the system crash again.
    Besides, i get another error during i2c master read. I try to read 1024 bytes from another master device(J6). The system log shows "controller timed out", after code trace, i think is because return value of wait_for_completion_timout() is 0, so i2c controller start reset & init again.
    Could you tell me what this function doing? and what reason could possible cause it to return 0?

    P.S. I also try to read 128 bytes, it works, no crash happend.

    BR,
    Shawn
  • Hello,

    Is there anyone can help me to figure out which reaon might cause this error?
    =>read 256 bytes is fine, but i2c controller will timeout if read 512 bytes or 1024 bytes.
  • Could any one provide some suggestion about =>
    what this function(wait_for_completion_timout()) doing? and what reason could possible cause it to return 0?

    BR,
    Shawn
  • Hi Stan,

    We need to verify I2C master and slave function of TI J6. Does TI J6 linux BSP just support I2C master driver?
    We need to modify I2C driver to support I2C slave function of TI J6, right?
    Thanks for your support.

    BR,
    Shawn
  • Hi Shawn,

    I have forwarded the question to an I2C expert.
    Meanwhile can you say which version of SDK/linux kernel you use?

    Regards,
    Yordan
  • shawn lin said:
    Does TI J6 linux BSP just support I2C master driver?
    We need to modify I2C driver to support I2C slave function of TI J6, right?

    Yes, Jacinto6 SDK support I2C driver in master mode only, see linux-kernel/drivers/i2c/busses/i2c-omap.c

    For slave mode, you need to configure I2C_CON[10] MST = 0

    In I2C driver these are:

    #define OMAP_I2C_CON_MST    (1 << 10)    /* Master/slave mode */

    This bit is set to 1 (master mode) in omap_i2c_xfer_msg()

    w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;

    omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, w);

    Regards,
    Pavel

  • Note that no slave mode support in the driver, this is because there was no framework support in Linux kernel for i2c to be in slave mode, so far. In kernel > =4.1, i2c slave support has been added to the framework. But the omap driver is still missing this support.

    So beside I2C driver update (adding I2C slave mode), you might also need to backport framework changes to support i2c slave.

    After adding this support two J6 / J6Eco /mix can be connected over i2c one acting as an i2c master and another as slave.

    See also if the below e2e threads will be in help:

    e2e.ti.com/.../399132
    e2e.ti.com/.../256743

    Regards,
    Pavel
  • Hi Pavel,

    Thank for your reply, i will try to configue I2C slave later.
    Before that, i already modify i2c-omap.c file to let two master(Master-A & B) can transmit data. But there is a question:
    If Master-A try to send data to Master-B. Then, Master-B need to wake up first (use command "i2cget -y 3 0x33" to read data from non-existence device(0x33)) before Master-A sending data to it. Without waking it up, I2C-B can't get AAS IRQ.
    Do you have any idea about this scenario?

    Regards,
    Shawn
  • Shawn,

    Multi-master is not supported in the I2C driver, so you should implement it. Refer to the TRM for details.

    See also if the below e2e threads will be in help:

    e2e.ti.com/.../266300
    e2e.ti.com/.../326882

    Regards,
    Pavel
  • Hi Yordan,

    Thanks for your reply.
    The version of SDK/linux kernel I use is 3.13.0-39 -generic.

    Regards,
    Shawn
  • Hi Pavel,


    2 questions


    1.So you mean, it's because the multi-master function is not supported in driver now, that's why i need to use command "i2cget -y 3 0x33" to let master-B wake up to receive data?


    2.as you mention before, i should modify MST = 0 , enable AAS & RRDY & XRDY interrupt, and add some action after receive interrput for I2C slave modification, right?


    Regards,
    Shawn
  • shawn lin said:
    1.So you mean, it's because the multi-master function is not supported in driver now, that's why i need to use command "i2cget -y 3 0x33" to let master-B wake up to receive data?

    No, I do not. Where exactly you found this statement in my posts?

    shawn lin said:
    2.as you mention before, i should modify MST = 0 , enable AAS & RRDY & XRDY interrupt, and add some action after receive interrput for I2C slave modification, right?

    Yes, MST should be 0.

    See Figure 24-27. HS I2C Slave Transmitter/Receiver Mode, Interrupt regarding interrupt configuration in slave mode and also 24.1.5.1.1.1.2 Initialize the I2C Controller

    Regards,
    Pavel

  • Hi Pavel,

    Thanks for your information. I want to download i2c_omap_slave.tar.gz. but don't find it .the interlinkage is disable .please reuploading it .I need it . Thanks for your support.

    Regards,
    Shawn
  • Shawn,

    shawn lin said:
    I want to download i2c_omap_slave.tar.gz. but don't find it

    Please provide more details about this file. Is this file somehow related with TI SDK?

    shawn lin said:
    the interlinkage is disable .please reuploading it .I need it .

    You want from me to re-upload this file, but could you please specify where exactly I uploaded this file?

    Regards,
    Pavel

  • Hi Pavel,

    Thanks for your reply.
    I followed your information to look at the below e2e thread and found the related information below.

    e2e.ti.com/.../256743

    ''
    Hi Walter,

    The AM335x PSP is using the i2c-omap.c kernel driver. Unfortunately it doesn't seem like it has slave mode functionality. Take a look at this thread, where Sebastian Geissler has added slave functionality in the driver, but it is for kernel version 2.6. You can find the source code inside his TI profile, section Files.

    Best regards,
    Miroslav
    ''

    Regards,
    Shawn
  • Shawn,

    This file is not mine and I do not have it, thus unfortunately I can not re-upload it.

    Regards,
    Pavel
  • Hi Pavel,

    Can you tell me how to disable I2C auto suspend function?
    Each time i let i2c to read data from non-exist device(use command "i2cget -y 4 0x33"), will get read error message, and system will re-init i2c.
    Based on debug message, i saw system will first call "omap_i2c_runtime_resume" to wake up i2c interface and after a while, call "omap_i2c_runtime_suspend" to suspend it .
    two questions
    1.Is this scheme used for power saving?
    2.What should i do to disable this auto suspend function?

    Regards,
    Shawn
  • Shawn,

    You can try to disable runtime suspend through menuconfig:

    Power management options ---> - - Run-time PM core functionality

    See also the below e2e threads:

    e2e.ti.com/.../364423
    e2e.ti.com/.../1520091

    Regards,
    Pavel
  • Hello Shawn,
    On J6 though the HW supports i2c slave mode and multi master mode the SW does not support it.
    In recent kernels the i2c slave support has been added to i2c framework but omap driver did not have the support.

    Can you tell me the use case? why do you need to transfer information over i2c form one device to another?
    Why not UART?

    We recommend you to use UART interface as teh support already exists and should be pretty easy to set up and maintain.
    It would save you time and effort to use already developed SW, instead of going through development and multiple test cycles to ensure you test all corner cases.

    There were efforts made by TIers earlier to add i2c slave support in mainline kernel but was turned down due to test gaps. You may find teh discussion on mailing lists
    www.spinics.net/.../msg129253.html
    patchwork.kernel.org/.../

    If you search for i2c slave support on e2e youll come across the threads where it's discussed in detail.

    Regards,
    RK
  • Hi Pavel,

    The Run-time PM core functionality can't be disabled. Currently setting just like this =>

    Do i have other way to disable it? or can i disable it only on I2C interface? Afterall, what i really concern is the PM effect to I2C.

    Regards,

    Shawn

  • Hi Ravikumar,

    We need I2C transfer to verify J6 I2C interface. It is a test requirement. I know there exist I2C self loop test, but transfer test is our requirement.
    Thanks the info you provide, i'll check it.
    I already modify the driver(i2c-omap.c and i2c-dev.c) to let two J6 I2C can tranfer data to each other. But without doing this step(let i2c-slave one to read data from non-exist device), the slave can't get interrupt(AAS) while master sending data to it. Based on debug message, i think may be the power management cause this scenario, that's why i search the way to dsable runtime suspend.

    Regards,
    Shawn
  • shawn lin said:
    The Run-time PM core functionality can't be disabled.

    shawn lin said:
    Do i have other way to disable it?

    Seems that CONFIG_PM_RUNTIME depends on other kernel settings and can not be removed easily.

    shawn lin said:
    or can i disable it only on I2C interface?

    Yes, I will suggest to try this approach first. Disable runtime suspend/resume only in I2C driver (i2c-omap.c)

    Regards,
    Pavel

  • Hi Pavel,

    It's works.
    First, i try to mark the "pm_runtime_enable()" at omap_i2c_probe() to disable suspend/resume, but fail. System can't boot up successfully.
    So i try to use "pm_runtime_get()" to active I2C controller, it works. I2C can receive interrupt without doing this step(let i2c-slave one to read data from non-exist device).
    Thanks for your support.

    Regards,
    Shawn