cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Slave “Repeated Start�? Callback?

raymartin
Associate II

STM32F105, HCLK=72MHz, HAL Ver 1.1.8.0, SCL = 100KHz

Is there a “Repeated Start�? HAL callback? I couldn’t find any direct reference but does the STM32 I2C peripheral know when this occurs and set a status bit somewhere?

In my application, I can’t allow the slave to stretch the clock. So when the Master sends my Device Address followed by a Register Number, my slave code polls SCL/SDA GPIO pins to detect Repeated Start then calls HAL_I2C_Slave_Seq_Transmit_DMA. If I wait for the 2nd Address Callback, the slave transmit starts too late.

My approach appears to work but assumes Repeated Start is to the same device address (only a direction change).

I tried calling HAL_I2C_Slave_Seq_Transmit_DMA after the 1st address callback (before master sends the Register Number to slave) but it didn’t work. The slave doesn’t know in advance if the master will continue writing after it sends the initial Register Number (slave supports data read and data write). The earliest indication is Repeated Start.

3 REPLIES 3
raymartin
Associate II

0693W00000NqfSWQAZ.pngThe diagram above summarizes the problem. The critical area is detecting Repeated Start before the slave must transmit to the master. Using the GPIO poll technique I described earlier, it is possible to operate at 100KHz SCL without clock stretching but I’m hoping there’s a formal way to do this.

raymartin
Associate II

I was able to repurpose the PEC bit in the I2C_CR1 resister (my application doesn’t use Packet Error Checking). One key behavior of this bit is the hardware clears it when it detects START or REPEATED START. The steps below explain how I use this:

1) When the master first sends my slave device address, my slave HAL_I2C_AddrCallback gets called and it sets PEC then calls HAL_I2C_Slave_Seq_Receive_IT to receive 1 byte (register number) from the master.

2) The master continues by sending the register number it wants to start reading or writing. My slave HAL_I2C_SlaveRxCpltCallback gets called and it checks the value of PEC.

3a) If the slave notices PEC is cleared, it means the master did a Repeated Start just after sending the register number. The slave then calls HAL_I2C_Slave_Seq_Transmit_DMA to transmit data to the master.

3b) If instead the slave notices PEC is still set, it means Repeated Start did not occur so the slave calls HAL_I2C_Slave_Seq_Receive_IT to receive data from the master.

  

The PEC bit has 2 advantages over GPIO polling:

1) It’s hardware based and uses the factory method for detecting Start/Repeated Start

2) It’s latched until cleared so my code can detect it even after the event occurred

I’m now able to run at SCL=400KHz without clock stretching. The reason the slave must use DMA to transmit is because this must start immediately after the master sends DevAddrRD.

swer
Associate II

Hello raymartin,

I also need to detect the repeated start condition and your approach also seems reasonable. Can you please share a short snippet of code how to use the PEC flag in the I2C_CR1 register.

Thank you in advance