2016-02-16 06:57 AM
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?2016-02-17 01:10 AM
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. JW2016-02-17 07:27 AM
Thank you for your constructive comments and questions...
>> I can't see where do you enable I2C1_ER_IRQ in NVICGood 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 itAgain, 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-wiseLike 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.2016-02-19 06:36 AM
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...2016-02-19 10:40 AM
I run out of ideas at this point, sorry.
JW2016-02-19 11:18 AM
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); }2016-02-19 02:01 PM
>>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.2016-02-19 02:27 PM
2016-02-19 02:39 PM
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?2016-02-19 02:53 PM
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. 😉2016-02-19 03:23 PM
>>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.