cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L073 I2C not sending 9th clock pulse

GBohlin
Associate II

Hi,

I have an STM32L073 communicating with an IS31FL3246 LED driver over I2C. Occasionally the MCU will not send the 9th clock pulse and therefore locks the bus. 0693W00000NqEtpQAF.png(As shown in the picture the analog signal has a valid waveform without much noise)

Before this happens there are several valid I2C transactions like this one.

0693W00000NqEu4QAF.pngBelow is configuration used:

static void initDMA(void)
{
    DMA1_CSELR->CSELR |= DMA_LED_DRIVER_I2C_TX_CHANNEL_SELECT;
    DMA_LED_DRIVER_I2C_TX->CCR &= ~DMA_CCR_EN;
    DMA1->IFCR |= DMA_LED_DRIVER_I2C_TX_CLEAR_FLAGS;
    DMA_LED_DRIVER_I2C_TX->CPAR = (uint32_t) &I2C_LED_DRIVER->TXDR;
    DMA_LED_DRIVER_I2C_TX->CCR |= DMA_CCR_TCIE;
    DMA_LED_DRIVER_I2C_TX->CCR |= (1u << DMA_CCR_DIR_Pos);
    DMA_LED_DRIVER_I2C_TX->CCR |= (1u << DMA_CCR_MINC_Pos);
    DMA_LED_DRIVER_I2C_TX->CCR |= DMA_CCR_EN;
}

I2C timings are according to datasheet example.

static void initI2CTiming(void)
{
    I2C_LED_DRIVER->TIMINGR |= 0x01 << I2C_TIMINGR_PRESC_Pos;
    I2C_LED_DRIVER->TIMINGR |= 0x09 << I2C_TIMINGR_SCLL_Pos;
    I2C_LED_DRIVER->TIMINGR |= 0x03 << I2C_TIMINGR_SCLH_Pos;
    I2C_LED_DRIVER->TIMINGR |= 0x02 << I2C_TIMINGR_SDADEL_Pos;
    I2C_LED_DRIVER->TIMINGR |= 0x03 << I2C_TIMINGR_SCLDEL_Pos;
}
static void write(uint8_t *pData)
{
    I2C_LED_DRIVER->CR1 |= I2C_CR1_PE;
    I2C_LED_DRIVER->CR1 |= I2C_CR1_TXDMAEN;
    I2C_LED_DRIVER->CR2 |= I2C_CR2_AUTOEND;
    I2C_LED_DRIVER->CR2 &= ~I2C_CR2_RD_WRN;
    
    I2C_LED_DRIVER->CR2 &= ~I2C_CR2_SADD;
    I2C_LED_DRIVER->CR2 |= LED_DRIVER_I2C_WRITE_ADDRESS << I2C_CR2_SADD_Pos;
 
    I2C_LED_DRIVER->CR2 &= ~I2C_CR2_NBYTES;
    I2C_LED_DRIVER->CR2 |= 2u << I2C_CR2_NBYTES_Pos;
 
    DMA_LED_DRIVER_I2C_TX->CCR &= ~DMA_CCR_EN;
    DMA_LED_DRIVER_I2C_TX->CNDTR = 2u;
    DMA_LED_DRIVER_I2C_TX->CMAR = (uint32_t) pData;
    DMA_LED_DRIVER_I2C_TX->CCR |= DMA_CCR_EN;
 
    I2C_LED_DRIVER->CR2 |= I2C_CR2_START;
}

I couldn't find anything in the device errata sheet and since the MCU is the master I assume the issue is not the LED driver.

6 REPLIES 6
Simon V.
ST Employee

Hello,

Could you please confirm us some information please ?

Do please confirm that the issue occurs when the master is writing the slave please ?

On the faulty capture, it looks that slave ack is missing...

Last point, when the issue occurs, could you please read the I2C_ISR register to get the status of the I2C peripheral ?

Thanks in advance,

Regards,

Simon

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi,

> Do please confirm that the issue occurs when the master is writing the slave please ?

Yes, this happens when the master (STM32L073) is writing to the slave.

> On the faulty capture, it looks that slave ack is missing...

Yes, that is because it doesn't get a clock pulse from the master where it can send the ack. The issue is that the 9th clock pulse is missing...

> Last point, when the issue occurs, could you please read the I2C_ISR register to get the status of the I2C peripheral ?

0693W00000Nqv6vQAB.pngThe ARLO bit is set but there are only two devices on the bus, the master (STM32L073) and the slave (IS31FL3246).

Regards

Gustaf

Apparently you have to handle ARLO even if there's no other explicit master on the bus, as glitches/slow edges may make the slave to think that there's other master pulling down SDA.

The older I2C version (in 'F2/'F4 and older) tends to stop clocking and lock up amidst a byte, when this happens, without setting the arbitration lost bit, so timeouts are vital there.

Decreasing the pullup value and reviewing grounds/crosstalks decrease likelyhood that this happens. Tinkering with the analog/digital filters, and maybe with relevant GPIOx_OSPEEDR, may help too.

JW

Hi Jan,

At the moment I have a workaround which detects timeout, and therefore also ARLO. When that happens I pull the reset pin on the slave and restart the communication. I was hoping there was a better alternative but as I understand it from your answer this is expected behavior and therefore that is the "only" fix?

Regards

Gustaf

Gustaf,

What I try to do is, get things working without any of these fixes (see above my remarks on grounds (LEDs, they suck high current in pulses, heh?)/crosstalks, pullups, filters), and then I put the fixes back for better sleep.

JW

That makes sense, I've seen that there are filters in the microcontroller that I can activate but I haven't looked into it too much, maybe I should give that a try. I also at the moment have a crude setup with fairly long wires for development purposes, but when I get our first prototype boards we will likely have better signals and this issue will be less frequent. Your "solution" sounds like a reasonable way forward, thank you 😀

Regards

Gustaf