MKE1xF I2C FIFO Error Flag

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

MKE1xF I2C FIFO Error Flag

1,433 Views
mariogolubic
Contributor II

Hi,

I'm trying to resolve this issue for some time now but no luck. I'll state the short form of the firmware workflow.

Behind the simple task-scheduler (lowest ISR priority) there is a constantly running SPWM generator (48kHz) and a ADC (48kHz) (2ch PDB driven). Both are using (high priority) ISR's to set/read parameters.

I2C is connected to a 4x20 character LCD. I2C is clocked at 400kHz. I2C is also used as a non-blocking process with a state machine in ISR to service the ADDRESS-COMMAND-DATA sequence. Address and Command bytes never change.

Every 1ms there is a function call to send a char to a LCD. When to counter runs to 80, whole thing starts again. To start a transfer there is a dedicated function StartMaster(...); that prepares the data to be sent in a software TX buffer. Software TX buffer later fills the I2C periphery hardware Tx buffer.

After a call of the function (I2C bus must be IDLE first), ADDRESS is sent to the LCD. On ACK, ISR send the COMMAND, and on second ACK, ISR sends the DATA byte. STOP is generated after the last ACK.

Sometimes, very irregularly and hard to connect with other functions, the I2C driver detects FIFO Error Flag. This then blocks the LCD and whole thing freezes until reset.

I would appreciate very much if some one knows the conditions in which this flag is raised (or suggest the workaround). Datasheet is very narrow in describing this phenomena: Detects an attempt to send or receive data without first generating a (repeated) START condition. (Kinetis KE1xF Sub-Family Reference Manual, Rev. 3, 06/2017, Page 1250)

If any additional information's are necessary please do ask. I can even present some code segments if needed.

Thanks,

Mario

5 Replies

1,248 Views
mariogolubic
Contributor II

Greetings,

error is resolved.

As it seems it's not related to the MCU HW, rather it's the issue with the way the commands are placed in the code. That being said, it also has to do with the many interrupts running in the background and the position of the next state in the I2C state machine. Check the original code, above and then correct version below.

What was done, was that the next state was refreshed before feeding the data to the TX FIFO. As it turns out, I2C ISR was faster upon arrival than the chance to update the next state variable.

StartMaster()   // called once from task manager, every 1 ms
{
      if(IDLE == i2cDriver->State)
      {
         i2cDriver->State = COMMAND;   // change state first, then load TX FIFO
         m_I2C_send_addres();
      }
}

LcdISR()   // called on ACK or any other I2C interrupt, 80 times in a row
{
  CheckErrorFlags();   // here is where flag type can be checked: NACK, ARBLOST, FIFOERR
   switch(i2cDriver->State)
   {
      case COMMAND:
         i2cDriver->State = DATA;
         m_I2C_send_data(command);
         
      case DATA:
         i2cDriver->State = STOP;
         m_I2C_send_data(data);

      case STOP:
         m_I2C_STOP();
         i2cDriver->State = IDLE;
      default:
         m_I2C_STOP();
         i2cDriver->State = ERROR;
   }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos

1,248 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hi Mario,

I have a couple of questions that can help me better understand the behavior you are experiencing.

Sometimes, very irregularly and hard to connect with other functions, the I2C driver detects FIFO Error Flag

When you say sometimes, is this during the execution of the 80 times yuo are expecting this to go through. Does it always happen after a certain number? Or you can do this process several times before the LCD freezes?

Are you basing your application on an example? If so can you please provie the IDE Name and Version and SDK version as well. 

Best Regards,

Sabina

1,248 Views
mariogolubic
Contributor II

Hi Sabina,

thank You for taking interest in this topic. I'll answer the questions as best as I can, so if anything is left ambiguous feel free to comment. (Your questions are marked so they can be visually different)

When you say sometimes, is this during the execution of the 80 times you are expecting this to go through.

The FIFO error occurs only while sending this data stream (80 messages) to the LCD.

Does it always happen after a certain number?

I did try to find out this by inspecting the I2C lines with a scope and also capturing error in the debug mode. I didn't found a number of messages send prior to the freeze to be a constant. Sometimes, everything works for a number of minutes, 10-12-15-40min and then it suddenly falls apart. Also, regarding the message number, nothing happens on the same count. Sometimes it breaks after 40 successful messages send, sometime after 60 and so on. I know that if there was something regular, I could point myself to the issue and inspect it more deeply, but sadly it isn't. That's why I am asking of the conditions when the FEF is asserted. Maybe this mechanism could put some light on the issue.

Or you can do this process several times before the LCD freezes?

I think I answered this question above.

Also changing the priority of interrupts didn't help. I've even put the I2C ISR on priority 0 but no luck.

I2C engine (simplified)

StartMaster()   // called once from task manager, every 1 ms
{
      if(IDLE == i2cDriver->State)
      {
         i2cDriver->State = ADDRESS;
         m_I2C_send_addres();
         i2cDriver->State = COMMAND;
      }
}

LcdISR()   // called on ACK or any other I2C interrupt, 80 times in a row
{
  CheckErrorFlags();   // here is where flag type can be checked: NACK, ARBLOST, FIFOERR
   switch(i2cDriver->State)
   {
      case COMMAND:
         m_I2C_send_data(command);
         i2cDriver->State = DATA;
      case DATA:
         m_I2C_send_data(data);
         i2cDriver->State = STOP;
      case STOP:
         m_I2C_STOP();
         i2cDriver->State = IDLE;
      default:
         m_I2C_STOP();
         i2cDriver->State = ERROR;
   }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos

1,248 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hello Mario,

Thank you for the detailed information. The FEF flag is enabled, when clock stretching is disabled. It is possible that you are having clock synchronization issues when the data is being sent through. Generally this is not necessary as the master determines the speed and the slave follows, but it is possible that the slave may be taking longer to process the information at certain points and therefore causing it to stop transmitting data randomly. 

Assuming that the hardware is setup correctly and prior to making any changes, Could you check if the following bits are also set along with the FEF.

TXFE

RXUFE

TXOF

RXUF

Let me know the results of this, so I can continue the support.

Best Regards,

Sabina

0 Kudos

1,248 Views
mariogolubic
Contributor II

Thanks Sabina,

I've attached full I2C0 memory dump on event. I'm not sure but except FEF, no other register exist from Your list. :smileysad:

I2C0_dump.png

I'll be on Your disposal for further questions.

Kind regards,

Mario

0 Kudos