Discussion:
STM32F4 vs. I2C - mystery timeouts
(too old to reply)
Mike Smith
2012-02-20 07:37:07 UTC
Permalink
I'm trying to get a handle on an issue I'm seeing where, on an STM32F4 configured:

CONFIG_I2C=y
CONFIG_I2C_POLLED=n
CONFIG_I2C_TRANSFER=y
CONFIG_I2C_TRACE=y
CONFIG_DEBUG_I2C=y
CONFIG_I2CTOOL_BUILTIN=y

A simple I2C register read:

nsh> i2c get -r 0a
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
0. STATUS: 00030001 COUNT: 1 EVENT: 6 PARM: 00000000
1. STATUS: 00070082 COUNT: 2 EVENT: 7 PARM: 00000000
2. STATUS: 00070084 COUNT: 3 EVENT: 8 PARM: 00000001
3. STATUS: 00030001 COUNT: 4 EVENT: 6 PARM: 00000000
4. STATUS: 00030002 COUNT: 5 EVENT: 6 PARM: 00000000
5. STATUS: 00030040 COUNT: 6 EVENT: 7 PARM: 00000000
i2ctool: get: Transfer failed: 16

is failing.

The actual transaction on the bus looks perfect, right down to the NACK that terminates the read.

Switching interrupt-driven mode for polled mode doesn't change the result, though the trace log is a bit more comprehensive:

nsh> i2c get -r 0a
stm32_i2c_sem_waitdone: intstate: 1 elapsed: 500 threshold: 500 status: 00030000
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
0. STATUS: 00000000 COUNT: 1 EVENT: 0 PARM: 00000000
1. STATUS: 00020000 COUNT: 5 EVENT: 0 PARM: 00000000
2. STATUS: 00030000 COUNT: 7 EVENT: 0 PARM: 00000000
3. STATUS: 00030001 COUNT: 8 EVENT: 1 PARM: 00000002
4. STATUS: 00030000 COUNT: 9 EVENT: 0 PARM: 00000000
5. STATUS: 00070000 COUNT: 53 EVENT: 0 PARM: 00000000
6. STATUS: 00070082 COUNT: 54 EVENT: 2 PARM: 0000000a
7. STATUS: 00070080 COUNT: 55 EVENT: 3 PARM: ffffffdb
8. STATUS: 00070084 COUNT: 93 EVENT: 8 PARM: 00000001
9. STATUS: 00070080 COUNT: 94 EVENT: 3 PARM: ffffffd8
10. STATUS: 00030080 COUNT: 96 EVENT: 3 PARM: ffffffd7
11. STATUS: 00030000 COUNT: 97 EVENT: 0 PARM: 00000000
12. STATUS: 00030001 COUNT: 99 EVENT: 1 PARM: 00000001
13. STATUS: 00030000 COUNT: 100 EVENT: 0 PARM: 00000000
14. STATUS: 00030002 COUNT: 145 EVENT: 0 PARM: 00000000
15. STATUS: 00030000 COUNT: 146 EVENT: 0 PARM: 00000000
16. STATUS: 00030040 COUNT: 191 EVENT: 5 PARM: 00000001
17. STATUS: 00030000 COUNT: 192 EVENT: 0 PARM: 00000000
i2ctool: get: Transfer failed: 16


Any suggestions would be appreciated…

= Mike



------------------------------------

Yahoo! Groups Links

<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/nuttx/

<*> Your email settings:
Individual Email | Traditional

<*> To change settings online go to:
http://groups.yahoo.com/group/nuttx/join
(Yahoo! ID required)

<*> To change settings via email:
nuttx-digest-***@public.gmane.org
nuttx-fullfeatured-***@public.gmane.org

<*> To unsubscribe from this group, send an email to:
nuttx-unsubscribe-***@public.gmane.org

<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
Gregory Nutt
2012-02-20 13:12:43 UTC
Permalink
Hi, Mike,

First notice that the process times out without completing the transfer:

  > stm32_i2c_process: Timed out: CR1: 0001 status: 00030000

This comes from arch/arm/src/stm32/ stm32_i2c.c:

 /* Wait for an ISR, if there was a timeout, fetch latest status to get
   * the BUSY flag.
   */

  if (stm32_i2c_sem_waitdone(priv) < 0)
    {
      status = stm32_i2c_getstatus(priv);
      errval = ETIMEDOUT;

      i2cdbg("Timed out: CR1: %04x status: %08x\n",
             stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET), status);

      /* "Note: When the STOP, START or PEC bit is set, the software must
       *  not perform any write access to I2C_CR1 before this bit is
       *  cleared by hardware. Otherwise there is a risk of setting a
       *  second STOP, START or PEC request."
       */

      stm32_i2c_clrstart(priv);
    }
  else
    {
      /* clear SR2 (BUSY flag) as we've done successfully */

      status = priv->status & 0xffff;
    }

Then you get this error:

  > i2ctool: get: Transfer failed: 16

  #define EBUSY               16
  #define EBUSY_STR           "Device or resource busy"


The only place that EBUSY is reported is in arch/arm/src/stm32/ stm32_i2c.c. After the I2C transfer is complete, the device continues to appear busy:

  /* This is not an error, but should not happen.  The BUSY signal can hang,
   * however, if there are unhealthy devices on the bus that need to be reset.
   * NOTE:  We will only see this busy indication if stm32_i2c_sem_waitdone()
   * fails above;  Otherwise it is cleared.
   */

  else if ((status & (I2C_SR2_BUSY << 16)) != 0)
    {
      /* I2C Bus is for some reason busy */

      errval = EBUSY;
    }


But I think that the root cause of the problem is the timeout.  The interrupt handler does not believe that the transfer is complete.  It does not wake up the process and it finally times and is still busy.

Greg

PS.  Unless you have strong motivation to use interrupts I would not.  The polled version is much faster.  You can use less CPU bandwidth by polling rather than by taking all of the interrupts.  I2C is too fast to be interrupt driven (unless your I2C clock is very low I suppose).



________________________________
From: Mike Smith <drziplok-***@public.gmane.org>
To: nuttx-***@public.gmane.org
Sent: Monday, February 20, 2012 1:37 AM
Subject: [nuttx] STM32F4 vs. I2C - mystery timeouts


I'm trying to get a handle on an issue I'm seeing where, on an STM32F4 configured:

CONFIG_I2C=y
CONFIG_I2C_POLLED=n
CONFIG_I2C_TRANSFER=y
CONFIG_I2C_TRACE=y
CONFIG_DEBUG_I2C=y
CONFIG_I2CTOOL_BUILTIN=y

A simple I2C register read:

nsh> i2c get -r 0a
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
0. STATUS: 00030001 COUNT:  1 EVENT:  6 PARM: 00000000
1. STATUS: 00070082 COUNT:  2 EVENT:  7 PARM: 00000000
2. STATUS: 00070084 COUNT:  3 EVENT:  8 PARM: 00000001
3. STATUS: 00030001 COUNT:  4 EVENT:  6 PARM: 00000000
4. STATUS: 00030002 COUNT:  5 EVENT:  6 PARM: 00000000
5. STATUS: 00030040 COUNT:  6 EVENT:  7 PARM: 00000000
i2ctool: get: Transfer failed: 16

is failing.

The actual transaction on the bus looks perfect, right down to the NACK that terminates the read.

Switching interrupt-driven mode for polled mode doesn't change the result, though the trace log is a bit more comprehensive:

nsh> i2c get -r 0a
stm32_i2c_sem_waitdone: intstate: 1 elapsed: 500 threshold: 500 status: 00030000
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
0. STATUS: 00000000 COUNT:  1 EVENT:  0 PARM: 00000000
1. STATUS: 00020000 COUNT:  5 EVENT:  0 PARM: 00000000
2. STATUS: 00030000 COUNT:  7 EVENT:  0 PARM: 00000000
3. STATUS: 00030001 COUNT:  8 EVENT:  1 PARM: 00000002
4. STATUS: 00030000 COUNT:  9 EVENT:  0 PARM: 00000000
5. STATUS: 00070000 COUNT:  53 EVENT:  0 PARM: 00000000
6. STATUS: 00070082 COUNT:  54 EVENT:  2 PARM: 0000000a
7. STATUS: 00070080 COUNT:  55 EVENT:  3 PARM: ffffffdb
8. STATUS: 00070084 COUNT:  93 EVENT:  8 PARM: 00000001
9. STATUS: 00070080 COUNT:  94 EVENT:  3 PARM: ffffffd8
10. STATUS: 00030080 COUNT:  96 EVENT:  3 PARM: ffffffd7
11. STATUS: 00030000 COUNT:  97 EVENT:  0 PARM: 00000000
12. STATUS: 00030001 COUNT:  99 EVENT:  1 PARM: 00000001
13. STATUS: 00030000 COUNT: 100 EVENT:  0 PARM: 00000000
14. STATUS: 00030002 COUNT: 145 EVENT:  0 PARM: 00000000
15. STATUS: 00030000 COUNT: 146 EVENT:  0 PARM: 00000000
16. STATUS: 00030040 COUNT: 191 EVENT:  5 PARM: 00000001
17. STATUS: 00030000 COUNT: 192 EVENT:  0 PARM: 00000000
i2ctool: get: Transfer failed: 16


Any suggestions would be appreciated


= Mike



------------------------------------

Yahoo! Groups Links



    http://docs.yahoo.com/info/terms/
Gregory N
2012-02-20 14:22:32 UTC
Permalink
Post by Mike Smith
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
But I suppose you already knew that. You would probably like to know why the transaction timed out. I don't know the answer because I don't know what you asked the I2C driver to do. Most likely you are asking the I2c driver to do something that the device can't support and the device is behaving badly.

Here is what I see in the trace (the version without interrupts which seems very different from the interrupt driven version):

1. Start/Master mode. Send address (I2CEVENT_SB == event 1, message count == 2)
2. Address sent, send data. Probably a register address (I2CEVENT_SENDBYTE == event 2, byte count == 10)
3. Read data, probably register contents (I2CEVENT_READ == event 3, byte count = -0x25???)
4. Repeated start needed in some transfers (I2CEVENT_BTFSTART == event 8, message count = 1)
5. Read data, (I2CEVENT_READ == event 3, byte count = -0x28???)
6. Read data, (I2CEVENT_READ == event 3, byte count = -0x29???)
7. Then the repeated start condition (I2CEVENT_SB == event 1, message count = 1)
8. I2CEVENT_RXNE == event 5

It looks like you are reading 8-bits from a register then trying to read more bytes. That seems odd.

