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:
patacongo
2011-09-09 19:50:18 +00:00
parent e42851c3fa
commit d075716e48
2 changed files with 54 additions and 54 deletions
+2
View File
@@ -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 */
+52 -54
View File
@@ -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)
{ {