Post Go back to editing

I2C error while AD2428 initializing at sub node

Thread Summary

The user is experiencing EREMOTEIO (error 121) during I2C writes to subnode 0x69 while initializing the AD2428 using I2C on Linux. The A2B_INT_TYPE values are not as expected, and the vendor ID read from register 0x02 is incorrect. The issue is resolved by checking the I2C lines with a logic analyzer, which revealed that the lines break when driving 6MHz BCLK and LRCK for PLL lock. Adding an I2C protection circuit is suggested as a potential solution.
AI Generated Content
Category: Software
Product Number: AD2428
Software Version: SigmaStudio+ 2.3.0 (Update 4) with A2B 1.3.2
Hello.
 
I'm working on initializing ad2428 using I2C on Linux.
I2C commands list(.h, .xml) is made (export) from with Sigma Studio+ 2.3.
 
The issue is error 121 occurred (EREMOTEIO, Remote I/O error) while i2c write at subnode (0x69).
The weird part is that when reading the subnode vendor (register=0x02), the values are 0x0d 0x28 instead of 0xad 0x28.
 
And I'm not sure why the A2B_INT_TYPE value is not equal as expected.
 
Thank you.
Eunsang Ko
LocoField
 
 
Below is i2c logs:
 
[  0 ] i2c_write [ 68 12 ]: 04 A2B_CONTROL_RESET
[  0 ] a2b_delay [    19 ]
[  0 ] i2c_read  [ 68 17 ]: 00 A2B_INT_TYPE not equal. expected: 19
[  0 ] i2c_read  [ 68 02 ]: AD 28 00 A2B_ID_VENDOR
[  0 ] i2c_write [ 68 12 ]: 84 A2B_CONTROL_RESET
[  0 ] a2b_delay [    19 ]
[  0 ] i2c_read  [ 68 17 ]: 00 A2B_INT_TYPE not equal. expected: 19
[  0 ] a2b_delay [    19 ]
[  0 ] i2c_read  [ 68 17 ]: FF A2B_INT_TYPE not equal. expected: 19
[  0 ] i2c_read  [ 68 02 ]: AD 28 00 A2B_ID_VENDOR
[  0 ] i2c_write [ 68 1B ]: FF FF 0F A2B_INT_MSK0
[  0 ] i2c_write [ 68 96 ]: 02
[  0 ] i2c_write [ 68 1A ]: 01 A2B_INT_PND2
[  0 ] i2c_write [ 68 0F ]: 83 A2B_CONTROL_RESPCYCS
[  0 ] i2c_write [ 68 12 ]: 81 A2B_CONTROL_RESET
[  0 ] a2b_delay [    01 ]
[  0 ] i2c_read  [ 68 17 ]: FF A2B_INT_TYPE not equal. expected: 01
[  0 ] i2c_write [ 68 41 ]: 81 A2B_I2S_GCFG
[  0 ] i2c_write [ 68 09 ]: 01 A2B_CONTROL_SWCTL
[  0 ] i2c_write [ 68 13 ]: 83 A2B_CONTROL_DISCVRY
[  0 ] a2b_delay [    64 ]
[  0 ] i2c_read  [ 68 17 ]: 0D A2B_INT_TYPE not equal. expected: 64
[  0 ] a2b_delay [    32 ]
[  0 ] i2c_read  [ 68 17 ]: 0D A2B_INT_TYPE not equal. expected: 32
[  0 ] i2c_write [ 68 09 ]: 21 A2B_CONTROL_SWCTL
[  0 ] i2c_write [ 68 01 ]: 00 A2B_CONTROL_NODEADR
[ -121 ] i2c_read  [ 69 02 ]: 0D 28 00 00 A2B_ID_VENDOR not equal. expected: AD 28 00 01
[ -121 ] i2c_write [ 69 0B ]: 80 A2B_SLOT_LDNSLOTS
[ -121 ] i2c_write [ 69 46 ]: 00 A2B_I2S_SYNCOFFSET
[ -121 ] i2c_write [ 69 41 ]: 81 A2B_I2S_GCFG
[ -121 ] i2c_write [ 69 42 ]: 89 A2B_I2S_CFG
[ -121 ] i2c_write [ 69 4A ]: C0 A2B_IO_GPIODAT
[ -121 ] i2c_write [ 69 4D ]: C0 A2B_IO_GPIOOEN
[ -121 ] i2c_write [ 69 4E ]: 30 A2B_IO_GPIOIEN
[ -121 ] i2c_write [ 69 5A ]: 80 A2B_IO_CLK2CFG
[ -121 ] i2c_write [ 69 65 ]: 01 A2B_SLOT_DNMASK0
[ -121 ] i2c_write [ 69 96 ]: 02
[ -121 ] i2c_write [ 69 5C ]: 20
[ -121 ] i2c_write [ 69 1B ]: EF FF A2B_INT_MSK0
[  0 ] i2c_write [ 68 01 ]: 00 A2B_CONTROL_NODEADR
[ -121 ] i2c_write [ 69 00 ]: 6A A2B_I2C_CHIP
[  0 ] i2c_write [ 68 01 ]: 20 A2B_CONTROL_NODEADR
...
[  0 ] i2c_write [ 68 09 ]: 01 A2B_CONTROL_SWCTL
[  0 ] i2c_write [ 68 0D ]: 01 A2B_CONTROL_DNSLOTS
[  0 ] i2c_write [ 68 41 ]: 81 A2B_I2S_GCFG
[  0 ] i2c_write [ 68 42 ]: 98 A2B_I2S_CFG
[  0 ] i2c_write [ 68 1B ]: FF FF 0F A2B_INT_MSK0
[  0 ] i2c_write [ 68 01 ]: 00 A2B_CONTROL_NODEADR
[  0 ] i2c_write [ 68 01 ]: 80 A2B_CONTROL_NODEADR
[ -121 ] i2c_write [ 69 40 ]: 00 A2B_I2S_PLLCTL
[  0 ] i2c_write [ 68 01 ]: 00 A2B_CONTROL_NODEADR
[ -121 ] i2c_write [ 68 10 ]: 66 A2B_CONTROL_SLOTFMT
[ -121 ] i2c_write [ 68 11 ]: 02 A2B_CONTROL_DATCTL
[ -121 ] i2c_write [ 68 12 ]: 81 A2B_CONTROL_RESET
[  0 ] a2b_delay [    01 ]
[  0 ] i2c_read  [ 68 17 ]: 19 A2B_INT_TYPE not equal. expected: 01
[  0 ] i2c_write [ 68 01 ]: 00 A2B_CONTROL_NODEADR
[ -121 ] i2c_write [ 69 09 ]: 00 A2B_CONTROL_SWCTL
[  0 ] i2c_write [ 68 12 ]: 82 A2B_CONTROL_RESET
 
 
while my i2c functions:
 
