mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Only enable I2C interrupts when a transfer is started
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3945 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -107,6 +107,8 @@
|
|||||||
#define I2C_CR2_DMAEN (1 << 11) /* Bit 11: DMA Requests Enable */
|
#define I2C_CR2_DMAEN (1 << 11) /* Bit 11: DMA Requests Enable */
|
||||||
#define I2C_CR2_LAST (1 << 12) /* Bit 12: DMA Last Transfer */
|
#define I2C_CR2_LAST (1 << 12) /* Bit 12: DMA Last Transfer */
|
||||||
|
|
||||||
|
#define I2C_CR2_ALLINTS (I2C_CR2_ITERREN|I2C_CR2_ITEVFEN|I2C_CR2_ITBUFEN)
|
||||||
|
|
||||||
/* Own address register 1 */
|
/* Own address register 1 */
|
||||||
|
|
||||||
#define I2C_OAR1_ADD0 (1 << 0) /* Bit 0: Interface Address */
|
#define I2C_OAR1_ADD0 (1 << 0) /* Bit 0: Interface Address */
|
||||||
|
|||||||
@@ -109,6 +109,21 @@
|
|||||||
# define CONFIG_STM32_I2CTIMEOMS 0 /* User provided seconds */
|
# define CONFIG_STM32_I2CTIMEOMS 0 /* User provided seconds */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Debug ****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_I2C
|
||||||
|
# define i2cdbg dbg
|
||||||
|
# ifdef CONFIG_DEBUG_I2CINTS
|
||||||
|
# define intdbg lldbg
|
||||||
|
# else
|
||||||
|
# define intdbg(x...)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# undef CONFIG_DEBUG_I2CINTS
|
||||||
|
# define i2cdbg(x...)
|
||||||
|
# define intdbg(x...)
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@@ -220,9 +235,17 @@ int inline stm32_i2c_sem_waitisr(FAR struct i2c_dev_s *dev)
|
|||||||
FAR struct stm32_i2c_priv_s *priv = ((struct stm32_i2c_inst_s *)dev)->priv;
|
FAR struct stm32_i2c_priv_s *priv = ((struct stm32_i2c_inst_s *)dev)->priv;
|
||||||
struct timespec abstime;
|
struct timespec abstime;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
uint32_t regval;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
|
||||||
|
/* Enable I2C interrupts */
|
||||||
|
|
||||||
|
regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
|
||||||
|
regval |= (I2C_CR2_ITERREN | I2C_CR2_ITEVFEN);
|
||||||
|
stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Get the current time */
|
/* Get the current time */
|
||||||
@@ -250,6 +273,11 @@ int inline stm32_i2c_sem_waitisr(FAR struct i2c_dev_s *dev)
|
|||||||
}
|
}
|
||||||
while (ret != OK && errno == EINTR);
|
while (ret != OK && errno == EINTR);
|
||||||
|
|
||||||
|
/* Disable I2C interrupts */
|
||||||
|
|
||||||
|
regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
|
||||||
|
regval &= ~I2C_CR2_ALLINTS;
|
||||||
|
stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -437,21 +465,18 @@ static inline void stm32_i2c_enablefsmc(uint32_t ahbenr)
|
|||||||
* Interrupt Service Routines
|
* Interrupt Service Routines
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
//DEBUG TO BE CLEANED
|
|
||||||
//#define NON_ISR
|
|
||||||
|
|
||||||
static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
|
static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
|
||||||
{
|
{
|
||||||
uint32_t status = stm32_i2c_getstatus(priv);
|
uint32_t status = stm32_i2c_getstatus(priv);
|
||||||
|
|
||||||
#ifdef NON_ISR
|
#ifdef CONFIG_DEBUG_I2CINTS
|
||||||
static uint32_t isr_count = 0;
|
static uint32_t isr_count = 0;
|
||||||
static uint32_t old_status = 0xFFFF;
|
static uint32_t old_status = 0xFFFF;
|
||||||
isr_count++;
|
isr_count++;
|
||||||
|
|
||||||
if (old_status != status)
|
if (old_status != status)
|
||||||
{
|
{
|
||||||
printf("status = %8x, count=%d\n", status, isr_count); fflush(stdout);
|
intdbg("status = %8x, count=%d\n", status, isr_count); fflush(stdout);
|
||||||
old_status = status;
|
old_status = status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -501,9 +526,8 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
|
|||||||
if (--priv->dcnt >= 0)
|
if (--priv->dcnt >= 0)
|
||||||
{
|
{
|
||||||
/* Send a byte */
|
/* Send a byte */
|
||||||
#ifdef NON_ISR
|
|
||||||
printf("Send byte: %2x\n", *priv->ptr);
|
intdbg("Send byte: %2x\n", *priv->ptr);
|
||||||
#endif
|
|
||||||
stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);
|
stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -521,15 +545,12 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
|
|||||||
{
|
{
|
||||||
/* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
|
/* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
|
||||||
|
|
||||||
#ifdef NON_ISR
|
intdbg("dcnt=%d\n", priv->dcnt);
|
||||||
printf("dcnt=%d\n", priv->dcnt);
|
|
||||||
#endif
|
|
||||||
if (--priv->dcnt >= 0)
|
if (--priv->dcnt >= 0)
|
||||||
{
|
{
|
||||||
*priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
|
*priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
|
||||||
#ifdef NON_ISR
|
intdbg("Received: %2x\n", *(priv->ptr-1) );
|
||||||
printf("Received: %2x\n", *(priv->ptr-1) );
|
|
||||||
#endif
|
|
||||||
/* Disable acknowledge when last byte is to be received */
|
/* Disable acknowledge when last byte is to be received */
|
||||||
|
|
||||||
if (priv->dcnt == 1)
|
if (priv->dcnt == 1)
|
||||||
@@ -556,9 +577,7 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
|
|||||||
|
|
||||||
if (priv->dcnt<=0 && (status & I2C_SR1_BTF))
|
if (priv->dcnt<=0 && (status & I2C_SR1_BTF))
|
||||||
{
|
{
|
||||||
#ifdef NON_ISR
|
intdbg("BTF\n");
|
||||||
printf("BTF\n");
|
|
||||||
#endif
|
|
||||||
stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET); /* ACK ISR */
|
stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET); /* ACK ISR */
|
||||||
|
|
||||||
/* Do we need to terminate or restart after this byte */
|
/* Do we need to terminate or restart after this byte */
|
||||||
@@ -590,9 +609,7 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
|
|||||||
}
|
}
|
||||||
else if (priv->msgv)
|
else if (priv->msgv)
|
||||||
{
|
{
|
||||||
#ifdef NON_ISR
|
intdbg("stop2: status = %8x\n", status);
|
||||||
printf("stop2: status = %8x\n", status);
|
|
||||||
#endif
|
|
||||||
stm32_i2c_sendstop(priv);
|
stm32_i2c_sendstop(priv);
|
||||||
if (priv->isr_wait)
|
if (priv->isr_wait)
|
||||||
{
|
{
|
||||||
@@ -674,7 +691,7 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attach ISRs */
|
/* Attach ISRs */
|
||||||
|
|
||||||
irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_isr);
|
irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_isr);
|
||||||
irq_attach(STM32_IRQ_I2C1ER, stm32_i2c1_isr);
|
irq_attach(STM32_IRQ_I2C1ER, stm32_i2c1_isr);
|
||||||
@@ -719,17 +736,11 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set peripheral frequency, where it must be at least 2 MHz
|
/* Set peripheral frequency, where it must be at least 2 MHz for 100 kHz
|
||||||
* for 100 kHz or 4 MHz for 400 kHz. Enable interrupt generation.
|
* or 4 MHz for 400 kHz. This also disables all I2C interrupts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET,
|
stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, (STM32_PCLK1_FREQUENCY / 1000000));
|
||||||
#ifndef NON_ISR
|
|
||||||
I2C_CR2_ITERREN | I2C_CR2_ITEVFEN | // I2C_CR2_ITBUFEN |
|
|
||||||
#endif
|
|
||||||
(STM32_PCLK1_FREQUENCY / 1000000)
|
|
||||||
);
|
|
||||||
|
|
||||||
stm32_i2c_setclock(priv, 100000);
|
stm32_i2c_setclock(priv, 100000);
|
||||||
|
|
||||||
/* Enable I2C */
|
/* Enable I2C */
|
||||||
@@ -824,7 +835,7 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
ahbenr = stm32_i2c_disablefsmc(inst->priv);
|
ahbenr = stm32_i2c_disablefsmc(inst->priv);
|
||||||
|
|
||||||
/* wait as stop might still be in progress
|
/* Wait as stop might still be in progress
|
||||||
*
|
*
|
||||||
* \todo GET RID OF THIS PERFORMANCE LOSS and for() loop
|
* \todo GET RID OF THIS PERFORMANCE LOSS and for() loop
|
||||||
*/
|
*/
|
||||||
@@ -839,27 +850,20 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
inst->priv->msgv = msgs;
|
inst->priv->msgv = msgs;
|
||||||
inst->priv->msgc = count;
|
inst->priv->msgc = count;
|
||||||
|
|
||||||
/* Set clock (on change it toggles I2C_CR1_PE !) */
|
/* Set I2C clock frequency (on change it toggles I2C_CR1_PE !) */
|
||||||
|
|
||||||
stm32_i2c_setclock(inst->priv, inst->frequency);
|
stm32_i2c_setclock(inst->priv, inst->frequency);
|
||||||
|
|
||||||
/* Trigger start condition, then the process moves into the ISR */
|
/* Clear any pending error interrupts */
|
||||||
|
|
||||||
|
stm32_i2c_putreg(inst->priv, STM32_I2C_SR1_OFFSET, 0);
|
||||||
|
|
||||||
|
/* Trigger start condition, then the process moves into the ISR. I2C
|
||||||
|
* interrupts will be enabled within stm32_i2c_waitisr().
|
||||||
|
*/
|
||||||
|
|
||||||
stm32_i2c_sendstart(inst->priv);
|
stm32_i2c_sendstart(inst->priv);
|
||||||
|
|
||||||
#ifdef NON_ISR
|
|
||||||
do
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
stm32_i2c_isr(&stm32_i2c1_priv);
|
|
||||||
status = inst->priv->status;
|
|
||||||
}
|
|
||||||
while (status & (I2C_SR2_BUSY << 16));
|
|
||||||
}
|
|
||||||
while( sem_trywait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr ) != 0 );
|
|
||||||
#else
|
|
||||||
#if 1
|
|
||||||
/* Wait for an ISR, if there was a timeout, fetch latest status to get
|
/* Wait for an ISR, if there was a timeout, fetch latest status to get
|
||||||
* the BUSY flag.
|
* the BUSY flag.
|
||||||
*/
|
*/
|
||||||
@@ -883,14 +887,8 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
status = inst->priv->status & 0xffff;
|
status = inst->priv->status & 0xffff;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
do
|
/* Check for error status conditions */
|
||||||
{
|
|
||||||
printf("%x, %d\n", inst->priv->status, isr_count );
|
|
||||||
}
|
|
||||||
while( sem_trywait( &inst->priv->sem_isr ) != 0 );
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (status & I2C_SR1_BERR)
|
if (status & I2C_SR1_BERR)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user