TC3XX: I2C Slave not responding with ACK

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

cross mob
lgacnik97
Level 2
Level 2
10 replies posted 5 replies posted 5 sign-ins

I'm using TC397XE for this project where I'm trying to achieve basic Master-Slave communication between two I2C modules of TC397XE. I2C0 as Master and I2C1 as Slave.

I reached the point, where Master sends data, but doesn't receive respond from Slave (which should respond with Acknowledgement - SDA low during 9th SCL positive edge). I'm suspicious about Slave configuration settings, although cannot find the cause of problems. Here is Slave configuration code:

 

  /************************* I2C Module 1 => SLAVE *************************/
    
  /* Enable access for CLC */
  clearWdtEndinit();
  
  /* Clock enable for I2C1 module */
  I2C1_CLC.B.DISR = 0;              // Enable module
  while( I2C1_CLC.B.DISS == 1 );    // Wait while disabled
  I2C1_CLC1.B.RMC = 1;              // Clock division by 1
  while( I2C1_CLC1.B.RMC != 1 );    // Wait while disabled
  I2C1_CLC1.B.DISR = 0;             // Enable module
  while( I2C1_CLC1.B.DISS == 1 );   // Wait while disabled
  
  /* Configure protocol interrupts */
  I2C1_ERRIRQSM.U = 0;
  I2C1_PIRQSM.U = 0;
  I2C1_IMSC.U = 0;
  
  /* Disable I2C1 module */
  I2C1_RUNCTRL.B.RUN = 0;           // Configuration registers accessible
  
  /* Configure operation options */
  I2C1_ADDRCFG.U = 0;
  I2C1_ADDRCFG.B.ADR = I2C_config.slaveAddress;  // Address is given by this 
                                                 // struct
  I2C1_ADDRCFG.B.TBAM = I2C_config.addressMode;  // 7-Bit Address mode select
  I2C1_ADDRCFG.B.MnS = 0;                      // Module configured as master

  
  /* Configure FIFO settings */
  I2C1_FIFOCFG.U = 0;
  I2C1_FIFOCFG.B.RXFC = 1;     // RX FIFO as flow controller
  I2C1_FIFOCFG.B.TXFC = 1;     // TX FIFO as flow controller
  I2C1_FIFOCFG.B.RXFA = 0;     // RX FIFO Alignment - byte aligned 
  I2C1_FIFOCFG.B.TXFA = 0;     // TX FIFO Alignment - byte aligned
  I2C1_FIFOCFG.B.RXBS = 0;     // Burst size 1 word
  I2C1_FIFOCFG.B.TXBS = 0;     // Burst size 1 word
 
  clearWdtEndinit();
  
  /* Configure PORT settings for I2C_1 SDA/SCL pins*/
  P11_IOCR12.B.PC14 = 0x00;         // SCL input -> P11.14
  P11_IOCR12.B.PC13 = 0x00;         // SDA input -> P11.13
  I2C1_GPCTL.B.PISEL = 0x00;        // PORT-A selected
  
  setWdtEndinit();
  
  /* Enable I2C1 module */
  I2C1_RUNCTRL.B.RUN = 1;      // I2C1 Module enabled - configuration 
                               // registers not accessible

 

Before Master write sequence, both error and protocol interrupt sources are enabled. Then the packet size is writen to TPSCTRL register and the packet data is writen to TXD register. After that, Master waits until TX_END request is set by PIRQSS register. After that, write sequence ends.

Also during this sequence, after TXD register is being written to, following status is set:  I2C0_BUSSTAT.BS = 2 (busy master), I2C1_BUSSTAT.BS = 1 (bus busy). Also, after address being send, I2C1_BUSSTAT.BS = 1 (bus busy) but I2C1_BUSSTAT.RnW = 0 (device is transmitting - although it should equal to "1" as it Slave and is being addressed).

Is there anything that might have to be reconfigured otherwise or not configured here but should be? Should additional steps be taken at Slave side during Master write sequence?

 

0 Likes
1 Solution
lgacnik97
Level 2
Level 2
10 replies posted 5 replies posted 5 sign-ins

Hello,

we just solved this issue. The problem was not with operation of I2C (even though you gave some good insights on I2C operation), but with the I2C slave I/O IOCR register setting. Since slave needed to read address + data on I2C bus, I thought slave's SDA and SCL needed to be set as input but that is not true. That is because Slave's SDA needs to pull voltage LOW at 9th SCL cycle and that is not possible if SDA is set as input.

That is why I2C pins (on Tricore TC399XE) need to be set as I2C Alternate Output Function (this is done via AOF inspection in data sheet and then setting IOCR with right code value).

Kind regards!

View solution in original post

0 Likes
9 Replies
Nambi
Moderator
Moderator
Moderator
50 likes received 5 likes given 100 solutions authored

Hi,

1. Could you compare the value of the I2C Address sent on the bus and the value of ADR in I2C1_ADDRCFG?
2. For the 7-bit address mode, the address is based on bits 7:1 of I2C1_ADDRCFG and not bits 6:0. Could you check if this syntax is met?

