I2C Slave Mode Receive in Burst Mode

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hallo together,

with the very good, qualified and nice support of this forum I have a stable configuration for my XMC1100. Thank you very much.

So one thing is not really working so far. I use the I2C module as Slave. There I want to receive multiple bytes with one transfer. For inspiration I used the I2C003_Example1_XMC11 provided by Infineon. With the master (which is actually a Cortex-M3 microcontroller) I try to read multiple bytes from the XMC in one transfer, but it is not working.

I have to do the following (code in master):


for (unsigned int i = 0; i < length; i++)
{
i2c_read(XMC_address, &c, 1)
}


This results in a single byte read repeated "length"-times. It seems to me, that I cannot use the BURST_RECEIVE mode specified in the I2C protocol. I hope that I am wrong. But I didnt' found an interrupt that sounds like a repeated read request. I used the same settings as in the example design.
In the protocol specific interrupt settings I didn't find an interrupt which sounds to me like the feature I'm looking for.

Sebastian
0 Likes
6 Replies
chismo
Employee
Employee
First like received
Hi Sebastian,

The USIC I2C slave supports transmission of multiple bytes (master read) with one transfer.

The following figure shows the expected interrupts during a master read sequence:
1444.attach

The slave read request (SRR) interrupt can be used to trigger the write of slave transmit data into IN or TBUF, depending on the buffer used.
If TxFIFO is used and is fitting for the number of bytes to be transmitted, all the data can be written at once with the SRR interrupt service routine.
If standard buffer TBUF is used, additional transmit buffer interrupts (TBIF) would be needed to transmit the subsequent bytes.

Hope this helps...

Regards,
Min Wei
0 Likes
Not applicable
Hi Min Wei,

I wish to know in which reference can I find the figure that you have posted.

Best,
0 Likes
chismo
Employee
Employee
First like received
Hello,

This figure is taken from the USIC I2C section on data flow handling in the product reference manual. For XMC1100 RM v1.2, it is located on page 409 of the pdf file, figure 14-57.

Regards,
Min Wei
0 Likes
Not applicable
Hi Min Wei,

thank you very much. In fact, that helped a lot. At the moment I'm programming the feature that with an Buffer Interrupt, the Transmit Buffer FIFO is automatically filled with the remaining bytes. I think I will be ready in the course of next week. Then I will describe what I did in this forum to help other developers.

Have a nice weekend!
Sebastian
0 Likes
Not applicable
Hi all,

as promised I provide a small explanation how I made the I2C in Slave Mode ready for an Interrupt-driven transmission.

My configuration (Dave APP I2C003) is:


  • Transmit FIFO Buffer: Size 32
  • Transmit FIFO Buffer: Trigger Limit: 16
  • I2C Protocol Specific Interrupt Configurations: Enable slave read requested interrupt


For the Interrupt-driven I2C-Transmission I need two interrupts:

  • I2C_Read_Request (for the initial Read Request the Master)
  • I2C_TxD_Buffer (to refill the transmit buffer in case more than 32 Bytes are requested by the master)


Here is the list with my interrupts (three in total, one for receive and two for the send)

1451.attach

Last we need the two functions for the two interrupts:

The following code is for the initial read request: First I flush the TxD-FIFO because I made the specification that a read request by the master must read all bytes of one specific command. I know the length of each of my specific answers. Then I write as many bytes as possible into the TxD FIFO.
If the FIFO is full, I save in my struct I2COutCmd (which holds a pointer to my data, the whole size and the bytes transmitted so far) the bytes transmitted. The FIFO is full, if the function I2C_WriteData returns false.


void slave_Read_Req_handler(void)
{
uint32_t cnt = 0;

USIC_FlushTxFIFO(I2C003_Handle0.I2CRegs);

while (cnt <= I2COutCmd.size)
{
SlaveTxData.Payload = I2COutCmd.data[cnt++];
SlaveTxData.TDF_Type = I2C003_TDF_STXDATA;
if (!I2C003_WriteData(&I2C003_Handle0,&SlaveTxData))
{
cnt--;
break;
}
}
I2COutCmd.sent = cnt;
}


Second I get an interrupt if the FIFO falls below the 16 bytes. Of course you can configure the number of bytes as you want. Then I do exactly the same thing as in the first interrupt routine. I fill the FIFO with the rest of the bytes.


void slave_TxD_Buffer_handler(void)
{
if (I2COutCmd.sent != I2COutCmd.size)
{
while (I2COutCmd.sent <= I2COutCmd.size)
{
SlaveTxData.Payload = I2COutCmd.data[I2COutCmd.sent++];
SlaveTxData.TDF_Type = I2C003_TDF_STXDATA;
if (!I2C003_WriteData(&I2C003_Handle0,&SlaveTxData))
{
I2COutCmd.sent--;
break;
}
}
}
}


In fact, that's the whole work. Just one last tipp to the buffer interrupt: You can get an interrupt if the FIFO falls below the configured bytes (in my case 16) or you can get an interrupt if the FIFO reaches the 16 bytes according to the register TBCTR:

1452.attach

There you can find the bit LOF:

1453.attach

This bit is initially Zero, exactly what I needed. I didn't find a function to configure this bit, but with CMSIS it is not a problem. You can just do the following wiht the help of the XMCxxx.h files:


void custom_init()
{
USIC_CH_TypeDef* I2CRegs;
I2CRegs->TBCTR |= (1 << LOF);
}


I hope I can help anyone to save some time. 🙂
Sebastian
0 Likes
chismo
Employee
Employee
First like received
Hello Sebastian,

Thanks for sharing your code. I am sure this will be a very useful reference for other users.

Cheers,
Min Wei
0 Likes