Question about i2cio module

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Question about i2cio module

2,176 Views
aresmarser
Contributor III

Hello Sirs,

I am studying NHS3100 board kit.

I want to add my motion sensor with I2C interface.

I read some document and it is said that "The user of the I2CIO module only needs to use the API functions below to have full I2C communication. "

I tried my test and the code snippet based on "app_demo_dp_tlogger" is below but it does NOT work.

And I have already linked the mods "i2cio" into my project.

---

    RegData = 0x57;
//    Sensor_WriteReg(LIS3DH_I2C_DEVICE2_WRITE_ADDR, LIS3DH_CTRL_REG1, &RegData);
{
 uint8_t sendBuf[2] = {0x00};
    I2CIO_Init();
 sendBuf[0] = LIS3DH_CTRL_REG1;
 sendBuf[1] = 0x57;
    I2CIO_Tx(sendBuf,2);
}
 printf("Write slaveAddr 0x%02X, reg_addr 0x%02X, Write Data 0x%02X\r\n", LIS3DH_I2C_DEVICE2_WRITE_ADDR, LIS3DH_CTRL_REG1, RegData);
---
The running/testing log is below:
---
Sensor_Init for I2C...
Chip_I2C_MasterSend slaveAddr 0x32, txBuff: 20 57
Chip_I2C_MasterTransfer
Chip_I2C_EventHandler: I2C event 3
Chip_I2C_EventHandler: I2C event 1
Chip_I2C_EventHandler: I2C transfer status 4
---
From my observation, the routine stuck in the while statement in the funciton "Chip_I2C_EventHandler":
---
/* Wait for the status to change */
while (*stat == I2C_STATUS_BUSY) {
}
---
I didn't see I2C_STATUS_DONE which will be set in the function "I2C0_IRQHandler" => "Chip_I2C_MasterStateHandler" as my own understand.
Anyone could help me to review if anthing wrong?
Thanks,
Arna
Labels (1)
0 Kudos
Reply
7 Replies

1,927 Views
aresmarser
Contributor III

Hi Kan,

I tried to debug with breakpoints as below.

Chip_I2C_MasterStateHandler.png

Chip_I2C_MasterSend.png

Chip_I2C_MasterRead.png

And here is my test code snippet ------------

  uint8_t slaveAddr = 0x19;
  uint8_t regAddr = 0x20;  // 0x0F;
  uint8_t readData = 0;
  int result = 0;
  Chip_I2C_MasterSend(I2C0, slaveAddr, &regAddr, 1);
  result = Chip_I2C_MasterRead(I2C0, slaveAddr, &readData, 1);
-------------------------------------------------------------------------------------
(1) For "Chip_I2C_MasterSend" procedure, "Chip_I2C_MasterStateHandler" hit the breakpoint and finally "Chip_I2C_MasterSend" hit the breakpoint, that is, the operation was successful.
(2) But for "Chip_I2C_MasterRead" procedure, both "Chip_I2C_MasterStateHandler"  and "Chip_I2C_MasterRead" never hit the breakpoints!
Here is the problem I met.
Any idea how I should debug to dig out the root cause?
I have sufferred from this problem for several days.
Look forward to your support and help.
Appreciated if you could help me more.
Many thanks,
Arna
0 Kudos
Reply

1,927 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi Arna,

To debug I2C, you'd better do with an I2C logic analyzer, or at least an oscilloscope to check if the waveform on I2C SCL and SDA lines is what you expected, and you may also check the data sheet of the I2C device you were handling, if the reading process is correct for that device.

Hope that helps,

Best Regards,

Kan

0 Kudos
Reply

1,927 Views
aresmarser
Contributor III

Hi Kan,

Thank you for more comment.

It makes me more clear to undstand the whole thing.

As my understanding,

Once the master transfer done, the status shoud be set as "I2C_STATUS_DONE". Am I right?

And I see it would happen in two cases as below:

1. -# Interrupt based handling makes use of #Chip_I2C_EventHandler handler.

I2C0_IRQHandler => Chip_I2C_MasterStateHandler => handleMasterXferState => change "xfer->status" to “I2C_STATUS_DONE” once master transfer done;

2. -# Polling based handling makes use of #Chip_I2C_EventHandlerPolling handler.

Chip_I2C_EventHandlerPolling =>  Chip_I2C_MasterStateHandler => handleMasterXferState => change "xfer->status" to “I2C_STATUS_DONE” once master transfer done.

Is it right?

And if the stat is always I2C_STATUS_BUSY, the while condition is always met and the function is never return.

So I am confused why the stat was not changed.

------

/* Chip event handler interrupt based */
void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
{
    struct i2c_interface *iic = &i2c[id];
    volatile I2C_STATUS_T *stat;
    /* Only WAIT event needs to be handled */
    if (event != I2C_EVENT_WAIT) {
        return;
    }
    stat = &iic->mXfer->status;
    /* Wait for the status to change */
    while (*stat == I2C_STATUS_BUSY) {
    }
}
/* Chip polling event handler */
void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
{
    struct i2c_interface *iic = &i2c[id];
    volatile I2C_STATUS_T *stat;
    /* Only WAIT event needs to be handled */
    if (event != I2C_EVENT_WAIT) {
        return;
    }
    stat = &iic->mXfer->status;
    /* Call the state change handler till xfer is done */
    while (*stat == I2C_STATUS_BUSY) {
        if (Chip_I2C_IsStateChanged(id)) {
            Chip_I2C_MasterStateHandler(id);
        }
    }
}
------

Thanks,

Arna

0 Kudos
Reply

1,927 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi Arna,

Yes, your understanding is right. I2C_STATUS_DONE is set in handleMasterXferState(), which is called in I2C0_IRQHandler() or Chip_I2C_EventHandlerPolling(), but what ever you used for the event handler, you may just set a breakpoint at the following line:

pastedImage_1.png

you may know if this state is set during your test, there is no printf() needed for that purpose.

Hope that helps,

Best Regards,

Kan

0 Kudos
Reply

1,927 Views
aresmarser
Contributor III

Hi Kan,,

Thank you for your reply.

 I set "Quickstart -> Quick Settings -> Set library/header type => Redlib (semihost)" to use standard printf function.

1. "It is not recommended using printf() in an interrupt based handler"

=> Is it ok if I use polling event handler "Chip_I2C_SetMasterEventHandler(I2C0, Chip_I2C_EventHandlerPolling)" instead of event handler interrupt based "Chip_I2C_SetMasterEventHandler(I2C0, Chip_I2C_EventHandler)"?

2. "It would be better if you use an I2C analyzer to trace the data transaction."

=> How to do that? Any user manual?

Thanks,

Arna

0 Kudos
Reply

1,927 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi Arna,

Sorry for the misunderstanding, what I mean is Printf() is not recommended using in an ISR, but ok if you put it in Chip_I2C_EventHandlerPolling() or Chip_I2C_EventHandler(). and from the log, the I2C seems work well as the state changing shows it starts from I2C_EVENT_LOCK to I2C_EVENT_UNLOCK, it means the master transfer is complete, so it should no be stuck in the while loop, the reason why you didn't see I2C_STATUS_DONE is due to this state is only set in Chip_I2C_MasterStateHandler(), which is called in Chip_I2C_EventHandlerPolling(), not Chip_I2C_EventHandler().

The I2C analyzer is just a logic analyzer for I2C protocol. something like Beagle I2C/SPI Protocol Analyzer - Total Phase .

Hope that helps,


Have a great day,
Kan

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

1,927 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi Arna,

How did you get the log? It is not recommended using printf() in an interrupt based handler, cause it affects the timing. It would be better if you use an I2C analyzer to trace the data transaction.


Have a great day,
Kan

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply