MKL03Z: I2C module: Cannot send a "start" without sending a "stop" prior

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

MKL03Z: I2C module: Cannot send a "start" without sending a "stop" prior

Jump to solution
3,331 Views
gauravbanyal
Contributor IV

I have a question on using the I2Cmodule. I am writing the driver for an I2C EEPROM and I need to do the following for performing a read operation on the EEPROM. Note that after sending the address of the byte I want to read, I have to send a start again (without a preceeding stop). This doesn’t seem to be possible in I2C module.

 read.jpg

How I am trying to achieve this is by doing two transactions on the I2C bus. First to write the “Byte addr” bytes. This I am ending without a STOP bit. The next to read the data byte.

==============

bool eeprom_read_byte(uint16_t address, uint8_t * data){

 

    //Get the I2C instance handle

    I2C_Type * i2c_handle = NULL;

                        i2c_handle = i2c_shared_init();

   

    i2c_master_transfer_t masterXfer = {

        .slaveAddress   = EEPROM_I2C_SLAVE_ADDR_7BIT,

                                                .direction      = kI2C_Write,

                                                .subaddress     = (uint32_t) address,

                                                .subaddressSize = 2,

                                                .data           = NULL,

                                                .dataSize       = 0,

                                                .flags          = kI2C_TransferNoStopFlag

                        };

   

    status_t status = I2C_MasterTransferBlocking( i2c_handle, &masterXfer );

   

                        if( kStatus_Success != status ){

                                                PRINTF(("%s[%d], %s() - I2C_MasterTransferBlocking failed: %d\r\n", __FILE__, __LINE__, __func__, status));

                                                return FAILED;

                        }

   

    masterXfer.slaveAddress   = EEPROM_I2C_SLAVE_ADDR_7BIT;

    masterXfer.direction      = kI2C_Read;

    masterXfer.subaddress     = (uint32_t) address;

    masterXfer.subaddressSize = 0;

    masterXfer.data           = data;

    masterXfer.dataSize       = 1;

    masterXfer.flags          = kI2C_TransferDefaultFlag;

 

    status = I2C_MasterTransferBlocking( i2c_handle, &masterXfer ); è This always returns error kStatus_I2C_Busy

 

    if (kStatus_Success != status){

                                                PRINTF(("%s[%d], %s() - I2C_MasterTransferBlocking failed: %d\r\n", __FILE__, __LINE__, __func__, status));

        return FAILED;

                        }

   

                        return SUCCESSFUL;

}

==============

The “kStatus_I2C_Busy” is returned from the following code inside I2C_MasterStart() function and below is the explanation of this from the reference manual.

 

    /* Return an error if the bus is already in use. */

    if (statusFlags & kI2C_BusBusyFlag)

    {

        result = kStatus_I2C_Busy;

    }

 

 rm.jpg

Please suggest me how I can achieve the I2C communication needed to perform a read operation on this I2C EEPROM.

Labels (1)
Tags (1)
1 Solution
2,682 Views
gauravbanyal
Contributor IV

It works now.

 

You don’t want to know the reason as it does not add to your knowledge. The phenomenon operating here was optical illusion. When there are pins around the ground pin, you can end up connecting a non-connected pin to ground, thinking you have connected the ground pin to ground.

Fix that and it starts to work.

 

Thanks for investigations and spending the time and your responses. I appreciate. 

But I am sorry for your wasted time.

 

Thanks,

Gaurav.

View solution in original post

0 Kudos
Reply
18 Replies
2,682 Views
bobpaddock
Senior Contributor III

Look up 'Repeated Start'.  Note that parts that have double buffered I2C has  a bug in them related to Repeated Start.
There have been several discussion here on how to work around the issue.

0 Kudos
Reply
2,682 Views
gauravbanyal
Contributor IV

Hello Bob, 

Now my understanding is that a repeated start means when a "start" is sent without a "stop" preceding it. I now think I was doing it wrong earlier. So I changed the red colored code below to "masterXfer.flags = kI2C_TransferRepeatedStartFlag". With this, I see that the read is sent on the bus. Now the problem is that no data is returned.

==========

masterXfer.slaveAddress   = EEPROM_I2C_SLAVE_ADDR_7BIT;

masterXfer.direction      = kI2C_Read;

masterXfer.subaddress     = (uint32_t) address;

masterXfer.subaddressSize = 0;

masterXfer.data           = data;

masterXfer.dataSize       = 1;

masterXfer.flags          = kI2C_TransferDefaultFlag;

status = I2C_MasterTransferBlocking( i2c_handle, &masterXfer ); // This always returns error kStatus_I2C_Busy

==========

With this change following is what I see on the scope:

IMG_5039.JPG

Could you please elaborate on the workaround or could you point me to the right discussion on the forum which talks about this case?

Thanks,

Gaurav.

0 Kudos
Reply
2,682 Views
bobpaddock
Senior Contributor III

General format for EEPROM read is:

Start
Device_Address Write

Write_EEPROM_ADDRESS_High (or low depending on the part)

Write_EEPROM_ADDRESS_Low

Repeated Start

Device_Address Read

Read/Ack

...

Read/Nack Nack indicates this is the last read.

The master still needs to generate the clocks so there needs to be more than one read.

0 Kudos
Reply
2,682 Views
mjbcswitzerland
Specialist V

Hi

See the appendix of http://www.utasker.com/docs/uTasker/uTasker_I2C.pdf for details about the issue and the way to work around it.
If you would like an immediate and complete solution proven in many industrial products using double-buffered I2C Kinetis parts just use the uTasker Open Source project (link below) which also simulates your chip and the I2C operation.


Regards

Mark

http://www.utasker.com/kinetis.html
http://www.utasker.com/kinetis/FRDM-KL03Z.html

0 Kudos
Reply
2,682 Views
gauravbanyal
Contributor IV

Hello Mark,

I figure out from the Appendix you shared that the typical issue is that the i2c master, after sending the repeated start sends a wrong slave address. But this doesn't seem to be happening in my case. Here it seems to be that I am able to read but the slave is not returning the right information.

In this, I write 0xAA at address 0x0004 and then try to read address 0x0004. What do you think could be wrong here? Do you think its the double buffering bug? how?

I2C.jpeg

Cheers,

Gaurav.

0 Kudos
Reply
2,682 Views
mjbcswitzerland
Specialist V

Hi

I am not sure whether this is a chip issue, driver issue or application issue yet but it looks like your write doesn't correspond to what you display in the initial post. There you show that you want
W50, 0, 4, W50, AA
but your oscilloscope is displaying W50, 0, 4, AA, which is different because the slave is never being addressed for the data write (the second W50 is missing).
In this case it may be normal that the read is a 0xff since you haven't written anything yet.

If you intended to send the second W50 between the 4 and the AA if could be the chip bug where the second start address is lost (as noted in the appendix of the uTasker I2C document).

Regards

Mark

0 Kudos
Reply
2,682 Views
software
Contributor I

Hi

I am using I2C for communicate with my RTC device. I am transferring the data of 0x90(write mode) , 0x3F(resister address) , 0x02(data). Again I am writing 0x90(write mode) , 0x3F(resister address) , 0x06(data) as per data sheet we have write two data bytes. 

Now I am reading from that device(RTC) by writing data 0x90(write mode),0x30(register to read),repeat start,0x91(read mode). But i am getting data as 0xFF only.

where as this code is working when I am for MK60 but not working with MK66.

Can I know the reason.  

0 Kudos
Reply
2,682 Views
gauravbanyal
Contributor IV

This is because the write to this chip is a bit different. It does not need a repeated start.

write.JPG

The EEPROM datasheet I am referring to is this one:

datasheet.JPG

0 Kudos
Reply
2,682 Views
bobpaddock
Senior Contributor III

Section 5.2.1 of the data sheet does indicate that Repeated Start is used, it just doesn't call it that in that paragraph.

2,682 Views
mjbcswitzerland
Specialist V

Hi

Section 5.1 "Write operations":

