I²C Driver for TC3xx devices including DMA and Services

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

cross mob
Markus4711
Level 3
Level 3
First like received 10 questions asked 10 sign-ins
Dear all,

I implemented a driver for a I²C device to connect it to a TC375 (I simply assume it will be the same for all TC3xx maybe even TC2xx).
There is an example available (https://www.infineon.com/dgdl/Infineon-AURIX_I2C_Read_Ext_Device_1-Training-v01_00-EN.pdf) that contains a very simple way of communicating (aka reading certain internal register content) with a I²C device.
The example is running in interrupt flag polling mode (like a few other examples do) and is splitting the communication in a master write and master read cycle. Beside that I really don't like the idea to poll on interrupt flags, especially if you are dealing
with an external device that is minimum 3000times slower as the TC3xx, I could hardly believe that this example will work for the majority of I²C devices because it doesn't implement the restart condition between the two mentioned cycles. As as I can remember I always had
the need to use the restart feature of the I²C protocol, to communicate with an external device in a way of reading information from that external device. So I came to the conclusion that the example is not working for me and I guess for most serious application it is not working either.

So I start more less from scratch based on the iLLD library. Finding myself after 3 days of work in the situation that everything is working as expected. My implementation mirrors partly the I²C state machine of the TC3xx realised inside a I²C service routine. Within this state machine the DMA based transfers are configured and
started.
Therefore I ask myself if I over complicated my implementation or if this is the way it is meant to be. I know other µC that can be configured to switch from write->read after a defined number of transferred bytes and therefore release the amount of 'supervising and monitoring'
the I²C interface while it is actively used. Another point the complicates everything is that I could only find a way to configure one DMA channel for the I²C. Other µC I'm using are able to setup one for transmit and one for receive. So both can be configured before the communication
starts. In my implementation I had to reconfigure them after the master write part has been finished to become a read channel. This works because of my low CPU load in my current application. However, I consider this as something 'dangerous' if CPU load is raising and the
I²C communication is not considered to be one of the most important parts of a application.

So if there is someone who can point me to a more simple solution I will be glad to hear about.

Best Regards
Markus
0 Likes
3 Replies
MoD
Employee
Employee
50 likes received 500 replies posted 100 solutions authored
The FIFO of the I2C module can be used only in transmit or receive mode only. There is only 1 FIFO for both. Therefore you don't have different interrupts for receive and transmit.
You can use the DMA Linked List feature (see DMA description), in your case. You use 1 DMA channel with the set for transmit which will load the receive set when finished. Such a linked list can also contain other sets (e.g. clear of transfer request flags).
0 Likes
Markus4711
Level 3
Level 3
First like received 10 questions asked 10 sign-ins
MoD wrote:
The FIFO of the I2C module can be used only in transmit or receive mode only. There is only 1 FIFO for both. Therefore you don't have different interrupts for receive and transmit.
You can use the DMA Linked List feature (see DMA description), in your case. You use 1 DMA channel with the set for transmit which will load the receive set when finished. Such a linked list can also contain other sets (e.g. clear of transfer request flags).


Hi MoD,

thanks for the hint. Certainly I use only one service (I²C protocol service). Inside the service routine I switch between the different states (master write, restart, master read, master stop) and set the different protocol flags (in the endctrl and runctrl register).
So I have to track at which state the transmission sequence currently is to perform the right actions. I realised this by using a static variable that is representing the current state and is used as condition in a switch statement inside the service routine.

I haven't thought about using a DMA linked list. I tried this earlier this year on an other µC. At least on this µC I found out that DMA linked lists are not working because of the discrepancies between the I²C and DMA speed. The reason for this is that e.g. a DMA transmit is finished, as far
as the DMA module concerns, at the point in time the last information is written in the transmit register (TXD). I assume that the TC3xx DMA controller will start a successive linked DMA transfer right after that event. However, the I²C will take a lot more time to finish the transmit
(even on a byte transmit it will be 10.000s of CPU cycles).
So if the linked list transfer is setting a restart/stop/ACK/nACK condition in the I²C module (that is necessary to follow the I²C specification) while a transmit is performed, the whole transfer will be messed up. It will only work if the linked list transfer can be controlled by the previous transfer and a 'flag'.
I haven't checked the user manual if such a 'logic conditional' link is possible - I actually doubt that such a functionality exist. Maybe raising I²C interrupts and enabling the elements of a linked list transfer will improve the overall handing effort a little bit. Again, I doubt if such a 'stepwise enabling' of linked
list elements is possible.
Do you have experience in using linked list DMA and I²C?

Best Regards
Markus
0 Likes
MoD
Employee
Employee
50 likes received 500 replies posted 100 solutions authored
This what you described is the DMA Daisy Chain Mode.
In case of Linked List there will be only load a complete new set (addresses and soon) for the DMA channel after first set is finished. With link list, the transaction request must come from the HW, in your case the I2C module.
Therefore I don't see any problem. Please note that the DMA is used only for write to TXD and read from RXD. The states of the I2C are going via protocol interrupt (TX_END, RX and soon).
Unfortunately I don't have deep experience with link list DMA.
0 Likes