Use small lock to protect resources related to i2c master and slave.
Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
This commit is contained in:
parent
f8501fa3ea
commit
2c4fe28d4e
7 changed files with 150 additions and 76 deletions
|
|
@ -60,7 +60,7 @@
|
|||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "chip.h"
|
||||
|
|
@ -136,6 +136,7 @@ struct lpc54_i2cdev_s
|
|||
int16_t result; /* The result of the transfer */
|
||||
|
||||
mutex_t lock; /* Only one thread can access at a time */
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
sem_t waitsem; /* Supports wait for state machine completion */
|
||||
uint16_t irq; /* Flexcomm IRQ number */
|
||||
|
|
@ -186,6 +187,7 @@ struct i2c_ops_s lpc54_i2c_ops =
|
|||
static struct lpc54_i2cdev_s g_i2c0_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -196,6 +198,7 @@ static struct lpc54_i2cdev_s g_i2c0_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c1_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -206,6 +209,7 @@ static struct lpc54_i2cdev_s g_i2c1_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c2_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -216,6 +220,7 @@ static struct lpc54_i2cdev_s g_i2c2_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c3_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -226,6 +231,7 @@ static struct lpc54_i2cdev_s g_i2c3_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c4_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -236,6 +242,7 @@ static struct lpc54_i2cdev_s g_i2c4_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c5_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -246,6 +253,7 @@ static struct lpc54_i2cdev_s g_i2c5_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c6_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -256,6 +264,7 @@ static struct lpc54_i2cdev_s g_i2c6_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c7_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -266,6 +275,7 @@ static struct lpc54_i2cdev_s g_i2c7_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c8_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -276,6 +286,7 @@ static struct lpc54_i2cdev_s g_i2c8_dev =
|
|||
static struct lpc54_i2cdev_s g_i2c9_dev =
|
||||
{
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
# ifndef CONFIG_I2C_POLLED
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
# endif
|
||||
|
|
@ -409,7 +420,7 @@ static void lpc54_i2c_timeout(wdparm_t arg)
|
|||
struct lpc54_i2cdev_s *priv = (struct lpc54_i2cdev_s *)arg;
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
irqstate_t flags = enter_critical_section();
|
||||
irqstate_t flags = spin_lock_irqsave(&priv->spinlock);
|
||||
#endif
|
||||
|
||||
i2cerr("ERROR: Timeout! state=%u\n", priv->state);
|
||||
|
|
@ -430,7 +441,7 @@ static void lpc54_i2c_timeout(wdparm_t arg)
|
|||
/* Wake up any waiters */
|
||||
|
||||
nxsem_post(&priv->waitsem);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -521,7 +532,7 @@ static bool lpc54_i2c_nextmsg(struct lpc54_i2cdev_s *priv)
|
|||
* here.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
i2cinfo("nmsgs=%u\n", priv->nmsgs - 1);
|
||||
|
||||
|
|
@ -535,7 +546,7 @@ static bool lpc54_i2c_nextmsg(struct lpc54_i2cdev_s *priv)
|
|||
lpc54_i2c_xfrsetup(priv);
|
||||
|
||||
i2cinfo("state=%u\n", priv->state);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
|
@ -552,7 +563,7 @@ static bool lpc54_i2c_nextmsg(struct lpc54_i2cdev_s *priv)
|
|||
priv->state = I2CSTATE_IDLE;
|
||||
|
||||
i2cinfo("state=%u\n", priv->state);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -903,7 +914,7 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
|||
|
||||
i2cinfo("port=%d\n", port);
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
/* Configure the requestin I2C peripheral */
|
||||
|
||||
|
|
@ -1252,12 +1263,12 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
i2cerr("ERROR: Unsupported port=%d\n", port);
|
||||
leave_critical_section(flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
/* Install our operations */
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/i2c/i2c_slave.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <arch/chip/i2c_slave.h>
|
||||
|
|
@ -77,6 +77,8 @@ typedef struct rp2040_i2c_slave_s
|
|||
|
||||
i2c_slave_callback_t *callback; /* Callback function */
|
||||
void *callback_arg; /* Argument for callback */
|
||||
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
} rp2040_i2c_slave_t;
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -123,6 +125,7 @@ rp2040_i2c_slave_t i2c0_slave_dev =
|
|||
{
|
||||
.dev.ops = &i2c_slaveops, /* Slave operations */
|
||||
.controller = 0, /* I2C controller number */
|
||||
.spinlock = SP_UNLOCKED, /* Spinlock */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -133,6 +136,7 @@ rp2040_i2c_slave_t i2c1_slave_dev =
|
|||
{
|
||||
.dev.ops = &i2c_slaveops, /* Slave operations */
|
||||
.controller = 1, /* I2C controller number */
|
||||
.spinlock = SP_UNLOCKED, /* Spinlock */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -312,12 +316,9 @@ static int i2c_interrupt(int irq, void *context, void *arg)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void enable_i2c_slave(struct i2c_slave_s *dev)
|
||||
static void enable_i2c_slave_nolock(struct i2c_slave_s *dev)
|
||||
{
|
||||
rp2040_i2c_slave_t *priv = (rp2040_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
uint32_t intr_mask = RP2040_I2C_IC_INTR_STAT_R_RD_REQ
|
||||
| RP2040_I2C_IC_INTR_STAT_R_RX_FULL
|
||||
|
|
@ -344,8 +345,15 @@ static void enable_i2c_slave(struct i2c_slave_s *dev)
|
|||
|
||||
putreg32(RP2040_I2C_IC_ENABLE_ENABLE,
|
||||
RP2040_I2C_IC_ENABLE(priv->controller));
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
static void enable_i2c_slave(struct i2c_slave_s *dev)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
enable_i2c_slave_nolock(dev);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -366,7 +374,7 @@ static int my_set_own_address(struct i2c_slave_s *dev,
|
|||
| RP2040_I2C_IC_CON_SPEED_FAST;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
putreg32(address, RP2040_I2C_IC_SAR(priv->controller));
|
||||
|
||||
|
|
@ -377,9 +385,9 @@ static int my_set_own_address(struct i2c_slave_s *dev,
|
|||
|
||||
putreg32(con, RP2040_I2C_IC_CON(priv->controller));
|
||||
|
||||
enable_i2c_slave(dev);
|
||||
enable_i2c_slave_nolock(dev);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -399,13 +407,13 @@ static int my_write(struct i2c_slave_s *dev,
|
|||
rp2040_i2c_slave_t *priv = (rp2040_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
priv->tx_buffer = buffer;
|
||||
priv->tx_buf_ptr = buffer;
|
||||
priv->tx_buf_end = priv->tx_buffer + length;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -426,13 +434,13 @@ static int my_read(struct i2c_slave_s *dev,
|
|||
rp2040_i2c_slave_t *priv = (rp2040_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
priv->rx_buffer = buffer;
|
||||
priv->rx_buf_ptr = buffer;
|
||||
priv->rx_buf_end = priv->rx_buffer + length;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -453,12 +461,12 @@ static int my_register_callback(struct i2c_slave_s *dev,
|
|||
rp2040_i2c_slave_t *priv = (rp2040_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
priv->callback = callback;
|
||||
priv->callback_arg = arg;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/i2c/i2c_slave.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <arch/chip/i2c_slave.h>
|
||||
|
|
@ -77,6 +77,8 @@ typedef struct rp23xx_i2c_slave_s
|
|||
|
||||
i2c_slave_callback_t *callback; /* Callback function */
|
||||
void *callback_arg; /* Argument for callback */
|
||||
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
} rp23xx_i2c_slave_t;
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -123,6 +125,7 @@ rp23xx_i2c_slave_t i2c0_slave_dev =
|
|||
{
|
||||
.dev.ops = &i2c_slaveops, /* Slave operations */
|
||||
.controller = 0, /* I2C controller number */
|
||||
.spinlock = SP_UNLOCKED, /* Spinlock */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -133,6 +136,7 @@ rp23xx_i2c_slave_t i2c1_slave_dev =
|
|||
{
|
||||
.dev.ops = &i2c_slaveops, /* Slave operations */
|
||||
.controller = 1, /* I2C controller number */
|
||||
.spinlock = SP_UNLOCKED, /* Spinlock */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -312,12 +316,9 @@ static int i2c_interrupt(int irq, void *context, void *arg)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void enable_i2c_slave(struct i2c_slave_s *dev)
|
||||
static void enable_i2c_slave_nolock(struct i2c_slave_s *dev)
|
||||
{
|
||||
rp23xx_i2c_slave_t *priv = (rp23xx_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
uint32_t intr_mask = RP23XX_I2C_IC_INTR_STAT_R_RD_REQ
|
||||
| RP23XX_I2C_IC_INTR_STAT_R_RX_FULL
|
||||
|
|
@ -344,8 +345,15 @@ static void enable_i2c_slave(struct i2c_slave_s *dev)
|
|||
|
||||
putreg32(RP23XX_I2C_IC_ENABLE_ENABLE,
|
||||
RP23XX_I2C_IC_ENABLE(priv->controller));
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
static void enable_i2c_slave(struct i2c_slave_s *dev)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
enable_i2c_slave_nolock(dev);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -366,7 +374,7 @@ static int my_set_own_address(struct i2c_slave_s *dev,
|
|||
| RP23XX_I2C_IC_CON_SPEED_FAST;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
putreg32(address, RP23XX_I2C_IC_SAR(priv->controller));
|
||||
|
||||
|
|
@ -377,9 +385,9 @@ static int my_set_own_address(struct i2c_slave_s *dev,
|
|||
|
||||
putreg32(con, RP23XX_I2C_IC_CON(priv->controller));
|
||||
|
||||
enable_i2c_slave(dev);
|
||||
enable_i2c_slave_nolock(dev);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -399,13 +407,13 @@ static int my_write(struct i2c_slave_s *dev,
|
|||
rp23xx_i2c_slave_t *priv = (rp23xx_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
priv->tx_buffer = buffer;
|
||||
priv->tx_buf_ptr = buffer;
|
||||
priv->tx_buf_end = priv->tx_buffer + length;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -426,13 +434,13 @@ static int my_read(struct i2c_slave_s *dev,
|
|||
rp23xx_i2c_slave_t *priv = (rp23xx_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
priv->rx_buffer = buffer;
|
||||
priv->rx_buf_ptr = buffer;
|
||||
priv->rx_buf_end = priv->rx_buffer + length;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -453,12 +461,12 @@ static int my_register_callback(struct i2c_slave_s *dev,
|
|||
rp23xx_i2c_slave_t *priv = (rp23xx_i2c_slave_t *) dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
priv->callback = callback;
|
||||
priv->callback_arg = arg;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/mutex.h>
|
||||
|
|
@ -171,6 +171,7 @@ struct sam_i2c_dev_s
|
|||
uint16_t nextflags; /* Next message flags */
|
||||
|
||||
mutex_t lock; /* Only one thread can access at a time */
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
sem_t waitsem; /* Wait for I2C transfer completion */
|
||||
volatile int result; /* The result of the transfer */
|
||||
volatile int xfrd; /* Number of bytes transfers */
|
||||
|
|
@ -284,6 +285,7 @@ static struct sam_i2c_dev_s g_i2c0 =
|
|||
},
|
||||
.attr = &g_i2c0attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -310,6 +312,7 @@ static struct sam_i2c_dev_s g_i2c1 =
|
|||
},
|
||||
.attr = &g_i2c1attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -337,6 +340,7 @@ static struct sam_i2c_dev_s g_i2c2 =
|
|||
},
|
||||
.attr = &g_i2c2attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -364,6 +368,7 @@ static struct sam_i2c_dev_s g_i2c3 =
|
|||
},
|
||||
.attr = &g_i2c3attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -391,6 +396,7 @@ static struct sam_i2c_dev_s g_i2c4 =
|
|||
},
|
||||
.attr = &g_i2c4attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -418,6 +424,7 @@ static struct sam_i2c_dev_s g_i2c5 =
|
|||
},
|
||||
.attr = &g_i2c5attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -1018,14 +1025,16 @@ static int sam_i2c_transfer(struct i2c_master_s *dev,
|
|||
{
|
||||
priv->msg = msgs;
|
||||
priv->nextflags = count == 0 ? 0 : msgs[1].flags;
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
i2c_startmessage(priv, msgs);
|
||||
|
||||
/* And wait for the transfers to complete.
|
||||
* Interrupts will be re-enabled while we are waiting.
|
||||
*/
|
||||
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
ret = i2c_wait_for_bus(priv, msgs->length);
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -1040,12 +1049,12 @@ static int sam_i2c_transfer(struct i2c_master_s *dev,
|
|||
i2c_putreg8(priv, I2C_INT_MB | I2C_INT_SB,
|
||||
SAM_I2C_INTENCLR_OFFSET);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
/* Move to the next message */
|
||||
|
||||
|
|
@ -1169,9 +1178,9 @@ static uint32_t sam_i2c_setfrequency(struct sam_i2c_dev_s *priv,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
||||
static void i2c_hw_initialize_nolock(struct sam_i2c_dev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
uint32_t ctrla = 0;
|
||||
|
||||
|
|
@ -1179,7 +1188,6 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
|
||||
/* Enable clocking to the SERCOM module in PM */
|
||||
|
||||
flags = enter_critical_section();
|
||||
sercom_enable(priv->attr->sercom);
|
||||
|
||||
/* Configure the GCLKs for the SERCOM module */
|
||||
|
|
@ -1194,7 +1202,6 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
{
|
||||
i2cerr
|
||||
("ERROR: Cannot initialize I2C because it is already initialized!\n");
|
||||
leave_critical_section(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1204,7 +1211,6 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
if (regval & I2C_CTRLA_SWRST)
|
||||
{
|
||||
i2cerr("ERROR: Module is in RESET process!\n");
|
||||
leave_critical_section(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1244,7 +1250,15 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
/* Enable SERCOM interrupts at the NVIC */
|
||||
|
||||
up_enable_irq(priv->attr->irq);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
i2c_hw_initialize_nolock(priv, frequency);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -1369,7 +1383,7 @@ struct i2c_master_s *sam_i2c_master_initialize(int bus)
|
|||
|
||||
/* Perform one-time I2C initialization */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
/* Attach Interrupt Handler */
|
||||
|
||||
|
|
@ -1377,14 +1391,14 @@ struct i2c_master_s *sam_i2c_master_initialize(int bus)
|
|||
if (ret < 0)
|
||||
{
|
||||
i2cerr("ERROR: Failed to attach irq %d\n", priv->attr->irq);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Perform repeatable I2C hardware initialization */
|
||||
|
||||
i2c_hw_initialize(priv, frequency);
|
||||
leave_critical_section(flags);
|
||||
i2c_hw_initialize_nolock(priv, frequency);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return &priv->dev;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/mutex.h>
|
||||
|
|
@ -165,6 +165,7 @@ struct sam_i2c_dev_s
|
|||
uint16_t nextflags; /* Next message flags */
|
||||
|
||||
mutex_t lock; /* Only one thread can access at a time */
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
sem_t waitsem; /* Wait for I2C transfer completion */
|
||||
volatile int result; /* The result of the transfer */
|
||||
volatile int xfrd; /* Number of bytes transfers */
|
||||
|
|
@ -276,6 +277,7 @@ static struct sam_i2c_dev_s g_i2c0 =
|
|||
},
|
||||
.attr = &g_i2c0attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -303,6 +305,7 @@ static struct sam_i2c_dev_s g_i2c1 =
|
|||
},
|
||||
.attr = &g_i2c1attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -330,6 +333,7 @@ static struct sam_i2c_dev_s g_i2c2 =
|
|||
},
|
||||
.attr = &g_i2c2attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -357,6 +361,7 @@ static struct sam_i2c_dev_s g_i2c3 =
|
|||
},
|
||||
.attr = &g_i2c3attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -384,6 +389,7 @@ static struct sam_i2c_dev_s g_i2c4 =
|
|||
},
|
||||
.attr = &g_i2c4attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -411,6 +417,7 @@ static struct sam_i2c_dev_s g_i2c5 =
|
|||
},
|
||||
.attr = &g_i2c5attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -438,6 +445,7 @@ static struct sam_i2c_dev_s g_i2c6 =
|
|||
},
|
||||
.attr = &g_i2c6attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -465,6 +473,7 @@ static struct sam_i2c_dev_s g_i2c7 =
|
|||
},
|
||||
.attr = &g_i2c7attr,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
.waitsem = SEM_INITIALIZER(0),
|
||||
};
|
||||
#endif
|
||||
|
|
@ -1068,22 +1077,24 @@ static int sam_i2c_transfer(struct i2c_master_s *dev,
|
|||
{
|
||||
priv->msg = msgs;
|
||||
priv->nextflags = count == 0 ? 0 : msgs[1].flags;
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
i2c_startmessage(priv, msgs);
|
||||
|
||||
/* And wait for the transfers to complete.
|
||||
* Interrupts will be re-enabled while we are waiting.
|
||||
*/
|
||||
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
ret = i2c_wait_for_bus(priv, msgs->length);
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
/* Move to the next message */
|
||||
|
||||
|
|
@ -1209,9 +1220,9 @@ static uint32_t sam_i2c_setfrequency(struct sam_i2c_dev_s *priv,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
||||
static void i2c_hw_initialize_nolock(struct sam_i2c_dev_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
uint32_t ctrla = 0;
|
||||
|
||||
|
|
@ -1219,7 +1230,6 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
|
||||
/* Enable clocking to the SERCOM module in PM */
|
||||
|
||||
flags = enter_critical_section();
|
||||
sercom_enable(priv->attr->sercom);
|
||||
|
||||
/* Configure the GCLKs for the SERCOM module */
|
||||
|
|
@ -1234,7 +1244,6 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
{
|
||||
i2cerr("ERROR: Cannot initialize I2C "
|
||||
"because it is already initialized!\n");
|
||||
leave_critical_section(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1244,7 +1253,6 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
if (regval & I2C_CTRLA_SWRST)
|
||||
{
|
||||
i2cerr("ERROR: Module is in RESET process!\n");
|
||||
leave_critical_section(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1288,7 +1296,15 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
|||
|
||||
up_enable_irq(priv->attr->irq);
|
||||
up_enable_irq(priv->attr->irq + 1);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
i2c_hw_initialize_nolock(priv, frequency);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -1433,7 +1449,7 @@ struct i2c_master_s *sam_i2c_master_initialize(int bus)
|
|||
|
||||
/* Perform one-time I2C initialization */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
/* Attach Interrupt Handler */
|
||||
|
||||
|
|
@ -1441,7 +1457,7 @@ struct i2c_master_s *sam_i2c_master_initialize(int bus)
|
|||
if (ret < 0)
|
||||
{
|
||||
i2cerr("ERROR: Failed to attach irq %d\n", priv->attr->irq);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1449,14 +1465,14 @@ struct i2c_master_s *sam_i2c_master_initialize(int bus)
|
|||
if (ret < 0)
|
||||
{
|
||||
i2cerr("ERROR: Failed to attach irq %d\n", priv->attr->irq);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Perform repeatable I2C hardware initialization */
|
||||
|
||||
i2c_hw_initialize(priv, frequency);
|
||||
leave_critical_section(flags);
|
||||
i2c_hw_initialize_nolock(priv, frequency);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return &priv->dev;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
|
|
@ -288,6 +288,7 @@ struct stm32_i2c_priv_s
|
|||
|
||||
int refs; /* Reference count */
|
||||
mutex_t lock; /* Mutual exclusion mutex */
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
sem_t sem_isr; /* Interrupt wait semaphore */
|
||||
#endif
|
||||
|
|
@ -406,6 +407,7 @@ static struct stm32_i2c_priv_s stm32_i2c1_priv =
|
|||
.config = &stm32_i2c1_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -439,6 +441,7 @@ static struct stm32_i2c_priv_s stm32_i2c2_priv =
|
|||
.config = &stm32_i2c2_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -472,6 +475,7 @@ static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
|||
.config = &stm32_i2c3_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -577,7 +581,7 @@ static int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
uint32_t regval;
|
||||
int ret;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
/* Enable I2C interrupts */
|
||||
|
||||
|
|
@ -593,6 +597,8 @@ static int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
priv->intstate = INTSTATE_WAITING;
|
||||
do
|
||||
{
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
/* Wait until either the transfer is complete or the timeout expires */
|
||||
|
||||
#ifdef CONFIG_STM32_I2C_DYNTIMEO
|
||||
|
|
@ -611,6 +617,8 @@ static int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
}
|
||||
|
||||
/* Loop until the interrupt level transfer is complete. */
|
||||
|
|
@ -627,7 +635,7 @@ static int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
regval &= ~I2C_CR2_ALLINTS;
|
||||
stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
|
@ -407,6 +407,7 @@ struct stm32_i2c_priv_s
|
|||
|
||||
int refs; /* Reference count */
|
||||
mutex_t lock; /* Mutual exclusion mutex */
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
sem_t sem_isr; /* Interrupt wait semaphore */
|
||||
#endif
|
||||
|
|
@ -520,6 +521,7 @@ static struct stm32_i2c_priv_s stm32_i2c1_priv =
|
|||
.config = &stm32_i2c1_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -556,6 +558,7 @@ static struct stm32_i2c_priv_s stm32_i2c2_priv =
|
|||
.config = &stm32_i2c2_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -592,6 +595,7 @@ static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
|||
.config = &stm32_i2c3_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -628,6 +632,7 @@ static struct stm32_i2c_priv_s stm32_i2c4_priv =
|
|||
.config = &stm32_i2c4_config,
|
||||
.refs = 0,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
.spinlock = SP_UNLOCKED,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
|
|
@ -793,7 +798,7 @@ static inline int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
|
||||
/* Enable I2C interrupts */
|
||||
|
||||
|
|
@ -810,6 +815,8 @@ static inline int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
priv->intstate = INTSTATE_WAITING;
|
||||
do
|
||||
{
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
|
||||
/* Wait until either the transfer is complete or the timeout expires */
|
||||
|
||||
#ifdef CONFIG_STM32_I2C_DYNTIMEO
|
||||
|
|
@ -828,6 +835,8 @@ static inline int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
flags = spin_lock_irqsave(&priv->spinlock);
|
||||
}
|
||||
|
||||
/* Loop until the interrupt level transfer is complete. */
|
||||
|
|
@ -842,7 +851,7 @@ static inline int stm32_i2c_sem_waitdone(struct stm32_i2c_priv_s *priv)
|
|||
|
||||
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ALLINTS, 0);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&priv->spinlock, flags);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
|
@ -1742,7 +1751,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
|
|||
*/
|
||||
|
||||
#ifdef CONFIG_I2C_POLLED
|
||||
irqstate_t state = enter_critical_section();
|
||||
irqstate_t state = spin_lock_irqsave(&priv->spinlock);
|
||||
#endif
|
||||
/* Receive a byte */
|
||||
|
||||
|
|
@ -1759,7 +1768,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
|
|||
priv->dcnt--;
|
||||
|
||||
#ifdef CONFIG_I2C_POLLED
|
||||
leave_critical_section(state);
|
||||
spin_unlock_irqrestore(&priv->spinlock, state);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue