MQX 4.0 I2C Locks Up

cancel
Showing results for 
Search instead for 
Did you mean: 

MQX 4.0 I2C Locks Up

Jump to solution
4,362 Views
myke_predko
Senior Contributor III

This may be a follow on to "Using AN4652 - I2C Driver Locks Up" (https://community.freescale.com/message/313948#313948) but I had a couple of questions that didn't seem to be answered here. 

I am prototyping my product using the Tower System with the TWRK20D72M processor board (note that J25 and J26 have been pulled to minimize the load on the I2C bus, which seems to help), a TWR-SER PCB (there are no I2C devices here) and a prototype PCB with an I2C hand wired OLED mounted to it and a connection to an I2C controlled audio amplifier through an IDC cable.  I'm running at 400,000bps.  This is obviously not an optimal situation and I can see where the wiring can cause problems on the line as opposed to a properly terminated line on a PCB - this supposition seems to be supported with what I am observing. 

Periodically, the I2C crashes with the SDA line being held low.  The OLED *seems* to be holding down the (ie I can see the line being held low and when I pull the OLED, the SDA line goes high again). 

When the I2C line is down, I pause the application in CW and I find that execution is stuck in I2c_pol_ki2c.c at line 361:

         while (tmp & I2C_S_BUSY_MASK)

         {

            if (tmp & I2C_S_IICIF_MASK)

            {

               i2c_ptr->S |= I2C_S_IICIF_MASK;

               tmp = (uint_8)i2c_ptr->D;

            }

            tmp = i2c_ptr->S;

         }

This seems to be polling loop for the SDA line to go high. 

As I hinted at above, with the accelerometer connection through J25 and J26 disconnected, the rate of errors is much less - but it still happens.  What is really interesting is that if there is a 'scope probe on the SDA line, the program runs indefinitely (which tells me that it's a termination problem). 

My questions are:

1.  Is there a version of the MQX I2C driver which supports timeouts on the SDA/SCL lines?  I didn't want to use the code that was attached to "Using AN4652 - I2C Driver Locks Up" as the discussion was regarding MQX 3.8.1 and I'm working with MQX 4.0

2.  Any suggestions on how the line should be terminated?  This won't be an issue with the final product, but I want to have a reliable prototyping platform until the PCBs are available.  I'm going to try to match the scope termination with 1M resistors to ground.

Thanx,

myke

Tags (2)
0 Kudos
1 Solution
664 Views
Cdn_aye
Senior Contributor I

Hi Myke

You turn off the i2c drivers in user_config.h

Here is my user_config.h; note the II2C0_FB

I am using the K20dx256VLL10  although this is the user_config.h for the bsp for the twrk40dx256 because there is no bsp for the k20dx256

The extra code you mention relates to having the BSP load the driver during the init.

I would load the new code for the appnote but I can't see a way to do that for some reason. But it is simple; the code was updated about feb 21 2013. Just do a search for the authors name in the appnote. He added an additional flag check for a certain condition in a status register.

Anyway, it is well written and works without problem. Just follow the appnote for building the code. One of the files may have changed location for the build procedure, that is it is on level higher in the directory structure for mqx 4.0.

If you have a problem, post your question and I can show you how to proceed.

Regards

Robert

//====================================================================================

/* mandatory CPU identification */

#define MQX_CPU                 PSP_CPU_MK40DX256Z

#define BSP_DEFAULT_IO_CHANNEL              "ittya:"         // rwl, change so printf's not going on BT channel, ittya

#define BSP_DEFAULT_IO_CHANNEL_DEFINED

#define BSPCFG_ENABLE_IO_SUBSYSTEM      1

#define BSPCFG_ENABLE_II2C0_FB          1            // interrupt driven i2c driver re-added Feb 19 2013

#define BSPCFG_ENABLE_II2C1_FB          0

/* MGCT: <generated_code> */

#define BSPCFG_ENABLE_TTYA              0