When the bus master generates a Stop condition immediately after a data byte Ack bit (in
the “10th bit” time slot), either at the end of a Byte Write or a Page Write, the internal Write
cycle tW is triggered. A Stop condition at any other time slot does not trigger the internal
Write cycle.
A repeated start will presumably effectively cancel a write before it starts.
Also, the user's manual discusses how to poll for the write to complete in 5.1.6.
I also agree that, from 5.2.1, a repeated start is required (must be used) when reading.
From 5.1.1. the write address plus the data should be written in one single I2C frame. It doesn't state that it won't work if a repeated start is used but it is not the method that is explained and possibly will fail. Sending as two write frames looks to be incorrect since the second one's data will presumably be understood as a part of a new address and not as data.
Therefore it looks like the present problem is at the application level where there are one or more errors as it is being performed at the moment.
Regards
Mark
0 Kudos
Reply
2,683 Views
gauravbanyal
Contributor IV

It works now.

 

You don’t want to know the reason as it does not add to your knowledge. The phenomenon operating here was optical illusion. When there are pins around the ground pin, you can end up connecting a non-connected pin to ground, thinking you have connected the ground pin to ground.

Fix that and it starts to work.

 

Thanks for investigations and spending the time and your responses. I appreciate. 

But I am sorry for your wasted time.

 

Thanks,

Gaurav.

0 Kudos
Reply
2,680 Views
mjbcswitzerland
Specialist V

Hi

In that case the I2C bus looks correct and you are not using repeated-starts, which means you may not be affected by the chip's bugs.

If the oscilloscope shows the I2C activity correctly being coded it may be that you have write protection on the EEPROM stopping it changing its memory, which wouldn't be a I2C issue.

Regards

Mark

0 Kudos
Reply
2,682 Views
gauravbanyal
Contributor IV

This one too I have ruled out as a possibility:

"If the addressed location is Write-protected, by Write Control (WC) being driven high, the
device replies with NoAck, and the location is not modified. If, instead, the addressed
location is not Write-protected, the device replies with Ack."

There is something else which is just escaping my eyes/mind.

0 Kudos
Reply
2,682 Views
mjbcswitzerland
Specialist V

Hi

The oscilloscope is showing correct operation on the bus but the slave is responding with 0xff.


In this case the question is whether you can believe the oscilloscope's interpretation - I would look at the SDA/SCL signals directly to check the start, stop, ack, nack, timing etc. If all is correct it is not a I2C driver/chip issue but something at the slave.

Regards

Mark

0 Kudos
Reply
2,682 Views
gauravbanyal
Contributor IV

I am also printing the value that I read from the slave on my UART terminal. it is 0xFF.

BTW I am using repeated-start for the read. With that in mid, do you think what I see on the scope is correct in the sense that the issue that you know of, which is described in you uTasker documentation is not present here in the read?

0 Kudos
Reply
2,682 Views
mjbcswitzerland
Specialist V

Hi

Maybe the EEPROM requîres a STOP condition to start writing the data (meaning a repeated start after the write could be wrong)?
Also, after you have written something to an EEPROM it may take several ms before it has been programmed - usually one polls its status register until it shows that it is no longer busy before reading.
I don't see I2S bus problems at the moment and the application is more likely to be the issue.

Regards

Mark

0 Kudos
Reply
2,682 Views
gauravbanyal
Contributor IV

Hi Mark,

Thanks for this information. So my understanding is that this is a bug in the microcontroller's I2C module.

I have to admit that I don't completely understand the cause and hence don't know how to handle it. It seems that I have to either integrate uTasker in my project which would be quite risky to do at this stage or do a manual workaround in the SDK which I don't prefer doing.

If you or NXP can send me changed and validated SDK files for the I2C driver (fsl_i2c.c) with this workaround implemented, it will be much helpful. 

Best regards,

Gaurav.

0 Kudos
Reply
2,682 Views
mjbcswitzerland
Specialist V

Hi

You will need to contact NXP since I don't work with the SDK. In case of emergencies I can correct code and validate operation but this will need a contact which can be arranged at http://www.utasker.com/services.html

Regards

Mark

0 Kudos
Reply