cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
woitha
Visitor
Visitor
2,649 Views
Registered: ‎04-22-2013

Zynq with AXI_IIC (I2C) as slave device with repeated start

Hello,

 

I am trying to implement an I2C-Slave (AXI IIC) in a Zynq device. Based on the “xiic_slave_example.c” I could receive some bytes with the iic-module. So far, so good.

 

Because I have to add the slave device to an existing design I have the following data structure:

 

Write  to Slave:

  • The master sends the slave address with bit 0 = 0 (write to slave)
  • The master sends one byte (which is a register address)
  • The master sends two more bytes (16-Bit register)

Read from Slave:

  • The master sends the slave address with bit 0 = 0 (write to slave)
  • The master sends one byte (which is a register address)
  • The master sends a repeated start and the slave address with bit 0 = 1 (read from slave)
  • The master reads two bytes (16-Bit register)

The “Write to Slave” sequence is just reading 3 bytes from the master. However after the first byte there may be a repeated start and I have to send bytes to the master.

 

Can anyone give me a hint how I can solve this with the IIC API functions?

 

0 Kudos
2 Replies
hpoetzl
Voyager
Voyager
2,631 Views
Registered: ‎06-24-2013

Hey @woitha

 

The “Write to Slave” sequence is just reading 3 bytes from the master.

However after the first byte there may be a repeated start and I have to send bytes to the master.

 

Actually you have to look at it the other way round:

  • There is a two byte sequence (slave address-write plus register address) to select a register
  • In the write case, there are two more bytes which get written to this register
  • In the read case, there are two bytes read from the register

So basically what you need to do is to buffer the register address after the first data byte and

  • return data from the selected register on read or
  • update the selected register when written to

Hope that clarifies,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
woitha
Visitor
Visitor
2,601 Views
Registered: ‎04-22-2013

Hello Herbert,

 

thank you for your reply. However I had no problems to understand what I have to do. The question was how to do it with the API.

 

With a lot of try and error, I have found a sequence that seems to work somehow. However if someone has a better solution, I am still interested in it.

 

 

I have added the following routine  to the “xiic_slave_example.c”:

 

//--------------------------------------------------------------------------
// Simplified example for reading/writing a register
//--------------------------------------------------------------------------

int ReadWriteReg(void)
{
  int Status;

  ReceiveComplete = TransmitComplete = 1;

  Status = XIic_Start(&IicInstance);
  if (Status != XST_SUCCESS) return XST_FAILURE;

  XIic_IntrGlobalEnable(IicInstance.BaseAddress);

 

  // Read 1 or 3 bytes from master
  // 1st byte is register-address
  // byte 2 and 3 are data in case of register write
  // in case of a register read, there is only one byte
  while (ReceiveComplete)
  {
    if (SlaveRead)
    {
      XIic_SlaveRecv(&IicInstance, ReadBuffer, 4); // Why does count = 3 not work?
      SlaveRead = 0;
    }
  }

 

  // Check if we have received only one byte (using RecvByteCount does not work)
  if (IicInstance.RecvBufferPtr == ReadBuffer+1)
  {
    // We return our register number and the inverted register number
    // regular we will return our register here
    WriteBuffer[0] = ReadBuffer[0]; 
    WriteBuffer[1] = ~ReadBuffer[0];

 

    while (TransmitComplete)
    {
      if (SlaveWrite)
      {
        XIic_SlaveSend(&IicInstance, WriteBuffer, 2);
        SlaveWrite = 0;
      }
    }
  }
  else
  {
    // we should write received data to our register here
  }

 

  while(XIic_IsIicBusy(&IicInstance));

  XIic_IntrGlobalDisable(IicInstance.BaseAddress);

  Status = XIic_Stop(&IicInstance);
  if (Status != XST_SUCCESS) return XST_FAILURE;

  return XST_SUCCESS;
}

 

I am calling this routine instead of the SlaveReadData/SlaveWriteData sequence in the original example.

 

 

0 Kudos