Best Regards.

0 Likes

Hello!

Yes, address (or first byte being written to TXD) is same as the value being written (and read from - to verify write operation) to ADDRCFG register, ADR bit field of slave module. Also verified sent address with logic analyzer and it is really the one meant to be transmitted and the one that is stored in slave I2C module.

I'm aware of fact that LSB of address byte being used for RnW indication. Here is part of code which positions address on master side onto right spot:

uint8_t addr = I2C_txMSG.slaveAddress;  // address passed via struct member
  
addr = (addr << 1);     // bit_0 is R/W
addr = (addr & 0xFE);   // extract upper 7 bits of a byte
addr = (addr & ~0x01);  // clear LSB - write operation

If, let say, address 0x6C is send to slave, then in slave's ADDRCFG ADR bit field, 0x6C must be stored or should same procedure be executed as on master side before writing modified address to ADR bit field?

0 Likes
Nambi
Moderator
Moderator
Moderator
50 likes received 5 likes given 100 solutions authored

Hi,

1. For writing to Slave, If 0x6C is sent as the first byte on the bus, it is 01101100. The bit "0" is "0," indicating write. The 7-bit address is 0110110. Using 7-bit addressing mode ADR[9:0] = 01101100. Here ADR of ADDRCFG is 0x6C.

2. For reading from Slave, If 0x6D is sent as the first byte on the bus, it is 01101101. The bit "0" is "1," indicating read. The 7-bit address is 0110110. Using 7-bit addressing mode ADR[9:0] = 01101100. Here ADR of ADDRCFG is 0x6C.

3. Could you share the value of the complete ADDRCFG register for the I2C Slave and the waveform on the bus during the address phase?

4. Additional point. For the first byte of data 01101100(write) or 01101101(read), some analyzers may interpret the address as 01101100(0x6C), and some analyzers may interpret the address as 0110110(0x36 considering only the 7-bit address)

Best Regards.

0 Likes
lock attach
Attachments are accessible only for community members.

Regarding 4th paragraph, it can clearly be seen, that 0x6C decoded by LA, is the real address used to adress the slave.

At master side, address 0x6C is first shifted right by 1 (since LSB is RnW). Here, 0x6C is written directly to ADR of ADDRCFG. I also tried other option, where 7-bit address is also right shifted by 1 before stored to ADR of ADDRCFG but that didn't work either.

Kind Regards

0 Likes
Nambi
Moderator
Moderator
Moderator
50 likes received 5 likes given 100 solutions authored

Hi,

I assume that "SETEND_true.png" was captured during the configuration "Slave_after_address_config.png"
i)As per the waveform "SETEND_true.png", the first byte transmitted is "11011000". Here the 7 address bits are "1101100".
ii)As per the screenshot "Slave_after_address_config.png", the ADR value is "01101100". Here the 7 address bits are "0110110".

There is a mismatch here. Could you check after fixing this mismatch?

Best Regards.

0 Likes

Hello,

Waveform was captured during master send address sequence. Slave configuration was captured inside configuration state (while RUN = 0) as it cannot be configured on the run.

As for mismatch, I mentioned in earlier respond that I have already tried the following (shown in following address configuration caption). I have right shifted address on slave as I did on master. However,  slave still doesn't respond with Acknowledge (waveform remains the same).

Slave_after_address_config_2.png

Also, if you might be wondering, before master starts sending anything, interrupts are enabled globally and I2C error/protocol interrupt sources are cleared and enabled on slave and master's end. Master gets "NACK" and "TX_END" request, meanwhile slave get's no interrupt request (as if they weren't enabled at all, but are).

0 Likes

In addition, even if general call (7-bit address: 0x00) is put on I2C bus, slave still doesn't respond with Acknowledge but at slave's end, I2C module detects it is being accessed by master. This means there is some other issue than address content being compared at slave's end.

0 Likes

Here is another waveform capture (only that here ENDCTRL is "0", meaning stop condition is not set after NACK) - here it can be seen more clearly that there is no Acknowledge (after certain period, slave doesn't pull SDA to state LOW, meaning it doesn't respond with Acknowledgement). This is also the case of general call - slave's I2C detects that master is trying to send data to it (however GC request is not set).NACK.png

0 Likes
lgacnik97
Level 2
Level 2
10 replies posted 5 replies posted 5 sign-ins

Hello,

we just solved this issue. The problem was not with operation of I2C (even though you gave some good insights on I2C operation), but with the I2C slave I/O IOCR register setting. Since slave needed to read address + data on I2C bus, I thought slave's SDA and SCL needed to be set as input but that is not true. That is because Slave's SDA needs to pull voltage LOW at 9th SCL cycle and that is not possible if SDA is set as input.

That is why I2C pins (on Tricore TC399XE) need to be set as I2C Alternate Output Function (this is done via AOF inspection in data sheet and then setting IOCR with right code value).

Kind regards!

0 Likes