cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F1 I2C start failure

clark2
Associate II
Posted on February 16, 2016 at 15:57

I am working with an STM32F103RC and trying to develop an I2C master application.  Currently the I2C bus is populated with only this master and an MCP23017 slave.

In my most recent test run the program eventually ended up in a locked loop waiting for SB to set in SR1.  The START bit is set, PE is set, the peripheral clock is enabled, both signals are in the passive state... how is this possible?  Is there a known (yet unpublished) bug in this peripheral which would allow this condition?  The obvious answer is ''yes'' unless I'm missing something.

I realize the prudent thing to do would be to have a timeout test on this wait, but why?

30 REPLIES 30
Posted on February 17, 2016 at 10:10

It's still hummm, but I have a couple of comments:

- I can't see where do you enable I2C1_ER_IRQ in NVIC

- DMAx_ISR is read only, there's no point to write into it

- DMAx_IFCR is write only, I wouldn't RMW on it

- to write data, there's no need for restart and resending the device address - but that's just an optimization hint, should not make difference functionality-wise

and questions:

- if the stall occurs always in line 126 of i2c.c, it's before the first transmission of device address, ie. after STOP, not after the REPEATED START. There are two such places: before the read and before the write. Does it occur always at the same point, i.e. always before the read or always before the write, or is it random?

- is your LA fast enough to capture all transmissions in repeated-trigger mode? If so, could you toggle a GPIO just before calling i2c_handler(), and trigger the LA on this GPIO? If so, you should be able to see what happened on the I2C bus after i2c_handler() has been called, i.e. whether START occured or not.

JW

clark2
Associate II
Posted on February 17, 2016 at 16:27

Thank you for your constructive comments and questions...

>> I can't see where do you enable I2C1_ER_IRQ in NVIC

Good catch.  I removed that when changing to a polling method and forgot to add it back in.

>> DMAx_ISR is read only, there's no point to write into it

>> DMAx_IFCR is write only, I wouldn't RMW on it

Again, changing from interrupt-driven to polling, I managed to bork this particular task.

>> to write data, there's no need for restart and resending the device address - but that's just an optimization hint, should not make difference functionality-wise

Like you said...

>> if the stall occurs always in line 126 of i2c.c, it's before the first transmission of device address, ie. after STOP, not after the REPEATED START. There are two such places: before the read and before the write. Does it occur always at the same point, i.e. always before the read or always before the write, or is it random?

It hasn't occured enough times to know for certain.  This time it ran for hours and locked up some time during the night with i2c_pkg.cmd[0] == 0x13, so, it was attempting to read GPIOB.

>> is your LA fast enough to capture all transmissions in repeated-trigger mode? If so, could you toggle a GPIO just before calling i2c_handler(), and trigger the LA on this GPIO? If so, you should be able to see what happened on the I2C bus after i2c_handler() has been called, i.e. whether START occured or not.

I'm not sure.  I have a Saleae Logic Pro 8.  I will be disappointed if it can't do that, but it won't be the first disappointment with it...  I guess my next mission is to figure out how to do this.

clark2
Associate II
Posted on February 19, 2016 at 15:36

After some fiddling, I managed to capture events around the timeout (waiting for SB).  The I2C activity in to 100 mS before the timeout looks normal and no start sequence occurs.

Another curious situation is presenting itself and may or may not be related.  The MCP23017 is somehow being reconfigured or reset, the result being that port A becomes all inputs again.  The program keeps chugging along happily...

Posted on February 19, 2016 at 19:40

I run out of ideas at this point, sorry.

JW
Radosław
Senior II
Posted on February 19, 2016 at 20:18

Let you know my kindness. I must be awesome.

1. Still you don't understand how good code should be look.

2. Are you addicted to slow  not optimal bitband access? Why?

3. Your bit testing is very strange for example :

while ((I2C1->SR1 & 0x00040) != 0x000040); // RxNE

should be while (! (I2C1->SR1 & 0x00040)); or

while ((I2C1->SR1 & 0x00040) == 0);

4. DMA for I2C which can work fasstar than 400kHz?  How long frames you write/ read from slave?

at the end workinf transmit function in polling mode

void I2C1_write(const uint8_t ICaddress, const uint8_t address, const uint8_t *data, uint32_t count)

{

    uint32_t temp = temp;

    I2C1_CR1_ACK_bb = 1;

    I2C1_CR1_START_bb = 1;

    while (!(I2C1->SR & I2C_SR1_SB));

    I2C1->DR = ICaddress;

    while (!(I2C1->SR & I2C_SR1_ADDR));

    temp = I2C1->SR2;

    I2C1->DR = address;

    while (!(I2C1->SR & I2C_SR1_BTF));

    while (count--)

    {

        I2C1->DR = *data++;

        while (!(I2C1->SR & I2C_SR1_BTF));

    }

    I2C1_CR1_STOP_bb = 1;

    while (I2C1->CR & I2C_CR1_STOP);

}

clark2
Associate II
Posted on February 19, 2016 at 23:01