Also, there is a repeated start but data is received from the device before the start is acknowledged. That is also odd.

Some of the reported byte counts look bad too. I have no idea what is going on and I might have made some errors in interpreting the I2C trace, but maybe this is enough to help you do the analysis.

Greg
Mike Smith
2012-02-20 18:00:34 UTC
Permalink
Post by Mike Smith
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
But I suppose you already knew that. You would probably like to know why the transaction timed out. I don't know the answer because I don't know what you asked the I2C driver to do. Most likely you are asking the I2c driver to do something that the device can't support and the device is behaving badly.
In all cases, I'm using the i2c tool in apps/system/i2c, asking it to perform a register read from register 10:

nsh> i2c get -r 0a

Is this expected to work?

Looking at the bus with an analyser the signals look perfect for a register read, right down to the data:



(apologies if the attachment here is stripped or lost - it's a small PNG with the analyser waveforms).
1. Start/Master mode. Send address (I2CEVENT_SB == event 1, message count == 2)
2. Address sent, send data. Probably a register address (I2CEVENT_SENDBYTE == event 2, byte count == 10)
3. Read data, probably register contents (I2CEVENT_READ == event 3, byte count = -0x25???)
4. Repeated start needed in some transfers (I2CEVENT_BTFSTART == event 8, message count = 1)
5. Read data, (I2CEVENT_READ == event 3, byte count = -0x28???)
6. Read data, (I2CEVENT_READ == event 3, byte count = -0x29???)
7. Then the repeated start condition (I2CEVENT_SB == event 1, message count = 1)
8. I2CEVENT_RXNE == event 5
It looks like you are reading 8-bits from a register then trying to read more bytes. That seems odd.
Also, there is a repeated start but data is received from the device before the start is acknowledged. That is also odd.
Some of the reported byte counts look bad too. I have no idea what is going on and I might have made some errors in interpreting the I2C trace, but maybe this is enough to help you do the analysis.
It doesn't line up terribly well with either what I think the code is doing, or the trace. Is there a guide to the trace output, or should I just be digging through the code?

= Mike
Gregory N
2012-02-21 12:59:27 UTC
Permalink
Post by Mike Smith
nsh> i2c get -r 0a
Is this expected to work?
Not necessarily, the I2C will try to generate whatever you ask it to (data width, restarts, etc.). But not all combinations will work with all device.
But what is causing the hang is what is missing. What is missing is the STOP indication. From the driver's point of view, the last byte of data was never received and so the STOP condition was never sent and the transaction never terminated. This might be an error in the byte count (the values looked funny to me in your original ouput) or it might be just the protocol... perhaps the device will not send the next byte of data?

Greg
Michael Smith
2012-02-21 18:08:16 UTC
Permalink
Post by Mike Smith
nsh> i2c get -r 0a
Is this expected to work?
Not necessarily, the I2C will try to generate whatever you ask it to (data width, restarts, etc.). But not all combinations will work with all device.
Let me be more specific then; when configured to perform an 8 bit read from a bus/device/register triple known to be valid, and having observed a correct waveform on the I2C bus for that read, is it expected that the command complete successfully?
But what is causing the hang is what is missing. What is missing is the STOP indication. From the driver's point of view, the last byte of data was never received and so the STOP condition was never sent and the transaction never terminated. This might be an error in the byte count (the values looked funny to me in your original ouput) or it might be just the protocol... perhaps the device will not send the next byte of data?
It's normal for the master to terminate reads with NACK rather than STOP, as it forces the slave off the bus rather than risking the bus becoming stuck in the case where the slave thinks that the master is going to read more data (see the F4 reference manual, I2C/Master Receiver/Closing the communication).

The NACK is, however as far as I can tell, generated by the hardware as a consequence of successfully receiving a byte. What seems to be missing is the driver noticing that the last byte was transferred. Since this is "normal" for I2C reads, I was hoping that I'd just done something wrong with my configuration that might be causing this to be missed. It is the only phase where data is read from, rather than written to, the I2C controller in this example.

= Mike
avrbasic
2012-03-13 13:14:04 UTC
Permalink
Post by Michael Smith
Post by Mike Smith
nsh> i2c get -r 0a
Is this expected to work?
Not necessarily, the I2C will try to generate whatever you ask it to (data width, restarts, etc.). But not all combinations will work with all device.
Let me be more specific then; when configured to perform an 8 bit read from a bus/device/register triple known to be valid, and having observed a correct waveform on the I2C bus for that read, is it expected that the command complete successfully?
But what is causing the hang is what is missing. What is missing is the STOP indication. From the driver's point of view, the last byte of data was never received and so the STOP condition was never sent and the transaction never terminated. This might be an error in the byte count (the values looked funny to me in your original ouput) or it might be just the protocol... perhaps the device will not send the next byte of data?
It's normal for the master to terminate reads with NACK rather than STOP, as it forces the slave off the bus rather than risking the bus becoming stuck in the case where the slave thinks that the master is going to read more data (see the F4 reference manual, I2C/Master Receiver/Closing the communication).
The NACK is, however as far as I can tell, generated by the hardware as a consequence of successfully receiving a byte. What seems to be missing is the driver noticing that the last byte was transferred. Since this is "normal" for I2C reads, I was hoping that I'd just done something wrong with my configuration that might be causing this to be missed. It is the only phase where data is read from, rather than written to, the I2C controller in this example.
= Mike
Hi Mike we are seeing same thing: we have I2C eeprom on the bus
when doing

i2c dev -b1 0 7F

the dump goes fast til 50 (A0) then the timeouts happen..
and then it goes over quick again

we think that AS SOON as the slave on the bus responds, then
timeout comes, and the device is not detected..

Antti
lm_eth
2012-03-20 21:43:03 UTC
Permalink
I have a workaround for this issue - if this is still the case for you, I can dig up the code. It's a small change.

It enables only write-reads and writes though and is not a permanent / good solution. We didn't have the time yet to finish investigating this.
Post by avrbasic
Post by Michael Smith
Post by Mike Smith
nsh> i2c get -r 0a
Is this expected to work?
Not necessarily, the I2C will try to generate whatever you ask it to (data width, restarts, etc.). But not all combinations will work with all device.
Let me be more specific then; when configured to perform an 8 bit read from a bus/device/register triple known to be valid, and having observed a correct waveform on the I2C bus for that read, is it expected that the command complete successfully?
But what is causing the hang is what is missing. What is missing is the STOP indication. From the driver's point of view, the last byte of data was never received and so the STOP condition was never sent and the transaction never terminated. This might be an error in the byte count (the values looked funny to me in your original ouput) or it might be just the protocol... perhaps the device will not send the next byte of data?
It's normal for the master to terminate reads with NACK rather than STOP, as it forces the slave off the bus rather than risking the bus becoming stuck in the case where the slave thinks that the master is going to read more data (see the F4 reference manual, I2C/Master Receiver/Closing the communication).
The NACK is, however as far as I can tell, generated by the hardware as a consequence of successfully receiving a byte. What seems to be missing is the driver noticing that the last byte was transferred. Since this is "normal" for I2C reads, I was hoping that I'd just done something wrong with my configuration that might be causing this to be missed. It is the only phase where data is read from, rather than written to, the I2C controller in this example.
= Mike
Hi Mike we are seeing same thing: we have I2C eeprom on the bus
when doing
i2c dev -b1 0 7F
the dump goes fast til 50 (A0) then the timeouts happen..
and then it goes over quick again
we think that AS SOON as the slave on the bus responds, then
timeout comes, and the device is not detected..
Antti
Gregory N
2012-03-20 22:33:08 UTC
Permalink
Hi, Lorenz,
Post by lm_eth
I have a workaround for this issue - if this is still the case for you, I can dig up the code. It's a small change.
It enables only write-reads and writes though and is not a permanent / good solution. We didn't have the time yet to finish investigating this.
We are just now, today, starting to look at this. If you can give us what you have found it would save us some time and would be much appreciated.

Greg
Michael Smith
2012-03-21 05:37:49 UTC
Permalink
Greg,

Attached is, I believe, the patch that Lorenz is referring to from our working tree.

= Mike
Post by lm_eth
I have a workaround for this issue - if this is still the case for you, I can dig up the code. It's a small change.
It enables only write-reads and writes though and is not a permanent / good solution. We didn't have the time yet to finish investigating this.
Post by avrbasic
Post by Michael Smith
Post by Mike Smith
nsh> i2c get -r 0a
Is this expected to work?
Not necessarily, the I2C will try to generate whatever you ask it to (data width, restarts, etc.). But not all combinations will work with all device.
Let me be more specific then; when configured to perform an 8 bit read from a bus/device/register triple known to be valid, and having observed a correct waveform on the I2C bus for that read, is it expected that the command complete successfully?
But what is causing the hang is what is missing. What is missing is the STOP indication. From the driver's point of view, the last byte of data was never received and so the STOP condition was never sent and the transaction never terminated. This might be an error in the byte count (the values looked funny to me in your original ouput) or it might be just the protocol... perhaps the device will not send the next byte of data?
It's normal for the master to terminate reads with NACK rather than STOP, as it forces the slave off the bus rather than risking the bus becoming stuck in the case where the slave thinks that the master is going to read more data (see the F4 reference manual, I2C/Master Receiver/Closing the communication).
The NACK is, however as far as I can tell, generated by the hardware as a consequence of successfully receiving a byte. What seems to be missing is the driver noticing that the last byte was transferred. Since this is "normal" for I2C reads, I was hoping that I'd just done something wrong with my configuration that might be causing this to be missed. It is the only phase where data is read from, rather than written to, the I2C controller in this example.
= Mike
Hi Mike we are seeing same thing: we have I2C eeprom on the bus
when doing
i2c dev -b1 0 7F
the dump goes fast til 50 (A0) then the timeouts happen..
and then it goes over quick again
we think that AS SOON as the slave on the bus responds, then
timeout comes, and the device is not detected..
Antti
avrbasic
2012-03-21 10:14:13 UTC
Permalink
Post by Michael Smith
Greg,
Attached is, I believe, the patch that Lorenz is referring to from our working tree.
= Mike
the patch works only partially :(

1) if i2c trace and debug are DISABLED then the patch not works at all, no change of behaviour.. same as before, as soon i2c device is found during scan, long time comeouts..

2) if trace/debug enabled then scan DOES see the i2c device on the bus
but for some reason during scan first address was not seen

