Page 2 of 4
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 10:30 am
by barthess
Got some strange behavior only with ITG3200 when compiled with -O0. It sporadically cause I2CD_ACK_FAILURE error. With previous version all is OK. I will try to find problems.
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 1:23 pm
by dandys
Hi barthess, I have the similar behavior on my board. I2CD_ACK_FAILURE error occurs once per approximately 1400 I2C transactions, no matter what device I actually reading- I have MPU6050, LSM303DLHC and MS5611 on the bus. Early I thougt it's electrical problem, but i can see nice edges on oscilloscope and using 4k7 pullups. GCC 4.6.1 (Sourcery CodeBench Lite 2011.09-69) and compiling with -O2. Currently I using Chibios 2.4.2, but was the same with 2.4.1. If I may somewhat help you to debug the problem, let me know.
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 6:28 pm
by barthess
Hello, guys.
After digging code since whole Sunday I can say some more. The Invensens' sensors cause troubles. IMO because of too short timeouts in them i2c cells. To avoid this the ISR code must as fast as possible. The i2c_get_event() function runs too slow.
@ ahaczewski
your patch works perfectly on my F4x but on F1x cause troubles. So I decide to fallback to previous implementation that now works much better.
@ dandys
Probably you have CH_DBG_ENABLE_ASSERTS enabled and 400kHz speed of I2C bus. Am I correct? Try attached driver for v2.4.2 and let me know if it works.
I want to thanks:
Tectu for creating and maintaining IRC channel. It was really helpful for testing.
Ranzbak for patience and testing.
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 7:41 pm
by dandys
@ barthess
Unfortunately still returning error. CH_DBG_ENABLE_ASSERTS was already disabled and I've tried attached driver . Error rate seems to be unchanged

Also tried remove Invensense MPU6050 code, but error still happening while reading out LSM303DLHC magnetometer.
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 7:48 pm
by barthess
dandys
Can you join as in IRC channel?
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 7:50 pm
by barthess
Re: [STM32] I2C HAL driver problems and fixes
Posted: Sun Aug 05, 2012 11:02 pm
by dandys
SOLVED: it was just I2C IRQ priority problem. Increased priority and no errors now. Big thanks to barthess for patience. He helped me on IRC channel much.
Re: [STM32] I2C HAL driver problems and fixes
Posted: Mon Aug 06, 2012 11:45 am
by ahaczewski
@barthess: Looks like setting the POS flag is a bad thing after all, I have Invensense (ITG3200), BMP085, ADXL345 and HMC5883 on my bus and I2C locks on communication with more than 2 devices
Talking with one of them one transaction after another works flawlessly, but as soon as I go to other one the bus gets low and never rises again. Removing the if that sets POS flag fixed that one. ACK still needs to be reset for 1- or 2-byte receptions.
Will investigate some more and report back.
PS. I'll soon (14-30 days) have F1 to test against.
PPS. I checked again with RM and the POS flag thing is only for non-DMA transfers, resetting ACK is for all. I can't tell how I didn't see it the first time...

Re: [STM32] I2C HAL driver problems and fixes
Posted: Tue Aug 07, 2012 10:47 pm
by MartinP
No, it will not.
Hi Barthess,
inspired by
Ahaczewski's initial post I checked the RM0090 I2C Section and in 23.3.7 DMA requests(page 589) they say for Master receiver
When a single byte must be received: the NACK must be programmed during EV6
event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. Then the
user can program the STOP condition either after clearing ADDR flag, or in the
DMA Transfer Complete interrupt routine
when put aside the question when to clear the ADDR flag exactly (before or after DMA settings) this could be achieved with the following code (Developer Version from SVN):
Code: Select all
static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
uint32_t regSR2 = dp->SR2;
uint32_t event = dp->SR1;
/* Interrupts are disabled just before dmaStreamEnable() because there
is no need of interrupts until next transaction begin. All the work is
done by the DMA.*/
switch (I2C_EV_MASK & (event | (regSR2 << 16))) {
case I2C_EV5_MASTER_MODE_SELECT:
dp->DR = i2cp->addr;
break;
case I2C_EV6_MASTER_REC_MODE_SELECTED:
dp->CR2 &= ~I2C_CR2_ITEVTEN;
dmaStreamEnable(i2cp->dmarx);
dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */
if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2)
{
dp->CR1 &= ~I2C_CR1_ACK;
}
break;
case I2C_EV6_MASTER_TRA_MODE_SELECTED:
dp->CR2 &= ~I2C_CR2_ITEVTEN;
dmaStreamEnable(i2cp->dmatx);
break;
case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
/* Catches BTF event after the end of transmission.*/
if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) {
/* Starts "read after write" operation, LSB = 1 -> receive.*/
i2cp->addr |= 0x01;
dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
return;
}
dp->CR2 &= ~I2C_CR2_ITEVTEN;
dp->CR1 |= I2C_CR1_STOP;
wakeup_isr(i2cp, RDY_OK);
break;
default:
break;
}
/* Clear ADDR flag. */
if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10))
regSR2 = dp->SR2;
}
I've done some trials on a stm32f4 which worked but you are the experts ....
Martin
Re: [STM32] I2C HAL driver problems and fixes
Posted: Wed Aug 08, 2012 11:14 am
by barthess
MartinP wrote:inspired by Ahaczewski's initial post I checked the RM0090 I2C Section and in 23.3.7 DMA requests(page 589) they say for Master receiver
When a single byte must be received: the NACK must be programmed during EV6
event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. Then the
user can program the STOP condition either after clearing ADDR flag, or in the
DMA Transfer Complete interrupt routine
Thanks for pointing me. Previously I suppose that I2C cells in F1x and F4x are totally equal. I will do some tryouts.