cancel
Showing results for 
Search instead for 
Did you mean: 

I2C slave NOSTRETCH=1, When should I put data in TX register?

JulienD
Senior

Hello,

 

I'm trying communication between stm32G0 as I2C slave and a rapsberry pi 5 as master.

on pi side, the call is:

 

    self.cpt = (self.cpt + 1) % 255
    b = self.bus.read_i2c_block_data(42, self.cpt, 5);

 

I've seen in several places on the web that there are issues with clock stretching with the pi (and some tests on my side seem to agree). So I'm using NOSTRETCH activated on the microncontroler side.

For testing purpose I'm transmitting the array {0, 1, 2, 3, 4} on the microcontroler and I'm receiving [4, 0, 1, 2, 3] on the pi.

Here's a screenshot. The green line toggles when I put a byte in tx register.

 

JulienD_1-1729847569421.png

 

From the reference manual, I found this explanation:

 

JulienD_0-1729846997908.png

It shows that data should placed in the tx register before the start.

To do that, I tried to put the first byte in tx register during the read frame. The result is slightly different but still wrong : [5, 1, 2, 3, 4]

JulienD_2-1729847678793.png

I managed to make it successfull by sending nothing during the last TXIS interrupt of the frame but I'm not really satisfied with this solution.  It looks ugly.

 

JulienD_3-1729848018087.png

Is it the good way to do it?

Here's the code. 

 

void init(){
// cubemx initialization happened before this.

    LL_I2C_EnableIT_ERR(I2C1);
    LL_I2C_EnableIT_STOP(I2C1);
    LL_I2C_EnableIT_RX(I2C1);
    LL_I2C_EnableIT_NACK(I2C1);
    LL_I2C_EnableIT_TX(I2C1);
    LL_I2C_EnableIT_ADDR(I2C1);

    LL_I2C_Enable(I2C1);
}



uint8_t rx = 0;
uint8_t buffer[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
static uint8_t tx = 0;


void send_byte()
{
    LL_GPIO_TogglePin(debug2_GPIO_Port,  debug2_Pin);
    LL_I2C_TransmitData8(I2C1,  buffer[tx]);
    tx++;
}


void I2C1_IRQHandler(void)
{
    /* USER CODE BEGIN I2C1_IRQn 0 */

    if (LL_I2C_IsActiveFlag_ADDR(I2C1))
    {
        LL_I2C_ClearFlag_ADDR(I2C1);
        if (LL_I2C_GetTransferDirection(I2C1) == LL_I2C_DIRECTION_WRITE)
        {
            LL_GPIO_SetOutputPin(debug1_GPIO_Port,  debug1_Pin);
        }
        else
        {
            LL_GPIO_ResetOutputPin(debug1_GPIO_Port,  debug1_Pin);
        }
    }


    if (LL_I2C_IsActiveFlag_TXIS(I2C1))
    {
        {
            if (tx < 5)
                send_byte();
        }
    }


    if (LL_I2C_IsActiveFlag_OVR(I2C1))
        LL_I2C_ClearFlag_OVR(I2C1);

    if (LL_I2C_IsActiveFlag_RXNE(I2C1))
    {
        {
            rx =  LL_I2C_ReceiveData8(I2C1);
            tx = 0;
            send_byte();     // put the first byte in tx regsiter before the start condition
        }
    }


    if (LL_I2C_IsActiveFlag_STOP(I2C1))
    {
//        SET_BIT(I2C1->ISR, I2C_ISR_TXE);
//        SET_BIT(I2C1->ISR, I2C_ISR_TXIS);
        LL_I2C_ClearFlag_STOP(I2C1);
    }


    if (LL_I2C_IsActiveFlag_NACK(I2C1))
        LL_I2C_ClearFlag_NACK(I2C1);


    if (LL_I2C_IsActiveFlag_TCR(I2C1))
    {
    }


    if (LL_I2C_IsActiveFlag_TXE(I2C1))
    {
    }
}

 

 

 

 

 

 

 

0 REPLIES 0