2013-01-24 08:42 AM
Hello,
I have an issue while 2 STM32F103REY are connected through i2c, 7bits addressing. It works good in the following cases: master transmitter master receiver for 1 byte master receiver for n bytes, n >=2 Not ok for master receiver for 2 bytes. The driver used is a custom one. It uses interrupt. Surprisingly, the ''AN2824 I2C master programming examples (DMA, interrupts, polling)'' describe no examples with master receiver based on interrupt ? There are only DMA and polling examples for this cases. Does it means no robust solution is possible with interrupt ? The issue happens during a first 2 bytes reception but is only seen on the next reception. 3 interrupts occurs to read 3 bytes instead of 2 interrupts to read 2 bytes. The unexpected extra read data is lost, as not read before the next reception (it is unexpected). - Based on the errata sheet, I guess the best matched issue is the one reported as ''Some software events must be managed before the current byte is being transferred'' and applying to EV6_1. I have tried in the handler interrupt routines to ''Stretch SCL line between ADDR bit is cleared and ACK is cleared'' but without success. //GPIOB_CRL 0x40010C00 //GPIOB_ODR 0x40010C00 + 0xC //GPIOB_BSRR 0x40010C00 + 0x10 // set SCL gpio7, CNF7[1:0] bit 31-30 to 01: General purpose output Open-drain // no change of the GPIO mode as it is corretcly setup uint32_t bsrr = *(volatile uint32_t *) 0x40010C00; bsrr &= 0x7FFFFFFF; bsrr |= 0x70000000; *(volatile uint32_t *) 0x40010C00 = bsrr; // clear bit7 *(volatile uint32_t *) 0x40010C10 |= (1<<(16+7));//same result with *(volatile uint32_t *) 0x40010C0C &= 0xFFFFFF7F but the bit7 is stuck at 1 and this do nothing while is effective on an un-used IO. So I guess the I2C interface continue to drive SCL to 1 and the software request to go low level is then not efficient ? My investigation to change the GPIO alternate through AFIO, conclude that this is not possible during communication. I'd like clear code examples on how to do that. - I then try to mask interrupt as mentionned in AN2824 for the polling case but here during the interrupt handler. This was not efficient too. I have looked for information on the forum without success. Maybe there was a post, as user lanchon wrote ''I've posted master mode i2c code that works and a couple of posts detailing limitations of the i2c macrocell, look them up if you want'' but I have found nothing like this. Also I guess even if some of the issues described in the errata sheet have not been seen, they have to be workaround for robustness. Regarding the un-sucess for the first one, no clear synthesis for the whole and not enough detailed how to do (no code) for me, I really need your help. Thanks in advance #i2c #i2c2013-01-25 07:33 AM
Hi,
While I have still the same issue, I mix up with gpio. By default gpiob6 is SCL and gpiob7 is SDA. I wrongly seen gpio7 as SCL instead of SDA and it is at ''1'' between b) and e) code execution of below procedure. But in fact, gpiob6/SCL is at ''0''. In the errata sheet CD00190234, p19:Workaround 3 (only for EV6_1 and EV6_3 events used in method 2) EV6_1 event (used in master receiver 2 bytes): Stretch SCL line between ADDR bit is cleared and ACK is cleared: a) ADDR=1 b) Configure SCL I/O as GPIO open-drain output low c) Clear ADDR by reading SR1 register followed by reading SR3 d) Program ACK=0 e) Configure SCL I/O as Alternate Function open drain So for b) with a cleaner code on the right SCL gpio than this so poor one below is: uint32_t * gpiob_odr = (volatile uint32_t *) 0x40010C0C; uint32_t * gpiob_bsrr = (volatile uint32_t *) 0x40010C10; uint32_t * gpiob_crlh = (volatile uint32_t *) 0x40010C04; uint32_t * gpiob_crll = (volatile uint32_t *) 0x40010C00; //01: General purpose output Open-drain and //11: Output mode, max speed 50 MHz. (*gpiob_crll) &= 0xF7FFFFFF; (*gpiob_crll) |= 0x07000000; //clear bit6 so gpiob6 i2c1 SCL without remaping *gpiob_bsrr |= (1<<(16+6)); and e) //11: Alternate function output Open-drain //11: Output mode, max speed 50 MHz. (*gpiob_crll) |= 0x0F000000; Anyway, that changes nothing about the issue, still 3 bytes received instead of 2. If somebody encountered such issue, I like you to share how you deal with it.