int adi_a2b_NetworkSetup(int fd)
{
    ADI_A2B_DISCOVERY_CONFIG *pOPUnit;
    int status = 0;
    static unsigned char aDataBuffer[6000];
    static unsigned char aDataWriteReadBuf[4u];
 
    for (int i = 0i < CONFIG_LENi++)
    {
        pOPUnit = &gaA2BConfig[i];
 
        switch (pOPUnit->eOpCode)
        {
        case WRITE:
        {
            concatAddrData(&aDataBuffer[0u], pOPUnit->nAddrWidthpOPUnit->nAddr0u);
            auto command_name = getCommandName(pOPUnit->nAddr);
            (void)memcpy(&aDataBuffer[pOPUnit->nAddrWidth], pOPUnit->paConfigDatapOPUnit->nDataCount);
 
            status = i2c_write(fdpOPUnit->nDeviceAddrpOPUnit->nAddrWidth + pOPUnit->nDataCount&aDataBuffer[0u]);
 
            printf("[ %2d ] i2c_write [ %02X %02X ]: "statuspOPUnit->nDeviceAddraDataBuffer[0]);
            for (int j = 0j < pOPUnit->nDataCountj++)
            {
                printf("%02X "pOPUnit->paConfigData[j]);
            }
            printf("%s"command_name.c_str());
            printf("\n");
            break;
        }
        case READ:
        {
            (void)memset(&aDataBuffer[0u], 0upOPUnit->nDataCount);
            concatAddrData(&aDataBuffer[0u], pOPUnit->nAddrWidthpOPUnit->nAddr0u);
            auto command_name = getCommandName(pOPUnit->nAddr);
 
            status = i2c_read(fdpOPUnit->nDeviceAddrpOPUnit->nAddrWidth&aDataBuffer[0u], pOPUnit->nDataCount&aDataWriteReadBuf[0u]);
 
            printf("[ %2d ] i2c_read  [ %02X %02X ]: "statuspOPUnit->nDeviceAddraDataBuffer[0]);
            for (int j = 0j < pOPUnit->nDataCountj++)
            {
                printf("%02X "aDataWriteReadBuf[j]);
            }
 
            printf("%s "command_name.c_str());
 
            if (memcmp(aDataWriteReadBufpOPUnit->paConfigDatapOPUnit->nDataCount!= 0)
            {
                printf("not equal. expected: ");
                for (int j = 0j < pOPUnit->nDataCountj++)
                {
                    printf("%02X "pOPUnit->paConfigData[j]);
                }
            }
 
            printf("\n");
            break;
        }
        case DELAY:
        {
            int nDelayVal = 0;
            for (int j = 0j < pOPUnit->nDataCountj++)
            {
                nDelayVal = pOPUnit->paConfigData[j| nDelayVal << 8u;
            }
 
            printf("[  0 ] a2b_delay [    %02X ]\n"nDelayVal);
            usleep(nDelayVal * 100);
            break;
        }
        default:
            break;
        }
    }
 
    return status;
}
  • one quick check is to look at the actual i2c signal in hardware and see if the data is ok. I'm wondering if you're host computer is not handling i2c clock stretching correctly.

  • ahhhhhh.... I checked the I2C lines using Logic.

    But, the i2c lines are broken when driving 6MHz bclk and lrck for pll lock.

    What can I do to solve this problem? Including adding an i2c protection circuit.

  • >  when driving 6MHz bclk and lrck for pll lock

    I'm not quite following what the difference in signals you have applied to the main node is between the top plot and the second one.

    I didn't try and decode what INT_TYPE is telling you but I suspect that will explain or at least point to what has gone wrong.

    What I like to do is hook my hardware up to SS and record the physical I2C line on the main node, and then compare that to what my software is attempting to do.  There's of course a lot of ways to do things but the key point is to see what's going on when it works and then find the difference.

    You don't mention the hardware being used but dropping back to known hardware can also be helpful to establish a known baseline for comparing against.

    Good luck!

  • Thank you

    This appears to be a reset timing issue in my software, e.g. a2b delay.
    REG_A2B0_INTSRC(0x16) value should be 0x80. but no interrupt on main node after reset.
    Once it works normal when I use SS+.

    However, the command list from SS+ export seemed to have some issues.
    So I wrote it myself.

    DI_A2B_DISCOVERY_CONFIG gaA2BConfig[] =
    {

        /*-- COMMANDS FOR DEVICE - AD242xMain_0 --*/
        {0x68u, WRITE,  0x00u,  0x00000000u,    0x01u,  0x00000012u,    0x01u,  0x0001u,    &reset[0],  I2C},
        {0x00u, DELAY,  0x00u,  0x00000000u,    0x01u,  0x00000000u,    0x01u,  0x0001u,    &reset_delay[0],    I2C},
        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000002u,    0x01u,  0x0003u,    &master_vendor[0],  I2C},
        {0x68u, WRITE,  0x00u,  0x00000000u,    0x01u,  0x00000012u,    0x01u,  0x0001u,    &master_reset[0],   I2C},
        {0x00u, DELAY,  0x00u,  0x00000000u,    0x01u,  0x00000000u,    0x01u,  0x0001u,    &master_reset_delay[0], I2C},

        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000016u,    0x01u,  0x0001u,    &interrupt_source1[0],  I2C},
        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000017u,    0x01u,  0x0001u,    &interrupt_type[0], I2C},
        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000016u,    0x01u,  0x0001u,    &interrupt_source2[0],  I2C},

    };
  • Thank you

    This appears to be a reset timing issue in my software, e.g. a2b delay.
    REG_A2B0_INTSRC(0x16) value should be 0x80. but no interrupt on main node after reset.
    Once it works normal when I use SS+.

    However, the command list from SS+ export seemed to have some issues.
    So I wrote it myself.

    DI_A2B_DISCOVERY_CONFIG gaA2BConfig[] =
    {

        /*-- COMMANDS FOR DEVICE - AD242xMain_0 --*/
        {0x68u, WRITE,  0x00u,  0x00000000u,    0x01u,  0x00000012u,    0x01u,  0x0001u,    &reset[0],  I2C},
        {0x00u, DELAY,  0x00u,  0x00000000u,    0x01u,  0x00000000u,    0x01u,  0x0001u,    &reset_delay[0],    I2C},
        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000002u,    0x01u,  0x0003u,    &master_vendor[0],  I2C},
        {0x68u, WRITE,  0x00u,  0x00000000u,    0x01u,  0x00000012u,    0x01u,  0x0001u,    &master_reset[0],   I2C},
        {0x00u, DELAY,  0x00u,  0x00000000u,    0x01u,  0x00000000u,    0x01u,  0x0001u,    &master_reset_delay[0], I2C},

        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000016u,    0x01u,  0x0001u,    &interrupt_source1[0],  I2C},
        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000017u,    0x01u,  0x0001u,    &interrupt_type[0], I2C},
        {0x68u, READ,   0x00u,  0x00000000u,    0x01u,  0x00000016u,    0x01u,  0x0001u,    &interrupt_source2[0],  I2C},

    };