This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LP-MSPM0C1104: I2C Target Read failed

Part Number: LP-MSPM0C1104

Tool/software:

I implemented it according to the example "i2c_target_rw_multibyte_fifo_interrupts"
The master side communicates normally with the MCU through I2C
However, the master side will fail to read the MCU.
I added log to view the event status in interrupt and got the following results
DL_I2C_IIDX_TARGET_START

DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER

DL_I2C_IIDX_TARGET_START

DL_I2C_IIDX_TARGET_STOP

The event DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER cannot be entered.
I tried setting to enable TXFIFO_TRIGGER in syscfg
But the result is still the same
Is there anything else I need to set?

In addition, how do I know whether bit 0 of address is 1 or 0? (read or write)

  • Hello Keng,

    First make sure you have a strong pull up resistors (2.2k) on the SDA and SCL lines.  Next, you will need an oscilloscope or logic probe (Saleae for example) and monitor the I2C lines.  You can capture the first byte, which is the address byte and examine the addrs (bits 7..1) and the R/W bit 0.

    Let me know what you discover.

  • How do you tell that the master side failed? This trace seems to show that it succeeded.

    My observation about this example is that the TXFIFO trigger happens immediately at startup, since the FIFO is empty, and the program fills the Tx FIFO (16 bytes) then. Subsequent read requests are filled from the FIFO without the target seeing it directly, so your trace wouldn't show anything between the Start and the Stop.

    Another clue is that, after the Start, the target will stretch the clock if the TX FIFO is empty, so (assuming a required interrupt is somehow not happening) we wouldn't see a Stop in your trace.

    Incidentally: Did you change anything else in this example besides adding the trace?

  • Only get register, no address

  • Sorry, perhaps I didn't express myself clearly.

    My understanding of reading I2C communication is as follows: Start → Address → Reg → Start → Data... → Stop.

    Corresponding to the interrupt events, I think it should be:

    DL_I2C_IIDX_TARGET_START

    DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER

    DL_I2C_IIDX_TARGET_START

    DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER

    DL_I2C_IIDX_TARGET_STOP

    That's why I asked how to determine whether the bit 0 of the address is 0 or 1, because I need to know if it’s a read operation. If it is, I need to read the internal table and fill it into the Tx FIFO to return to the master.

    Or did I misunderstand something?

  • Hi Dennis,

    Sorry, you might have misunderstood my point. What I meant was how to determine in the program whether bit 0 of the address is 0 or 1, or if there is a function that tells me whether the current process is a write or read operation.

  • The TXFIFO interrupt is a request to fill it, not an indication that it is being drained. If the FIFO is non-empty, the Tx (master receive) byte will be sent  automatically.

    I didn't see anything in the I2C registers which indicates the direction (I may have missed it).   [Edit: I was looking right at it and didn't see it. I think SSR:TREQ and SSR:RREQ can tell you something. [Ref TRM Sec 13.2.3.7] ]

    One strategy might be to move the TXFIFO interrupt enablement to the START interrupt. 

    Another might be to not use the TXFIFO interrupt at all, rather accept the RXFIFO (non-empty) interrupt, generate the output, and store that in the TX FIFO then. You may need to use ACKOEN/ACKOVAL to flow-control the Rx for this [Ref TRM  (SLAU893A) Sec 13.2.3.4] You'll need SCLKSTRETCH=1 for this [Ref TRM Sec 13.2.3.7] 

    The TXWAIT_STALE_TXFIFO feature [Ref TRM Sec 13.2.3.12.1] may a use here.

  • Hi keng,

    Typically you don't need to decode the R/W bit.  This bit is decoded, along with the device addrs by the HW and based on the bit being a R or W, the MSP I2C peripheral logic will enter either the READ or WRITE state.  If the bit is W, then the host will be writing data to the MSP, which will come into the RXFIFO.  Here you would have your I2C ISR handler setup to handle the RXFIFO interrupt and remove the incoming data and put it in a buffer you created in your application. 

    Keep in mind that data that is passed back and forth between the host and the MSP have some type of agree protocol. For example, the protocol might look something like this: [CMD][LENGTH][DATA].  The MSP would recevie the packet and parse through looking at the CMD and from that know if the host will be requesting some data and can prepare TXFIFO to send data when the host sends the next packet with the R/W = READ.

    So I would take a look at some of the I2C DriverLib examples in the M0 SDK to see how the RXFIFO and TXFIFO are managed in the ISR handler.  This way you application doesn't need to struggle with trying to interpret the operation.  Let the interrupts steer the sequence of steps.

  • Status Update:

    The master can now read data from the target, but I'm not sure if my approach is correct.

    I discovered that the DL_I2C_TARGET_STATUS_QUICK_COMMAND_READ_WRITE in the SLAVE.SSR allows me to determine whether the operation is a read or write.

    Therefore, I added a check for QUICK_COMMAND_READ_WRITE during the RXFIFO_TRIGGER event to decide whether to fill the TXFIFO.

    The event flow now looks like this:


    DL_I2C_IIDX_TARGET_START

    DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER

    DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER

    DL_I2C_IIDX_TARGET_START

    DL_I2C_IIDX_TARGET_STOP

  • So does this work for you?

  • Yes, the waveform looks correct when measured with an oscilloscope

  • Excellent!  And is the SW working the way you want it to?  Any other issues?