>>Let you know my kindness. I must be awesome.

  Yes, you must be.

  

>>1. Still you don't understand how good code should be look.

  I'm fairly certain that I have a better grasp of ''how good code should

  be look'' than you might think.  I don't know how old you are, but I

  would bet my last Reese's Peanut Butter Cup that I was writing compilers

  and assemblers (in assembly language) before you drew your first breath.

  Like I said, I'm not that interested in beautification or optimization at

  this point.  I am only testing the peripheral functionality.

  

>>2. Are you addicted to slow  not optimal bitband access? Why?

  You have not demonstrated how bitband access is ''slow not optimal''.

  It is specifically designed to be optimal and atomic.

  Please do elaborate.

  

>>3. Your bit testing is very strange for example :

>>   while ((I2C1->SR1 & 0x00040) != 0x000040); // RxNE

>>   should be while (! (I2C1->SR1 & 0x00040)); or

>>   while ((I2C1->SR1 & 0x00040) == 0);

  This statement, which you call ''strange'', is straight out of the AN2824

  ''Optimized I2C Examples'' to which you referred earlier.  I agree; I would

  not normally write the expression that way either.

  

  And, FWIW, all three of the above statements produce EXACTLY the same

  code, at least with GCC...

  

  while ((I2C1->SR1 & 0x00040) != 0x000040);

    4B0B        ldr r3, 0x08000374

    695B        ldr r3, [r3, #20]

    F0030340    and r3, r3, #0x40

    2B00        cmp r3, #0

    D0F9        beq 0x08000346

  while (! (I2C1->SR1 & 0x00040));

    4B07        ldr r3, 0x08000374

    695B        ldr r3, [r3, #20]

    F0030340    and r3, r3, #0x40

    2B00        cmp r3, #0

    D0F9        beq 0x08000354

  while ((I2C1->SR1 & 0x00040) == 0);

    4B04        ldr r3, 0x08000374

    695B        ldr r3, [r3, #20]

    F0030340    and r3, r3, #0x40

    2B00        cmp r3, #0

    D0F9        beq 0x08000362

>>4. DMA for I2C which can work fasstar than 400kHz?  

  I'm not sure what you're getting at here.  Please explain.

>>How long frames you write/ read from slave?

  This is not known.  I intend to use the I2C bus as a general purpose

  expansion port to enable yet unknown functionality.  I would expect

  this number to be less than 128.

Radosław
Senior II
Posted on February 19, 2016 at 23:27

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6jH&d=%2Fa%2F0X0000000bu6%2FNPTc4RDKpfY_DzuRt8UmdnuWPynuBR.kqrHinDIvgGM&asPdf=false
clark2
Associate II
Posted on February 19, 2016 at 23:39

Why do you set ACK when transmitting?

Are those bitband accesses I see?  I thought those were bad?

What do you do if SB never gets set?

Radosław
Senior II
Posted on February 19, 2016 at 23:53

1. ACK in write. I can remember this function i wrote 4 years ago. Probably some precotions.

2. BB specially for you. In past i too like BB. But now I use it almost never. I use universal function for I2C (I2C number as parameter.

3. This is only functional example without any exeptions.  But i can remember when last time  my I2C stacks. 

ACK if I remember correctly.  I have some problem like your and it was becose of some ACK  problems.  I was long time ago.

PS.   Literals you know this?  in BB access each adrress must be stored somewhere. (In flash).  Count flash accesses in BB method and normal. Flash is slow as you probably know.

If you love BB acces so much. Write bit structures for it, then you can get some optimal usage of it.

 

PS2. Sorry for my english. ;)

clark2
Associate II
Posted on February 20, 2016 at 00:23

>>2. ... I use universal function for I2C (I2C number as parameter. 

  In this particular application I have only one I2C port available.

  Therefore, I chose not to include this feature.

  

>>3. This is only functional example without any exeptions.  But i can remember when last time  my I2C stacks.  

  I am encountering this exact problem, which is the whole point...

  

>>PS.   Literals you know this?  in BB access each adrress must be stored somewhere. (In flash).  Count flash accesses in BB method and normal. Flash is slow as you probably know.

  ''Normal'' memory accesses require the address to be stored somewhere, too.

  I really don't see where you are coming from with this...

  Reading a bitband alias memory location is no different from reading

  any other RAM location, except that you are reading a single bit.

  

  This is from the Cortex-M3 Technical Reference Manual:

  The System bus interface contains logic that controls bit-band accesses as follows:

    • It remaps bit-band alias addresses to the bit-band region.

    • For reads, it extracts the requested bit from the read byte, and returns this in the Least

    Significant Bit (LSB) of the read data returned to the core.

    • For writes, it converts the write to an atomic read-modify-write operation.

    • The processor does not stall during bit-band operations unless it attempts to access the System bus while the bit-band operation is being carried out.

>>If you love BB acces so much. Write bit structures for it, then you can get some optimal usage of it. 

  I don't know what you're trying to say.  Accessing individual bits via a bitfield structure

  has no benefit.