i2c - No Slave Address Acknowledgement - Standard Peripheral Library - STM32L1xx
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2014-12-27 12:09 PM
Posted on December 27, 2014 at 21:09The original post was too long to process during our migration. Please click on the attachment to read the original post.
This discussion is locked. Please start a new topic to ask your question.
2 REPLIES 2
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2015-12-30 10:38 AM
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; }
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2015-12-30 6:20 PM
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