2021-08-28 03:15 AM
I'm configuring I2C4 as a slave receiver, using interrupt method. I noticed that when the I2C master (another MCU) sends the slave address, I2C4 detects an address match and sets the ADDR flag in the I2C4->ISR register. What baffles me is that at this point I2C4 holds the SCK line low and communication will not proceed. The only way I can avoid this 'stuck' situation is to enable the ADDRIE interrupt which will fire on an address match and I manually clear the ADDR flag.
I'm familiar with I2C protocol, but this is my first experience with STM32 I2C peripheral, and I thought it's strange that an address match event must be explicitly acknowledged (by clearing a flag) by software. Is this the normal behavior of I2C slave in STM32H7? I'm using the STM32H723ZG Nucleo board.
Below is my initialization code (for brevity I omitted the clock and pin configuration from the listing, they checked out all right).
// Disable I2C4.
I2C4->CR1 &= ~I2C_CR1_PE;
while(I2C4->CR1 & I2C_CR1_PE) {}
// Enable receive complete interrupt.
I2C4->CR1 |= I2C_CR1_RXIE;
// Set own address.
I2C4->OAR1 |= (LL_I2C_OWNADDRESS1_7BIT | (MY_ADDRESS << I2C_OAR1_OA1_Pos));
// Enable Own address 1.
2C4->OAR1 |= I2C_OAR1_OA1EN;
// Set timing register.
I2C4->TIMINGR = 0x00601956;
// Enable I2C4
I2C4->CR1 |= I2C_CR1_PE;
Here's the register contents when address match event occurs.
Solved! Go to Solution.
2021-08-28 10:59 AM
That's how it works with NOSTRETCH=0 (default). You can set NOSTRETCH=1 if you want, but the real solution would be to clear the flag and send data on TXDR or read from RXDR. See "I2C Slave Mode" in the reference manual.
2021-08-28 10:59 AM
That's how it works with NOSTRETCH=0 (default). You can set NOSTRETCH=1 if you want, but the real solution would be to clear the flag and send data on TXDR or read from RXDR. See "I2C Slave Mode" in the reference manual.