#define BSPCFG_ENABLE_ITTYA             1

#define BSPCFG_SCI0_BAUD_RATE           9600

#define BSPCFG_SCI0_QUEUE_SIZE          64

#define BSPCFG_ENABLE_TTYB              1               // defined so printf goes here

#define BSPCFG_ENABLE_ITTYB      0

#define BSPCFG_ENABLE_TTYC       0

#define BSPCFG_ENABLE_ITTYC      0

#define BSPCFG_ENABLE_TTYD              0

#define BSPCFG_ENABLE_ITTYD      0

#define BSPCFG_ENABLE_TTYE       0

#define BSPCFG_ENABLE_ITTYE      0

#define BSPCFG_ENABLE_TTYF       0

#define BSPCFG_ENABLE_ITTYF      0

#define BSPCFG_ENABLE_I2C0       0

#define BSPCFG_ENABLE_II2C0      0

#define BSPCFG_ENABLE_I2C1              0

#define BSPCFG_ENABLE_II2C1             0

#define BSPCFG_ENABLE_SPI0       0

#define BSPCFG_ENABLE_ISPI0      0

#define BSPCFG_ENABLE_SPI1       0

#define BSPCFG_ENABLE_ISPI1      0

#define BSPCFG_ENABLE_SPI2       0

#define BSPCFG_ENABLE_ISPI2      0

#define BSPCFG_ENABLE_RTCDEV     1

#define BSPCFG_ENABLE_II2S0      0

#define BSPCFG_ENABLE_IODEBUG    0

/* pccard shares CS signal with MRAM - opening pccard in user application disables MRAM */

#define BSPCFG_ENABLE_PCFLASH    1

#define BSPCFG_ENABLE_ADC0              1

#define BSPCFG_ENABLE_ADC1       1

#define BSPCFG_ENABLE_FLASHX            1

#define BSPCFG_ENABLE_ESDHC             0

#define BSPCFG_ENABLE_LCD        0

#define MQX_USE_SW_WATCHDOGS            1

#define  MQX_USE_TIMER                  1

#define MQX_HAS_TIME_SLICE              1

#define MQX_USE_IDLE_TASK        1

#define MQX_ENABLE_LOW_POWER     0

#define RTCSCFG_ENABLE_TCP              0

#define SHELLCFG_USES_MFS               1

#define SHELLCFG_USES_RTCS              0

#define MQX_KERNEL_LOGGING              1

#define MQX_USE_LOGS                    1

#define  MQX_ROM_VECTORS                0               // put vectors in RAM for bootloader

/* MGCT: </generated_code> */

View solution in original post

0 Kudos
19 Replies
664 Views
shikhasuresh
Contributor I

Hello,

I want to know whether the i2c lockup is removed in mqx4.2? Im working on K65 and trying to interface AFE4404 with K65 via I2C. The code is getting hanged after single write. I tried the same with capacitive touch panel and the same issue happened.Can anyone helps me to solve this issue?

0 Kudos
664 Views
myke_predko
Senior Contributor III

Just a few more datapoints. 

I tried a number of different resistors to ground with no luck on improving the performance of the prototype hardware. 

I also tried dropping the data rate, but I found that the code started looping in i2C_int_ki2c.c at line 359:

         while (0 == (i2c_ptr->S & I2C_S_IICIF_MASK))

            { };    /* wait for address transferred */

Any ideas?

Thanx,

myke

0 Kudos
664 Views
Martin_
NXP Employee
NXP Employee

Myke,

We think MQX 4.0 I2C driver has a sw problem when flushing. I've used the attached patch to fix, it has much improved my test application (running now on my table). Please give it a try (build your BSP with the attached file, then the application) and let me know how that works for you.

0 Kudos
664 Views
Cdn_aye
Senior Contributor I

Hi Myke

We also used the i2c polled driver and found that it would hang. My experience is that the best driver to use is the i2c interrupt driven driver in an4652, we have never had it fail as of yet. We previously had the polled driver hang and it was (for us) impossible to code around. All you need is to miss an ACK because of a system function (MQX) and you are done. There is no recovery; it hangs.

If you use the above driver, make sure you get the latest code base. It was updated a few weeks ago. I have spent a lot of time on  polled i3c polled driver in Coldfire and Kinetis (using PE and MQX) and couldn't get reliable operation. IMO is just the nature of a polled anything in an interrupt driven OS.

Robert

0 Kudos
664 Views
myke_predko
Senior Contributor III

Hi Robert and Martin,

Thank you for the replies. 

Before I implement the code in AN4652, I have a couple of questions:

  1. In my user_config.h file, I have specified the interrupt operation of the I2C driver (I am using both I2C ports on the K20) - which I should have noted in my original email, and was surprised to see the polling loop.  Will the driver in AN4652 change this to a full interrupt implementation? 
  2. I notice in the AppNote pdf, that it instructs the user to add the two lines select the II2C0 but NOT the II2C1 (Page 10) - will this fix work for both I2C ports on the K20? 
  3. Why would I patch the i2c_ki2c.h and init_bsp.c files when there are the same files in the .zip that comes with the AppNote? 
  4. Robert, you talk about getting the latest code base.  According to the "Release Notes", I have 4.0.0 (is there a better source for this information)?  If I look at the MQX page, all I see is 4.0 - where do I find the "latest code base" and what are the instructions for installing it?  Even if I look here: Freescale MQX&amp;#8482; Software Solutions Product Summary Page, I don't see any information on something that was released a few weeks ago.  

Thanx, I want to make sure this goes as smoothly as possible with minimal switch over time. 

myke

0 Kudos
665 Views
Cdn_aye
Senior Contributor I

Hi Myke

You turn off the i2c drivers in user_config.h

Here is my user_config.h; note the II2C0_FB

I am using the K20dx256VLL10  although this is the user_config.h for the bsp for the twrk40dx256 because there is no bsp for the k20dx256

The extra code you mention relates to having the BSP load the driver during the init.

I would load the new code for the appnote but I can't see a way to do that for some reason. But it is simple; the code was updated about feb 21 2013. Just do a search for the authors name in the appnote. He added an additional flag check for a certain condition in a status register.

Anyway, it is well written and works without problem. Just follow the appnote for building the code. One of the files may have changed location for the build procedure, that is it is on level higher in the directory structure for mqx 4.0.

If you have a problem, post your question and I can show you how to proceed.

Regards

Robert

//====================================================================================

/* mandatory CPU identification */

#define MQX_CPU                 PSP_CPU_MK40DX256Z

#define BSP_DEFAULT_IO_CHANNEL              "ittya:"         // rwl, change so printf's not going on BT channel, ittya

#define BSP_DEFAULT_IO_CHANNEL_DEFINED

#define BSPCFG_ENABLE_IO_SUBSYSTEM      1

#define BSPCFG_ENABLE_II2C0_FB          1            // interrupt driven i2c driver re-added Feb 19 2013

#define BSPCFG_ENABLE_II2C1_FB          0

/* MGCT: <generated_code> */

#define BSPCFG_ENABLE_TTYA              0

#define BSPCFG_ENABLE_ITTYA             1

#define BSPCFG_SCI0_BAUD_RATE           9600

#define BSPCFG_SCI0_QUEUE_SIZE          64

#define BSPCFG_ENABLE_TTYB              1               // defined so printf goes here

#define BSPCFG_ENABLE_ITTYB      0

#define BSPCFG_ENABLE_TTYC       0

#define BSPCFG_ENABLE_ITTYC      0

#define BSPCFG_ENABLE_TTYD              0

#define BSPCFG_ENABLE_ITTYD      0

#define BSPCFG_ENABLE_TTYE       0

#define BSPCFG_ENABLE_ITTYE      0

#define BSPCFG_ENABLE_TTYF       0

#define BSPCFG_ENABLE_ITTYF      0

#define BSPCFG_ENABLE_I2C0       0

#define BSPCFG_ENABLE_II2C0      0

#define BSPCFG_ENABLE_I2C1              0

#define BSPCFG_ENABLE_II2C1             0

#define BSPCFG_ENABLE_SPI0       0

#define BSPCFG_ENABLE_ISPI0      0

#define BSPCFG_ENABLE_SPI1       0

#define BSPCFG_ENABLE_ISPI1      0

#define BSPCFG_ENABLE_SPI2       0

#define BSPCFG_ENABLE_ISPI2      0

#define BSPCFG_ENABLE_RTCDEV     1

#define BSPCFG_ENABLE_II2S0      0

#define BSPCFG_ENABLE_IODEBUG    0

/* pccard shares CS signal with MRAM - opening pccard in user application disables MRAM */

#define BSPCFG_ENABLE_PCFLASH    1

#define BSPCFG_ENABLE_ADC0              1

#define BSPCFG_ENABLE_ADC1       1

#define BSPCFG_ENABLE_FLASHX            1

#define BSPCFG_ENABLE_ESDHC             0

#define BSPCFG_ENABLE_LCD        0

#define MQX_USE_SW_WATCHDOGS            1

#define  MQX_USE_TIMER                  1

#define MQX_HAS_TIME_SLICE              1

#define MQX_USE_IDLE_TASK        1

#define MQX_ENABLE_LOW_POWER     0

#define RTCSCFG_ENABLE_TCP              0

#define SHELLCFG_USES_MFS               1

#define SHELLCFG_USES_RTCS              0

#define MQX_KERNEL_LOGGING              1

#define MQX_USE_LOGS                    1

#define  MQX_ROM_VECTORS                0               // put vectors in RAM for bootloader

/* MGCT: </generated_code> */

View solution in original post

0 Kudos
664 Views
myke_predko
Senior Contributor III

Martin and Robert,

Thank you for the quick replies. 

Just a couple of quick ones back:

  1. I have the code from the AppNote - to find it, put in "AN4652" in the search bar, when you get all the options, click on "Documentation" and PDF and zip files come up.  The "date last modified" is "3/20/2013".  I believe this is the correct one according to what's written above. 
  2. When I look at Martin's reply, it seems to be a separate one to AN4652 and reading through things, it sounds like AN4652 is the superior solution, correct? 
  3. Finally, Robert, you mentioned above about getting the latest code base - could you please explain that in more detail?

Thanx,

myke

0 Kudos
664 Views
Cdn_aye
Senior Contributor I

Myke

I just downloaded the appnote zip from Mar 20 2013 and did a comparison and I don't see any difference from the original. I may be overlooking something but I don't think this is the latest code. File i2c_int_k_fb.c, is the only changed file.

I uploaded this to this site and it is said to be queued and waiting for scan but I am not sure how to make this available to others...

But I just did a search for Guo Jia on this forum and the file you need is attached by him with an explanation; download that.

Regards

Robert

0 Kudos
664 Views
myke_predko
Senior Contributor III

Hi Robert,

So, use the i2c_int_k_fb.c driver file found here: https://community.freescale.com/message/315959#315959 with the same instructions as in AN4652 which call for the patches to:

  • I2c_ki2c.h
  • init_bsp.c
  • user_config.h

Finally, I can use the version of MQX 4.0 that I downloaded without any other changes? 

Thanx,

myke

0 Kudos
664 Views
Cdn_aye
Senior Contributor I

Hi Myke

yes, that is correct

Robert

0 Kudos
664 Views
myke_predko
Senior Contributor III

Hi Robert and Martin,

Thank you for the help - I have installed the update and have run it consistently (ie consistent writes from the K20 to the OLD and I2C based amplifier on the I2C bus for about five hours now without any hangs.)  I'm crossing it off my list of issues.

For people who are looking to get reliable interrupt based I2C communications - this seems like the way to go, but I must warn you; the new driver does not work like the old (or any other driver) - study the code in AN4652 before making your changes.  I ended up rewriting all my I2C code and there are some changes to my messaging that I would like to make going forwards to eliminate the need for a separate txBuffer.

For Robert and Martin there are a few issues that I would like to bring to your attention (and if you put in fixes for them I would appreciate you letting me know):

1.  I don't believe that I2C writes are correct.  When I am sending a byte to a register, there are five write cycles, not the three that I would expect (7 bit slave address + R/W flag, 8 bit register address, 8 bit data for register).  Things seem to work but when I look at the waveform on my 'scope, I could see the two additional writes.

2.  Reads appear correct - four byte transfers (with the last one being an unacknowledged read).

3.  The data rate is one half the specified rate - to get a full 400kbps data rate (2.5us per bit), I had to specify 800kbps to get this actual data rate.

4.  The first screen shots in AN4652 (figure 5 & 6) does not match what would be sent out by the "master" and "slave" code, respectively, in the actual application.  It caused me a bit of time to convince myself that it wasn't correct because it would been very time consuming to wire up representative hardware to see the code in operation.

The steps I took to implement the AN4652 code were:

1.  Shut down CodeWarrior.  This was done to make sure the i2c_int_k_fb.c driver (I used the one attached in this thread) would be in the MQX bsp could be copied into the mqx source code folders.

2.  Copy the i2c_int_k_fb.c driver into C:\Freescale\Freescale_MQX_4_0\mqx\source\io\i2c\int

3.  Restart CodeWarrior.  When it was up, drag I2C_int_k_fb.c from C:\Freescale\Freescale_MQX_4_0\mqx\source\io\i2c\int into the bsp_.../Peripheral IO Drivers/i2c/int folder.  The file should be both part of the MQX project as well as have this location recognized by CodeWarrior.

4.  Add

extern uint_32 _ki2c_int_fb_install (char_ptr, KI2C_INIT_STRUCT_CPTR);

to i2c_ki2c.h in the "FUNCTION PROTOTYPES" area of the include file (which is found in bsp_.../Peripheral IO Drivers/i2c).  I noted that this was part of "AN4652" in case I had to find it again later.

5.  In, init_bsp.c, found in bsp_.../twrk... BSP Files, add the lines (after the I2C definitions and you may want to mark that this is an "AN4652" change as well:

#if BSPCFG_ENABLE_II2C0_FB

_ki2c_int_fb_install("ii2c0fb:", &_bsp_i2c0_init);

#endif

#if BSPCFG_ENABLE_II2C1_FB

_ki2c_int_fb_install("ii2c1fb:", &_bsp_i2c1_init);

#endif

6.  Open user_config.h and make sure all the I2C options are "false" (in the "BSP" tab).

7.  Next, click on the "user_config.h" tab to enable the text editor for user_config.h and add the lines to enable the use of AN4652 interrupt based I2C driver (set define to "1" if the I2C port is to be used - in the example below, both are enabled):

#define BSPCFG_ENABLE_II2C0_FB                    1  // interrupt driven i2c driver re-added Feb 19 2013

#define BSPCFG_ENABLE_II2C1_FB                    1

8.  "Clean" and "Build" the bsp project.

9.  Modify your application to work with the AN4652 interrupt based driver.  Go through the AppNote text and make sure you understand the use of fopen, ioctl(i2cHandle, IO_IOCTL_I2C_SET_BAUD (note that this requires 2x the speed that is desired to be specified), fwrite and fread.

10.  "Clean" and "Build" your application project.

Have a great weekend!

myke

664 Views
Cdn_aye
Senior Contributor I

Hi Myke

Good to hear you got it going.

The write & read methodology will normally depend on the device. Some devices require setup of a register pointer to access further registers and support a burst read which auto increments the pointer, other devices like the i2c eeprom example use special write procedures that differ from the RT clocks like the DS1305 for example.

As far as I know the only thing that is defined for i2c as a protocol are the bits in the 9 bit data stream and the relationship within the ACK NACK sequences for the SCL & SDA lines. The implementation of access to the registers is device dependent.

Regards

Robert

0 Kudos
664 Views
myke_predko
Senior Contributor III

Hi Robert,

Thanx for the reply.  As I said, the new driver does seem to be reliable (much more reliable than the original driver). 

Please let me know of any updates to the driver (such as getting the data rate correct).

myke

0 Kudos
664 Views
kirankunnath
Contributor II

Hi Myke,

     We are facing some issues with the MQX interrupt mode i2c. We have done all the settings as mentioned in AN4652. When running the code for reading data from a device register,the device is waiting for the condition

if(_lwevent_wait_ticks((LWEVENT_STRUCT_PTR)(&(io_info_ptr->lwevent_master)), 1, FALSE, 400) == LWEVENT_WAIT_TIMEOUT)

Everything will go fine till the call  in the Rx_master_ISR,

_lwevent_set((LWEVENT_STRUCT_PTR)(&(io_info_ptr->lwevent_master)), 1);

After this control is going to dispatch.s and lost. Do you have any idea why this is happening?

The same device is working fine in polling mode but after some time it will get hangs in

while (tmp & I2C_S_BUSY_MASK)

         {

            if (tmp & I2C_S_IICIF_MASK)

            {

               i2c_ptr->S |= I2C_S_IICIF_MASK;

               tmp = (uint_8)i2c_ptr->D;

            }

            tmp = i2c_ptr->S;

         }


Because of this issue,i tried using interrupt mode.


Please help.



regards,

Kiran

0 Kudos
664 Views
gordonfinlay
Contributor I

Hi Kiran,

It seems that in Myke Predko's response to your query above, he repeated the correct instructions for installing and calling the AN4652 driver, but I didn't see any answer to your question concerning the lwevent_wait_ticks() timeout, or the issue with a scheduler context switch.

Did you ever determine what was causing the MQX scheduler (in dispatch.S) to perform a context switch in your i2c_int_k_fb.c code when the _ki2c_isr made a call to _lwevent_set()? And did your code in _fb_rx_master receive the event using _lwevent_wait_ticks without timing out? If there was a timeout, was the code following the if statement executed without a context switch?

We have modified our version of the __fb_rx_master() and __fb_tx_master() which attempts to do a i2c bus reset (bin-banging the SCL/SDA lines as GPIOs to send clocks to the slave to release the SDA line if held low).

However, I did notice that there seems to be a missing "return 0;" statement in _fb_tx_master() function for the timeout condition. We assume that there should be a "return 0;"  statement here in a similar fashion to the code _fb_rx_master() where it handles the timeout for the _lwevent_wait_ticks call. We also have added code to do a forced i2c bus reset and to send a slave stop condition when the event timeouts occur (indicating that the ISR returned prematurely without sending an event due to the SLTF or SHTF2 flag bits in the SMB register indicating a SCL Low timeout or SDA Low timeout being set ).  Can you confirm if the driver should be doing a return after the timeout without falling through to the code below the if-block?

static uint_32 _fb_rx_master ( FB_VKI2C_INFO_STRUCT_PTR io_info_ptr, I2C_MemMapPtr i2c_ptr, uchar_ptr buffer, uint_32 length )

{

   //if(i2c_ptr->S & I2C_S_BUSY_MASK)

   //    return 0;

   length = I2C_FB_DATA_LEN(length);

   io_info_ptr->data = buffer;

   io_info_ptr->data_len = length;

   io_info_ptr->index = 0;

   io_info_ptr->index_rx_tx = 0;

   io_info_ptr->index_repeat_start = REPEAT_INDEX_RX;

   i2c_ptr->C1 |= 0x80;

   _start(i2c_ptr);

   io_info_ptr->index++;

   i2c_ptr->D = (io_info_ptr->data[io_info_ptr->index - 1] << 1) | I2C_OPERATION_WRITE; // send address

   // wait 1000 ticks --> 5 sec (maximum) for the transaction to end

   if (_lwevent_wait_ticks((LWEVENT_STRUCT_PTR)(&(io_info_ptr->lwevent_master)), 1, FALSE, 1000) == LWEVENT_WAIT_TIMEOUT)

   {

      i2c_ptr->C1 &= 0x7f;

      i2c_ptr->C1 |= 0x80;

      clock_out_slave();   // Bit-bang SCL/SDA lines to perform I2C reset to clock out slave if necessary

      _stop(i2c_ptr);         // Send a slave stop condition

      return 0;

   }

   i2c_ptr->C1 &= 0x7f;

   if (io_info_ptr->index_rx_tx < 1)

      return 0;

   else

      return io_info_ptr->index_rx_tx - 1;

}

static uint_32 _fb_tx_master ( FB_VKI2C_INFO_STRUCT_PTR io_info_ptr, I2C_MemMapPtr i2c_ptr, uchar_ptr buffer, uint_32 length )

{

   i2c_ptr = io_info_ptr->i2c_ptr;

   io_info_ptr->data = buffer;

   io_info_ptr->data_len = I2C_FB_DATA_LEN(length);

   io_info_ptr->index = 0;

   io_info_ptr->index_rx_tx = 0;

   io_info_ptr->index_repeat_start = REPEAT_INDEX_TX_NOT_USED; //ylly we do not want repeated start

   io_info_ptr->buf_x_stop[0] = io_info_ptr->data[0]; // record dst i2c slave address

   i2c_ptr->C1 |= 0x80;

   _start(i2c_ptr);

   io_info_ptr->index++;

   i2c_ptr->D = (io_info_ptr->data[io_info_ptr->index - 1] << 1) | I2C_OPERATION_WRITE; // send address

   // wait 1000 ticks --> 5 sec (maximum) for the transaction to end

   if (_lwevent_wait_ticks((LWEVENT_STRUCT_PTR)(&(io_info_ptr->lwevent_master)), 1, FALSE, 1000) != MQX_OK)

   {

      i2c_ptr->C1 &= 0x7f;

      i2c_ptr->C1 |= 0x80;

      clock_out_slave();     // Bit-bang SCL/SDA lines to perform I2C reset to clock out slave if necessary

      _stop(i2c_ptr);            // Send a slave stop condition

      return 0;                      // In the original patched code from Guo Jia - this line ( "return 0;" ) was missing - I assume that

                                          // it should be here (similar to _fb_rx_master function) to prevent falling through this if block to the lines below???

   }

   i2c_ptr->C1 &= 0x7f;

   if (io_info_ptr->index_rx_tx < 2)

      return 0;

   else

      return io_info_ptr->index_rx_tx - 2;

}

I look forward to your comments.

Gordon

0 Kudos
664 Views
myke_predko
Senior Contributor III

Hi Kiran,

I think that it's fairly well established that the int I2C handler code that comes with the MQX 4.0.0 and earlier (I don't know the exact status of what will be available for 4.1.0 and 5.0) don't work and you have to replace the code with the "i2c_int_k_fb.c" file that is linked to above. 

In my bsp documentation, below are the steps that I go through.  This is for using both I2C devices in a K20. 


1. Shut down CW. 

2. Copy i2c_int_k_fb.c into C:\Freescale\Freescale_MQX_4_0\mqx\source\io\i2c\int

3. Edit j20 in C:\Freescale\Freescale_MQX_4_0\mqx\source\bsp\j20 and add the lines after the “** Interrupt-driver I2C1 device”:

/*

** Enhanced Interrupt-driven I2C0 device

** MGCT: <option type="bool"/>

*/

#ifndef BSPCFG_ENABLE_II2C0_FB

    #define BSPCFG_ENABLE_II2C0_FB                 0

#endif

/*

** Enhanced Interrupt-driven I2C1 device

** MGCT: <option type="bool"/>

*/

#ifndef BSPCFG_ENABLE_II2C1_FB

    #define BSPCFG_ENABLE_II2C1_FB                 0

#endif

4. Edit user_config.h in C:\Freescale\Freescale_MQX_4_0\config\j20 and add the lines after the “#define BSPCFG_ENABLE_II2C1”:

#define BSPCFG_ENABLE_II2C0_FB 0

#define BSPCFG_ENABLE_II2C1_FB 0

5. Restart CW. 

6. Drag i2c_int_k_fb.c from C:\Freescale\Freescale_MQX_4_0\mqx\source\io\i2c\int into CW’s bsp_j20\Peripheral IO Drivers\i2c\int project

7. In i2c_ki2c.h found in CW’s bsp_j20\Peripheral IO Drivers\i2c project, in the “Function Prototypes” area, add the line:

extern uint_32 _ki2c_int_fb_install (char_ptr, KI2C_INIT_STRUCT_CPTR);

8. In init_bsp.c found in CW’s bsp_j20\j20 BSP Files project, after the check for BSPCFG_ENABLE_II2C1” add the lines:

#if BSPCFG_ENABLE_II2C0_FB

_ki2c_int_fb_install("ii2c0fb:", &_bsp_i2c0_init);

#endif

#if BSPCFG_ENABLE_II2C1_FB

_ki2c_int_fb_install("ii2c1fb:", &_bsp_i2c1_init);

#endif

9. Open user_config.h in CW and set the I2C options as:

#define BSPCFG_ENABLE_I2C0                        0

#define BSPCFG_ENABLE_I2C1                        0

#define BSPCFG_ENABLE_II2C0                       0

#define BSPCFG_ENABLE_II2C1                       0

#define BSPCFG_ENABLE_II2C0_FB                    1

#define BSPCFG_ENABLE_II2C1_FB                    1

10. Build the j20 libraries:

    • - PSP
    • - BSP
    • - MFS
    • - RTCS
    • - Shell
    • - USB Device
    • - USB Host

11. Ready to create applications which use the enhanced I2C libraries.

Sorry it's a lot of work - but I tried multiple options and this is the one that works. 

Good luck,

myke

0 Kudos
664 Views
Martin_
NXP Employee
NXP Employee

Unfortunately I don't have experience with AN4652, I'm happy to hear it works.

I would like to add to MQX 4.0 i2c driver Ad 1)

The fix I posted is for interrupt version of the driver. Unfortunately interrupt version uses polling method for flush(). I think it is bad software design.

It can be improved, for example add _time_delay() blocking call in fflush ioctl in the patched source file.

Another (better) option would be to synchronize with the interrupt routine using lwsem_wait/lwsem_post. The fflush ioctl would call lwsem_wait. The I2C interrupt routine would lwsem_post as soon as it writes the last data byte.

As for timeouts, you would need to add them manually around while(1) loops in the i2c driver. Especially around the while loops in the ioctl "flush" and maybe also ioctl "stop", in order to allow master to detect a problem at application level and recover.

We plan to re-desing the i2c driver, as we did previously with spi driver. It is on TODO list.

664 Views
c_dawg
Contributor III

Is this fix needed in MQX 4.1?

Thanks,

Colin

0 Kudos
664 Views
Martin_
NXP Employee
NXP Employee

I think the fix for the bug appears in MQX 4.0.2. However, the fix above is only for Kinetis specific file, so it is possible that ColdFire files are still affected. If so, copy IO_IOCTL_FLUSH_OUTPUT code from the Kinetis file to the ColdFire file.

0 Kudos