I have 2408 style eeprom that should respond on 8 addresses,
A0 (50)..

first was missing, 51..57 got scan ok results

Antti
Gregory N
2012-03-21 13:18:02 UTC
Permalink
Thanks, all,

Diego Sanchez is looking at the problem here and we will find a solution. I am concerned that (1) we need to understand the root cause of the problem. If we do not understand the root cause, then we cannot possibly put in the correct fix.

And (2) this driver works great on the F1. It has been tested and used a lot with many different devices. According to the documentation, there is no change in the I2C IP from F1 to F2 and the registers are identical bit-for-bit. So I am puzzled by what is different on F4 that causes the problem. Also, I am concerned about breaking F1 with F4 changes; the F1 I2C must stay stable stable.

I think that the only way to correct this is to first understand the root cause ... the fundamental difference between F1 and F4 that introduces the failure in the identical I2C on F4. I think one of the first things we need to do is to compare the I2C trace from an F1 with the I2C trace from an F4. Once we understand that difference, then I believe that we should be able to put in the correct fix.

Thanks for the patches. While it doesn't sound they can just be dropped in, I am sure that they are are a starting point that will help Diego a lot.

Greg
Post by avrbasic
Post by Michael Smith
Greg,
Attached is, I believe, the patch that Lorenz is referring to from our working tree.
= Mike
the patch works only partially :(
1) if i2c trace and debug are DISABLED then the patch not works at all, no change of behaviour.. same as before, as soon i2c device is found during scan, long time comeouts..
2) if trace/debug enabled then scan DOES see the i2c device on the bus
but for some reason during scan first address was not seen
I have 2408 style eeprom that should respond on 8 addresses,
A0 (50)..
first was missing, 51..57 got scan ok results
Antti
avrbasic
2012-03-21 17:26:31 UTC
Permalink
Post by Gregory N
Thanks, all,
Diego Sanchez is looking at the problem here and we will find a solution. I am concerned that (1) we need to understand the root
hi

and agree, well why we do not have F1xx devices that we need support
well we understand that the old code should remain working, if it
works now. There seems to be something funky with F4xxx

We are also trying out i2c with

1) STM32F4Discovery demo code, this code is supposedly working
on F4 disco - so far it DOES NOT WORK in our lab!

2) .NET MF 4.2 i2c - again, the hardware i2c code DOES NOT work
and what is much more interesting, when trying confirmed ready
and working SOFTWARE BIT BANG .NET C# code it does generate
timeout excpetions!! I mean SOFT BIT BANG routines ALSO get
similar errors, pretty much like nuttx i2c scan is seeing

we have high LA and stuff in the lab so we can troubleshoot
all kind of timing errors, etc, but this seems to be some
yes maybe undocu errata? Well the problem with soft i2c
makes the issue more interesting.

Probably the best is that i write new from scratch bit bang
code and test that, it MUST WORK, it always does...

so far please post your finding, so we can nail the root problem
hopefully some day soon

Antti
Gregory N
2012-03-21 17:56:52 UTC
Permalink
Hi, Antti,
Post by avrbasic
we have high LA and stuff in the lab so we can troubleshoot
all kind of timing errors, etc, but this seems to be some
yes maybe undocu errata? Well the problem with soft i2c
makes the issue more interesting.
It has been a lot time since I looked at, but my recollection is that everything worked with STM3240G-EVAL demo code. I have not done a line-for-line comparison of the F4 and F1 sample I2C code from STMicro, but I suspect they are the same.

My suspicions are either (1) there is some race condition that is not handled correctly by the NuttX I2C driver. This is contributed code and does not derive from the STMicro I2C driver. The state machine looks very different.

Or, (2) there is something different in the I2C setup. One very big different is, of course, frequency.

Greg
Gregory N
2012-03-28 22:12:33 UTC
Permalink
Antti/Mike/Lorenzo,

I have the STM32 F4 I2C driver running without errors now. But I am not certain that it is really working -- a LOT more testing is needed. I have checked in a candidate fix for the STM32 F4 I2C driver. The root cause of the problem seems to be a slight difference in behavior of the I2C block from F1 to F2.

Here are the excruciating details:

In F1, completion all byte transmissions are signal by the I2C SR1 BTF (byte transfer finished) bit. This is the behavior stated in the Reference (F4) Manual. BTF should be set by hardware:

–In reception when a new byte is received (including ACK pulse) and DR has not been read yet (RxNE=1).
–In transmission when a new byte should be sent and DR has not been written yet (TxE=1)

Se when you transmit a byte you should get TxE+BTF. When you receive a byte, you should get RxNE+BTF. But what I am actually seeing in the F4 hardware is that when RxNE is set, BTF is not set. The logic in the driver relied on BTF to terminate the transfer so that the driver hangs and eventually times out.

The fix I have in now is simply to use RXNE as a terminating conditions as well. Like:

+ /* Was last byte received or sent? Hmmm... the F4 seems to differ from
+ * the F1 in that BTF is not set after data is received (only RXNE).
+ */

+#ifdef CONFIG_STM32_STM32F40XX
+ if (priv->dcnt <= 0 && (status & (I2C_SR1_BTF|I2C_SR1_RXNE)) != 0)
+#else
if (priv->dcnt <= 0 && (status & I2C_SR1_BTF) != 0)
+#endif
{
...
}

I am just testing with the I2C tools so although no errors are reported, I am not certain that the driver is "really" working. Can one of you retest on some real hardware and see if it is returning real data?

Thanks... and in the meaning we will continue with some testing here.

Greg
Michael Smith
2012-03-28 22:25:32 UTC
Permalink
Greg,

Thanks for looking at this. Either Lorenz or I will pull your change in and give it a good workout in the next day or so.

= Mike
Post by Gregory N
Antti/Mike/Lorenzo,
I have the STM32 F4 I2C driver running without errors now. But I am not certain that it is really working -- a LOT more testing is needed. I have checked in a candidate fix for the STM32 F4 I2C driver. The root cause of the problem seems to be a slight difference in behavior of the I2C block from F1 to F2.
–In reception when a new byte is received (including ACK pulse) and DR has not been read yet (RxNE=1).
–In transmission when a new byte should be sent and DR has not been written yet (TxE=1)
Se when you transmit a byte you should get TxE+BTF. When you receive a byte, you should get RxNE+BTF. But what I am actually seeing in the F4 hardware is that when RxNE is set, BTF is not set. The logic in the driver relied on BTF to terminate the transfer so that the driver hangs and eventually times out.
+ /* Was last byte received or sent? Hmmm... the F4 seems to differ from
+ * the F1 in that BTF is not set after data is received (only RXNE).
+ */
+#ifdef CONFIG_STM32_STM32F40XX
+ if (priv->dcnt <= 0 && (status & (I2C_SR1_BTF|I2C_SR1_RXNE)) != 0)
+#else
if (priv->dcnt <= 0 && (status & I2C_SR1_BTF) != 0)
+#endif
{
...
}
I am just testing with the I2C tools so although no errors are reported, I am not certain that the driver is "really" working. Can one of you retest on some real hardware and see if it is returning real data?
Thanks... and in the meaning we will continue with some testing here.
Greg
avrbasic
2012-03-29 15:14:51 UTC
Permalink
well it doesnt seem to work
maybe i applied the patch badly, but after testing

I SOMETIMES get response detected on addresses 50,51 A0,A2
but the device actually replies 50..57, so the last 6 are always not
seen, and the first 2 addresses also respond like at random

so there is a major issue somewhere
but maybe better someone also confirms the behaviour
maybe i messed up something

antti
Post by Michael Smith
Greg,
Thanks for looking at this. Either Lorenz or I will pull your change in and give it a good workout in the next day or so.
= Mike
Post by Gregory N
Antti/Mike/Lorenzo,
I have the STM32 F4 I2C driver running without errors now. But I am not certain that it is really working -- a LOT more testing is needed. I have checked in a candidate fix for the STM32 F4 I2C driver. The root cause of the problem seems to be a slight difference in behavior of the I2C block from F1 to F2.
–In reception when a new byte is received (including ACK pulse) and DR has not been read yet (RxNE=1).
–In transmission when a new byte should be sent and DR has not been written yet (TxE=1)
Se when you transmit a byte you should get TxE+BTF. When you receive a byte, you should get RxNE+BTF. But what I am actually seeing in the F4 hardware is that when RxNE is set, BTF is not set. The logic in the driver relied on BTF to terminate the transfer so that the driver hangs and eventually times out.
+ /* Was last byte received or sent? Hmmm... the F4 seems to differ from
+ * the F1 in that BTF is not set after data is received (only RXNE).
+ */
+#ifdef CONFIG_STM32_STM32F40XX
+ if (priv->dcnt <= 0 && (status & (I2C_SR1_BTF|I2C_SR1_RXNE)) != 0)
+#else
if (priv->dcnt <= 0 && (status & I2C_SR1_BTF) != 0)
+#endif
{
...
}
I am just testing with the I2C tools so although no errors are reported, I am not certain that the driver is "really" working. Can one of you retest on some real hardware and see if it is returning real data?
Thanks... and in the meaning we will continue with some testing here.
Greg
Gregory N
2012-03-29 16:20:41 UTC
Permalink
Post by avrbasic
well it doesnt seem to work
maybe i applied the patch badly, ...
That little patch was just to show the nature of the final fix. I am not sure that that is everything you need. But there might be other changes that are required as well. I recommend that you get the whole stm32_i2c.c file from SVN.

Also, the I2C tool is not guaranteed to work with all devices anyway. It just sends a garbage command to the I2C device and if it gets a valid response it says that the device exists. But there could be more to talking to the device than that.

You should use i2c get with the right settings to confirm or disconfirm the driver.
avrbasic
2012-03-29 17:45:09 UTC
Permalink
Hi

i disagree a bit here, ANY i2c SCAN tool can work, and MUST show proper
scan result on all valid devices that ACK the bus, no exceptions.

it doesn't matter what devices are on bus, they must ACK dev addess byte

i have microchip 24c04 device as scan test, for sure it works 100% ok
but the nutty i2c tools return random scans, sometimes none, sometimes
partial addresses seen, and as before there is long timeout when the
device acks, but let me try with svn checkout

Antti
Post by Gregory N
Post by avrbasic
well it doesnt seem to work
maybe i applied the patch badly, ...
That little patch was just to show the nature of the final fix. I am not sure that that is everything you need. But there might be other changes that are required as well. I recommend that you get the whole stm32_i2c.c file from SVN.
Also, the I2C tool is not guaranteed to work with all devices anyway. It just sends a garbage command to the I2C device and if it gets a valid response it says that the device exists. But there could be more to talking to the device than that.
You should use i2c get with the right settings to confirm or disconfirm the driver.
avrbasic
2012-03-21 10:19:16 UTC
Permalink
Post by Michael Smith
Greg,
Attached is, I believe, the patch that Lorenz is referring to from our working tree.
= Mike
more comments, DEBUG ON mode

scan 50..57 gets found 50..57
scan say 40..60 finds only 51..57

read registers fails no matter what address used

Antti
dsancheznuttx
2012-03-21 21:21:50 UTC
Permalink
This is the trace of the i2c tool running on the F1 board

nsh> i2c set -a 48 A
0. STATUS: 00000000 COUNT: 1 EVENT: 0 PARM: 00000000
1. STATUS: 00020000 COUNT: 9 EVENT: 0 PARM: 00000000
2. STATUS: 00030001 COUNT: 13 EVENT: 1 PARM: 00000002
3. STATUS: 00030000 COUNT: 14 EVENT: 0 PARM: 00000000
4. STATUS: 00070082 COUNT: 84 EVENT: 2 PARM: 00000000
5. STATUS: 00070080 COUNT: 85 EVENT: 3 PARM: ffffffc5
6. STATUS: 00070084 COUNT: 145 EVENT: 8 PARM: 00000001
7. STATUS: 00070080 COUNT: 146 EVENT: 3 PARM: ffffffbe
8. STATUS: 00030000 COUNT: 152 EVENT: 0 PARM: 00000000
9. STATUS: 00030001 COUNT: 155 EVENT: 1 PARM: 00000001
10. STATUS: 00030000 COUNT: 156 EVENT: 0 PARM: 00000000
11. STATUS: 00070082 COUNT: 227 EVENT: 2 PARM: 0000000a
12. STATUS: 00070080 COUNT: 228 EVENT: 3 PARM: ffffffc5
13. STATUS: 00070084 COUNT: 288 EVENT: 9 PARM: 00000000
WROTE Bus: 1 Addr: 48 Subaddr: 00 Value: 0a

nsh> i2c get -a 48
0. STATUS: 00000000 COUNT: 1 EVENT: 0 PARM: 00000000
1. STATUS: 00020000 COUNT: 9 EVENT: 0 PARM: 00000000
2. STATUS: 00030001 COUNT: 13 EVENT: 1 PARM: 00000002
3. STATUS: 00030000 COUNT: 14 EVENT: 0 PARM: 00000000
4. STATUS: 00070082 COUNT: 84 EVENT: 2 PARM: 00000000
5. STATUS: 00070080 COUNT: 85 EVENT: 3 PARM: ffffffc5
6. STATUS: 00070084 COUNT: 145 EVENT: 8 PARM: 00000001
7. STATUS: 00070080 COUNT: 146 EVENT: 3 PARM: ffffffbe
8. STATUS: 00030000 COUNT: 152 EVENT: 0 PARM: 00000000
9. STATUS: 00030001 COUNT: 155 EVENT: 1 PARM: 00000001
10. STATUS: 00030000 COUNT: 156 EVENT: 0 PARM: 00000000
11. STATUS: 00030002 COUNT: 227 EVENT: 0 PARM: 00000000
12. STATUS: 00030000 COUNT: 228 EVENT: 0 PARM: 00000000
13. STATUS: 00030040 COUNT: 299 EVENT: 5 PARM: 00000001
14. STATUS: 00030000 COUNT: 300 EVENT: 0 PARM: 00000000
15. STATUS: 00030040 COUNT: 370 EVENT: 5 PARM: ffffffc3
16. STATUS: 00030044 COUNT: 432 EVENT: 9 PARM: 00000000
READ Bus: 1 Addr: 48 Subaddr: 00 Value: 1b
nsh>

The important part is in the last event (EVENT: 9), which
corresponds to the STOP condition, the bit(2) BTF (Byte transfer
finished) to be precise, has not been set in the STATUS REGISTER SR1
when it's running en the F4, which looks like the following.


nsh> i2c set -a 1c A
0. STATUS: 00030001 COUNT: 1 EVENT: 1 PARM: 00000002
1. STATUS: 00070082 COUNT: 2 EVENT: 2 PARM: 00000000
2. STATUS: 00070084 COUNT: 3 EVENT: 8 PARM: 00000001
3. STATUS: 00030001 COUNT: 4 EVENT: 1 PARM: 00000001
4. STATUS: 00070082 COUNT: 5 EVENT: 2 PARM: 0000000a
5. STATUS: 00070084 COUNT: 6 EVENT: 9 PARM: 00000000
WROTE Bus: 1 Addr: 1c Subaddr: 00 Value: 0a

nsh> i2c get -a 1c
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
0. STATUS: 00030001 COUNT: 1 EVENT: 1 PARM: 00000002
1. STATUS: 00070082 COUNT: 2 EVENT: 2 PARM: 00000000
2. STATUS: 00070084 COUNT: 3 EVENT: 8 PARM: 00000001
3. STATUS: 00030001 COUNT: 4 EVENT: 1 PARM: 00000001
4. STATUS: 00030002 COUNT: 5 EVENT: 0 PARM: 00000000
5. STATUS: 00030040 COUNT: 6 EVENT: 5 PARM: 00000001
6. STATUS: 00030000 COUNT: 7 EVENT: 0 PARM: 00000000
i2ctool: get: Transfer failed: 16
nsh>


I hope to get the solution to this problem soon,

