1
\$\begingroup\$

Trying to understand why the while loop is behaving weirdly.

HAL_MasterReceiveInterrupt() enables the control bits for I2C and continues to loop unless the STATE is READY - in other words, when the data is fully read but I see the it executing outside the while loop. So while loop shouldn't end until the the return value from the function is I2C_READY

The output looks as follows:

RXing...
Printing buffer values...
Stopping transmission

Instead of:

RXing...
Stopping transmission
Printing buffer values // now that we are outside the loop

what's up with the sequence of execution?

I2C_State HAL_MasterReceiveInterrupt(void)
{
    I2C_State i2cState = I2C_handle_p->I2C_State;

    if (i2cState != I2C_RX_BUSY && i2cState != I2C_TX_BUSY)
    {
        printf ("RXing...\n");
        I2C_handle_p->I2C_State = I2C_RX_BUSY;

        GenerateStartCondition(I2C_handle_p);

        I2C_SetCtrlBits();   // enable i2c control bits
    }
    return i2cState;
}

static void I2C_StopTransmission(void)
{
    printf ("Stopping transmission...\n\n");

    // disable control bits
    I2C_handle_p->pI2Cx->CR2 &= ~(1 << I2C_CR2_ITEVTEN_Pos);
    I2C_handle_p->pI2Cx->CR2 &= ~(1 << I2C_CR2_ITBUFEN_Pos);

    // restore struct
    I2C_handle_p->I2C_State = I2C_READY;
    I2C_handle_p->rxBufferLength = BYTES_PER_TRANSACTION;
} 

// app.c
void ReadVal() {
  while (HAL_MasterReceiveInterrupt() != I2C_READY);
  printf ("Printing buffer values..."); // assuming I2C read operation is completed
  while(1);
}
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Who calls the I2C_StopTransmission? But anyway, the I2C_StopTransmission sets the I2C_READY, so it shall be the last call before you execute "Printing buffer values". And HAL_MasterReceiveInterrupt changes the staus from I2C_READY to I2C_BUSY. So the sequence is as follows:

"Printing buffer values"
"Printing buffer values"
"Printing buffer values"
n x times

"RXing..."
"Stopping transmission..."
"Printing buffer values"
"Printing buffer values"
"Printing buffer values"
n x times

EDIT:

 if (i2cState != I2C_RX_BUSY && i2cState != I2C_TX_BUSY)

if it's not rx_busy and it's not tx_ busy then

I2C_handle_p->I2C_State = I2C_RX_BUSY;

?? then it's rx_busy??

Further, you ask a state that obviously is set by system and then you override it?

\$\endgroup\$
1
  • \$\begingroup\$ ah, so the initial value stored in i2cState is I2C_READY, hence the while loop doesn't get executed to begin with. But there's still a strange behavior that I'm not able to understand regarding getting out of the while loop even though i2cState is not I2C_READY (hence the prints). also, would it be better to add say I2C_NOTREADY so the initial value is not I2C_READY? in regards to later comment, the initial value is not expected to be either I2C_RX_BUSY or I2C_TX_BUSY \$\endgroup\$
    – xyf
    Apr 6, 2020 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.