Skip to main content
paulr
Associate
December 27, 2014
Question

i2c - No Slave Address Acknowledgement - Standard Peripheral Library - STM32L1xx

  • December 27, 2014
  • 2 replies
  • 1235 views
Posted on December 27, 2014 at 21:09

The original post was too long to process during our migration. Please click on the attachment to read the original post.
    This topic has been closed for replies.

    2 replies

    paulr
    paulrAuthor
    Associate
    December 30, 2015
    Posted on December 30, 2014 at 19:38

    Hi Folks:

    I modified I2C_CheckEvent(), as illustrated below, to prevent

    the I2C SR1 register from being read twice in the case of

    overly anxious compilers and optimizers. The solution is

    not elegant or sophisticated but works.  Basically, it

    involves using the volatile qualifier and computing the

    register address before accessing the register. A potential

    drawback is the use of a hardcoded register offset.

    Best Regards,

    Paul R.

    ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)

    {

      uint32_t lastevent = 0;

      volatile uint32_t flag1 = 0, flag2 = 0;

      volatile uint32_t *p_sr1;

      ErrorStatus status = ERROR;

      /* Check the parameters */

      assert_param(IS_I2C_ALL_PERIPH(I2Cx));

      assert_param(IS_I2C_EVENT(I2C_EVENT));

      /* Read the I2Cx status register */

      p_sr1 = (volatile uint32_t *) ((void *) I2Cx + I2C_Register_SR1);

      flag1 = *p_sr1;

      flag2 = I2Cx->SR2;

      flag2 = flag2 << 16;

      /* Get the last event value from I2C status register */

      lastevent = (flag1 | flag2) & FLAG_MASK;

    /* Check whether the last event contains the I2C_EVENT */

      if ((lastevent & I2C_EVENT) == I2C_EVENT)

      {

        /* SUCCESS: last event is equal to I2C_EVENT */

        status = SUCCESS;

      }

      else

      {

        /* ERROR: last event is different from I2C_EVENT */

        status = ERROR;

      }

      /* Return status */

      return status;

    }

    paulr
    paulrAuthor
    Associate
    December 31, 2015
    Posted on December 31, 2014 at 03:20

    Hi Folks:

    I know the exact cause of the I2C problem and have solved it.

    The cause is that in an OS environment with preemptive scheduling

    it is likely that data in read sensitive registers will be lost

    during task switches--due to the fact that you need to read

    registers in order to save them. For example, if the I2C SR1 register

    is saved during a task switch, the value of bit 1 may be

    cleared.

    The solution is to make the all the I2C operation code between

    the point the bus is acquired and the routine exits a critical section

    in the P_I2C_Rx_Byte() and P_I2C_Tx_Byte() routines. Since these

    routines only transfer a one byte register, it is safe to do this.

    The details of entering a critical section are OS dependent and

    and versions of these routines configured for FreeRTOS are attached.

    Also, I strongly advise adopting the changes in I2C_CheckEvent()

    which I previously described.

    Best Regards,

    Paul R.

    ________________

    Attachments :

    code.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzVA&d=%2Fa%2F0X0000000bMm%2FqT_Jv7BxqOxXBNmKcv.RA_qGB8xniQ4.4sdFq5kqlrM&asPdf=false