Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions arch/arm/src/lpc54xx/lpc54_i2c_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
}

Expand Down Expand Up @@ -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);

Expand All @@ -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
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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 */

Expand Down
38 changes: 23 additions & 15 deletions arch/arm/src/rp2040/rp2040_i2c_slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;

/****************************************************************************
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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));
}

static void enable_i2c_slave(struct i2c_slave_s *dev)
{
irqstate_t flags;

leave_critical_section(flags);
flags = spin_lock_irqsave(&priv->spinlock);
enable_i2c_slave_nolock(dev);
spin_unlock_irqrestore(&priv->spinlock, flags);
}

/****************************************************************************
Expand All @@ -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));

Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
Loading