Diego
avrbasic
2012-03-22 12:12:41 UTC
Permalink
This is really a mystery thing..

we have SOME code that works ok with F4 I2C, it from some github
project, that code works ok, ALL the other code is failing

https://github.com/yigiter/Sample-STM32F4-codes

the I2C from that project ist known working!

Antti
Post by dsancheznuttx
This is the trace of the i2c tool running on the F1 board
nsh> i2c set -a 48 A
0. STATUS: 00000000 COUNT: 1 EVENT: 0 PARM: 00000000
1. STATUS: 00020000 COUNT: 9 EVENT: 0 PARM: 00000000
2. STATUS: 00030001 COUNT: 13 EVENT: 1 PARM: 00000002
3. STATUS: 00030000 COUNT: 14 EVENT: 0 PARM: 00000000
4. STATUS: 00070082 COUNT: 84 EVENT: 2 PARM: 00000000
5. STATUS: 00070080 COUNT: 85 EVENT: 3 PARM: ffffffc5
6. STATUS: 00070084 COUNT: 145 EVENT: 8 PARM: 00000001
7. STATUS: 00070080 COUNT: 146 EVENT: 3 PARM: ffffffbe
8. STATUS: 00030000 COUNT: 152 EVENT: 0 PARM: 00000000
9. STATUS: 00030001 COUNT: 155 EVENT: 1 PARM: 00000001
10. STATUS: 00030000 COUNT: 156 EVENT: 0 PARM: 00000000
11. STATUS: 00070082 COUNT: 227 EVENT: 2 PARM: 0000000a
12. STATUS: 00070080 COUNT: 228 EVENT: 3 PARM: ffffffc5
13. STATUS: 00070084 COUNT: 288 EVENT: 9 PARM: 00000000
WROTE Bus: 1 Addr: 48 Subaddr: 00 Value: 0a
nsh> i2c get -a 48
0. STATUS: 00000000 COUNT: 1 EVENT: 0 PARM: 00000000
1. STATUS: 00020000 COUNT: 9 EVENT: 0 PARM: 00000000
2. STATUS: 00030001 COUNT: 13 EVENT: 1 PARM: 00000002
3. STATUS: 00030000 COUNT: 14 EVENT: 0 PARM: 00000000
4. STATUS: 00070082 COUNT: 84 EVENT: 2 PARM: 00000000
5. STATUS: 00070080 COUNT: 85 EVENT: 3 PARM: ffffffc5
6. STATUS: 00070084 COUNT: 145 EVENT: 8 PARM: 00000001
7. STATUS: 00070080 COUNT: 146 EVENT: 3 PARM: ffffffbe
8. STATUS: 00030000 COUNT: 152 EVENT: 0 PARM: 00000000
9. STATUS: 00030001 COUNT: 155 EVENT: 1 PARM: 00000001
10. STATUS: 00030000 COUNT: 156 EVENT: 0 PARM: 00000000
11. STATUS: 00030002 COUNT: 227 EVENT: 0 PARM: 00000000
12. STATUS: 00030000 COUNT: 228 EVENT: 0 PARM: 00000000
13. STATUS: 00030040 COUNT: 299 EVENT: 5 PARM: 00000001
14. STATUS: 00030000 COUNT: 300 EVENT: 0 PARM: 00000000
15. STATUS: 00030040 COUNT: 370 EVENT: 5 PARM: ffffffc3
16. STATUS: 00030044 COUNT: 432 EVENT: 9 PARM: 00000000
READ Bus: 1 Addr: 48 Subaddr: 00 Value: 1b
nsh>
The important part is in the last event (EVENT: 9), which
corresponds to the STOP condition, the bit(2) BTF (Byte transfer
finished) to be precise, has not been set in the STATUS REGISTER SR1
when it's running en the F4, which looks like the following.
nsh> i2c set -a 1c A
0. STATUS: 00030001 COUNT: 1 EVENT: 1 PARM: 00000002
1. STATUS: 00070082 COUNT: 2 EVENT: 2 PARM: 00000000
2. STATUS: 00070084 COUNT: 3 EVENT: 8 PARM: 00000001
3. STATUS: 00030001 COUNT: 4 EVENT: 1 PARM: 00000001
4. STATUS: 00070082 COUNT: 5 EVENT: 2 PARM: 0000000a
5. STATUS: 00070084 COUNT: 6 EVENT: 9 PARM: 00000000
WROTE Bus: 1 Addr: 1c Subaddr: 00 Value: 0a
nsh> i2c get -a 1c
stm32_i2c_process: Timed out: CR1: 0001 status: 00030000
0. STATUS: 00030001 COUNT: 1 EVENT: 1 PARM: 00000002
1. STATUS: 00070082 COUNT: 2 EVENT: 2 PARM: 00000000
2. STATUS: 00070084 COUNT: 3 EVENT: 8 PARM: 00000001
3. STATUS: 00030001 COUNT: 4 EVENT: 1 PARM: 00000001
4. STATUS: 00030002 COUNT: 5 EVENT: 0 PARM: 00000000
5. STATUS: 00030040 COUNT: 6 EVENT: 5 PARM: 00000001
6. STATUS: 00030000 COUNT: 7 EVENT: 0 PARM: 00000000
i2ctool: get: Transfer failed: 16
nsh>
I hope to get the solution to this problem soon,
Diego
Loading...