diff --git a/arch/arm/src/at32/at32_i2c.c b/arch/arm/src/at32/at32_i2c.c index bf3620d5f0bd6..ffd7d05f133a7 100644 --- a/arch/arm/src/at32/at32_i2c.c +++ b/arch/arm/src/at32/at32_i2c.c @@ -151,7 +151,7 @@ #include #include -#include +#include #include #include #include @@ -316,6 +316,7 @@ struct at32_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 @@ -429,6 +430,7 @@ static struct at32_i2c_priv_s at32_i2c1_priv = .config = &at32_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -465,6 +467,7 @@ static struct at32_i2c_priv_s at32_i2c2_priv = .config = &at32_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -501,6 +504,7 @@ static struct at32_i2c_priv_s at32_i2c3_priv = .config = &at32_i2c3_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -666,7 +670,7 @@ static inline int at32_i2c_sem_waitdone(struct at32_i2c_priv_s *priv) irqstate_t flags; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Enable I2C interrupts */ @@ -683,6 +687,8 @@ static inline int at32_i2c_sem_waitdone(struct at32_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_AT32_I2C_DYNTIMEO @@ -701,6 +707,8 @@ static inline int at32_i2c_sem_waitdone(struct at32_i2c_priv_s *priv) break; } + + flags = spin_lock_irqsave(&priv->spinlock); } /* Loop until the interrupt level transfer is complete. */ @@ -715,7 +723,7 @@ static inline int at32_i2c_sem_waitdone(struct at32_i2c_priv_s *priv) at32_i2c_modifyreg32(priv, AT32_I2C_CR1_OFFSET, I2C_CR1_ALLINTS, 0); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return ret; } #else @@ -1616,7 +1624,7 @@ static int at32_i2c_isr_process(struct at32_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 */ @@ -1633,7 +1641,7 @@ static int at32_i2c_isr_process(struct at32_i2c_priv_s *priv) priv->dcnt--; #ifdef CONFIG_I2C_POLLED - leave_critical_section(state); + spin_unlock_irqrestore(&priv->spinlock, state); #endif } else diff --git a/arch/arm/src/cxd56xx/cxd56_i2c.c b/arch/arm/src/cxd56xx/cxd56_i2c.c index 582a0643bddf5..d63c20a625c25 100644 --- a/arch/arm/src/cxd56xx/cxd56_i2c.c +++ b/arch/arm/src/cxd56xx/cxd56_i2c.c @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -84,6 +84,7 @@ struct cxd56_i2cdev_s uint32_t base_freq; /* branch frequency */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for transfer completion */ struct wdog_s timeout; /* watchdog to timeout when bus hung */ uint32_t frequency; /* Current I2C frequency */ @@ -108,6 +109,7 @@ static struct cxd56_i2cdev_s g_i2c0dev = .base = CXD56_SCU_I2C0_BASE, .irqid = CXD56_IRQ_SCU_I2C0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -119,6 +121,7 @@ static struct cxd56_i2cdev_s g_i2c1dev = .base = CXD56_SCU_I2C1_BASE, .irqid = CXD56_IRQ_SCU_I2C1, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -130,6 +133,7 @@ static struct cxd56_i2cdev_s g_i2c2dev = .base = CXD56_I2CM_BASE, .irqid = CXD56_IRQ_I2CM, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -358,11 +362,11 @@ static void cxd56_i2c_setfrequency(struct cxd56_i2cdev_s *priv, static void cxd56_i2c_timeout(wdparm_t arg) { struct cxd56_i2cdev_s *priv = (struct cxd56_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->error = -ENODEV; nxsem_post(&priv->wait); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -521,7 +525,7 @@ static int cxd56_i2c_receive(struct cxd56_i2cdev_s *priv, int last) i2c_reg_write(priv, CXD56_IC_DATA_CMD, CMD_READ); } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); wd_start(&priv->timeout, I2C_TIMEOUT, cxd56_i2c_timeout, (wdparm_t)priv); @@ -530,7 +534,7 @@ static int cxd56_i2c_receive(struct cxd56_i2cdev_s *priv, int last) i2c_reg_write(priv, CXD56_IC_DATA_CMD, CMD_READ | (en ? CMD_STOP : 0)); i2c_reg_rmw(priv, CXD56_IC_INTR_MASK, INTR_RX_FULL, INTR_RX_FULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxsem_wait_uninterruptible(&priv->wait); if (priv->error != OK) @@ -567,7 +571,7 @@ static int cxd56_i2c_send(struct cxd56_i2cdev_s *priv, int last) while (!(i2c_reg_read(priv, CXD56_IC_STATUS) & STATUS_TFNF)); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); wd_start(&priv->timeout, I2C_TIMEOUT, cxd56_i2c_timeout, (wdparm_t)priv); i2c_reg_write(priv, CXD56_IC_DATA_CMD, @@ -576,7 +580,7 @@ static int cxd56_i2c_send(struct cxd56_i2cdev_s *priv, int last) /* Enable TX_EMPTY interrupt for determine transfer done. */ i2c_reg_rmw(priv, CXD56_IC_INTR_MASK, INTR_TX_EMPTY, INTR_TX_EMPTY); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxsem_wait_uninterruptible(&priv->wait); return 0; diff --git a/arch/arm/src/gd32f4/gd32f4xx_i2c.c b/arch/arm/src/gd32f4/gd32f4xx_i2c.c index 9c4353f935764..73d53f1a22057 100644 --- a/arch/arm/src/gd32f4/gd32f4xx_i2c.c +++ b/arch/arm/src/gd32f4/gd32f4xx_i2c.c @@ -66,7 +66,7 @@ #include #include -#include +#include #include #include #include @@ -243,6 +243,7 @@ struct gd32_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 @@ -378,6 +379,7 @@ static struct gd32_i2c_priv_s gd32_i2c0_priv = .config = &gd32_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -413,6 +415,7 @@ static struct gd32_i2c_priv_s gd32_i2c1_priv = .config = &gd32_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -448,6 +451,7 @@ static struct gd32_i2c_priv_s gd32_i2c2_priv = .config = &gd32_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -691,7 +695,7 @@ static inline int gd32_i2c_sem_waitdone(struct gd32_i2c_priv_s *priv) uint32_t regval; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Enable I2C interrupts */ @@ -707,6 +711,8 @@ static inline int gd32_i2c_sem_waitdone(struct gd32_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_GD32F4_I2C_DYNTIMEO @@ -725,6 +731,8 @@ static inline int gd32_i2c_sem_waitdone(struct gd32_i2c_priv_s *priv) break; } + + flags = spin_lock_irqsave(&priv->spinlock); } /* Loop until the interrupt level transfer is complete. */ @@ -741,7 +749,8 @@ static inline int gd32_i2c_sem_waitdone(struct gd32_i2c_priv_s *priv) regval &= ~I2C_CTL1_INTS_MASK; gd32_i2c_putreg(priv, GD32_I2C_CTL1_OFFSET, regval); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); + return ret; } #else diff --git a/arch/arm/src/kinetis/kinetis_i2c.c b/arch/arm/src/kinetis/kinetis_i2c.c index 7267c7dac05d2..836902fbea672 100644 --- a/arch/arm/src/kinetis/kinetis_i2c.c +++ b/arch/arm/src/kinetis/kinetis_i2c.c @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -116,6 +116,7 @@ struct kinetis_i2cdev_s volatile uint8_t state; /* State of state machine */ bool restart; /* Should next transfer restart or not */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for state machine completion */ struct wdog_s timeout; /* watchdog to timeout when bus hung */ struct i2c_msg_s *msgs; /* Remaining transfers - first one is in @@ -193,6 +194,7 @@ static struct kinetis_i2cdev_s g_i2c0_dev = .config = &kinetis_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .state = STATE_OK, .msgs = NULL, @@ -216,6 +218,7 @@ static struct kinetis_i2cdev_s g_i2c1_dev = .config = &kinetis_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .state = STATE_OK, .msgs = NULL, @@ -239,6 +242,7 @@ static struct kinetis_i2cdev_s g_i2c2_dev = .config = &kinetis_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .state = STATE_OK, .msgs = NULL, @@ -262,6 +266,7 @@ static struct kinetis_i2cdev_s g_i2c3_dev = .config = &kinetis_i2c3_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .state = STATE_OK, .msgs = NULL, @@ -818,10 +823,10 @@ static void kinetis_i2c_timeout(wdparm_t arg) DEBUGASSERT(priv != NULL); i2cinfo("Timeout msg=%p\n", priv->msgs); - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->state = STATE_TIMEOUT; kinetis_i2c_endwait(priv); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** diff --git a/arch/arm/src/lc823450/lc823450_i2c.c b/arch/arm/src/lc823450/lc823450_i2c.c index 5632b5ea6b090..112bf70d7f0d7 100644 --- a/arch/arm/src/lc823450/lc823450_i2c.c +++ b/arch/arm/src/lc823450/lc823450_i2c.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include #include @@ -121,6 +121,7 @@ struct lc823450_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 @@ -209,6 +210,7 @@ static struct lc823450_i2c_priv_s lc823450_i2c0_priv = .config = &lc823450_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -239,6 +241,7 @@ static struct lc823450_i2c_priv_s lc823450_i2c1_priv = .config = &lc823450_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -1005,7 +1008,7 @@ static int lc823450_i2c_transfer(struct i2c_master_s *dev, if (lc823450_i2c_sem_waitdone(priv) < 0) { - irqs = enter_critical_section(); + irqs = spin_lock_irqsave(&priv->spinlock); ret = -ETIMEDOUT; @@ -1017,7 +1020,7 @@ static int lc823450_i2c_transfer(struct i2c_master_s *dev, priv->timedout = true; - leave_critical_section(irqs); + spin_unlock_irqrestore(&priv->spinlock, irqs); /* Wait for irq handler completion. 10msec wait is probably enough * to terminate i2c transaction, NACK and STOP contition for read @@ -1028,10 +1031,9 @@ static int lc823450_i2c_transfer(struct i2c_master_s *dev, } else { + spin_unlock_irqrestore(&priv->spinlock, irqs); i2cerr("No need of timeout handling. " "It may be done in irq handler\n"); - - leave_critical_section(irqs); } #ifndef CONFIG_LC823450_IPL2 diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c index 642557ec6b218..5b65332917628 100644 --- a/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c +++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_i2c.c @@ -60,7 +60,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -105,6 +105,7 @@ struct lpc17_40_i2cdev_s uint16_t irqid; /* IRQ for this device */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for state machine completion */ volatile uint8_t state; /* State of state machine */ struct wdog_s timeout; /* Watchdog to timeout when bus hung */ @@ -144,22 +145,25 @@ static int lpc17_40_i2c_reset(struct i2c_master_s *dev); #ifdef CONFIG_LPC17_40_I2C0 static struct lpc17_40_i2cdev_s g_i2c0dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif #ifdef CONFIG_LPC17_40_I2C1 static struct lpc17_40_i2cdev_s g_i2c1dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif #ifdef CONFIG_LPC17_40_I2C2 static struct lpc17_40_i2cdev_s g_i2c2dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif @@ -288,10 +292,10 @@ static void lpc17_40_i2c_timeout(wdparm_t arg) { struct lpc17_40_i2cdev_s *priv = (struct lpc17_40_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->state = 0xff; nxsem_post(&priv->wait); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -527,7 +531,7 @@ struct i2c_master_s *lpc17_40_i2cbus_initialize(int port) irqstate_t flags; uint32_t regval; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); #ifdef CONFIG_LPC17_40_I2C0 if (port == 0) @@ -617,12 +621,12 @@ struct i2c_master_s *lpc17_40_i2cbus_initialize(int port) else #endif { + spin_unlock_irqrestore(&priv->spinlock, flags); i2cerr("ERROR: LPC I2C Only supports ports 0, 1 and 2\n"); - leave_critical_section(flags); return NULL; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); putreg32(I2C_CONSET_I2EN, priv->base + LPC17_40_I2C_CONSET_OFFSET); diff --git a/arch/arm/src/lpc2378/lpc23xx_i2c.c b/arch/arm/src/lpc2378/lpc23xx_i2c.c index bc3b7e9b8bdde..af5d15cdaae46 100644 --- a/arch/arm/src/lpc2378/lpc23xx_i2c.c +++ b/arch/arm/src/lpc2378/lpc23xx_i2c.c @@ -62,7 +62,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -109,6 +109,7 @@ struct lpc2378_i2cdev_s uint16_t irqid; /* IRQ for this device */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for state machine completion */ volatile uint8_t state; /* State of state machine */ struct wdog_s timeout; /* Watchdog to timeout when bus hung */ @@ -148,22 +149,25 @@ static int lpc2378_i2c_reset(struct i2c_master_s *dev); #ifdef CONFIG_LPC2378_I2C0 static struct lpc2378_i2cdev_s g_i2c0dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif #ifdef CONFIG_LPC2378_I2C1 static struct lpc2378_i2cdev_s g_i2c1dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif #ifdef CONFIG_LPC2378_I2C2 static struct lpc2378_i2cdev_s g_i2c2dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif @@ -265,10 +269,10 @@ static void lpc2378_i2c_timeout(wdparm_t arg) { struct lpc2378_i2cdev_s *priv = (struct lpc2378_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->state = 0xff; nxsem_post(&priv->wait); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -481,7 +485,7 @@ struct i2c_master_s *lpc2378_i2cbus_initialize(int port) irqstate_t flags; uint32_t regval; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); #ifdef CONFIG_LPC2378_I2C0 if (port == 0) @@ -577,11 +581,11 @@ struct i2c_master_s *lpc2378_i2cbus_initialize(int port) else #endif { - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return NULL; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); putreg32(I2C_CONSET_I2EN, priv->base + I2C_CONSET_OFFSET); diff --git a/arch/arm/src/lpc31xx/lpc31_i2c.c b/arch/arm/src/lpc31xx/lpc31_i2c.c index b83231f9f2f68..285c3725825b4 100644 --- a/arch/arm/src/lpc31xx/lpc31_i2c.c +++ b/arch/arm/src/lpc31xx/lpc31_i2c.c @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -74,6 +74,7 @@ struct lpc31_i2cdev_s uint16_t irqid; /* IRQ for this device */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for state machine completion */ volatile uint8_t state; /* State of state machine */ struct wdog_s timeout; /* Watchdog to timeout when bus hung */ @@ -96,12 +97,14 @@ struct lpc31_i2cdev_s static struct lpc31_i2cdev_s i2cdevices[2] = { { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }, { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }, }; @@ -423,7 +426,7 @@ static void i2c_timeout(wdparm_t arg) { struct lpc31_i2cdev_s *priv = (struct lpc31_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); if (priv->state != I2C_STATE_DONE) { @@ -449,7 +452,7 @@ static void i2c_timeout(wdparm_t arg) nxsem_post(&priv->wait); } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -488,7 +491,7 @@ static int i2c_transfer(struct i2c_master_s *dev, /* Get exclusive access to the I2C bus */ nxmutex_lock(&priv->lock); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Set up for the transfer */ @@ -516,13 +519,17 @@ static int i2c_transfer(struct i2c_master_s *dev, while (priv->state != I2C_STATE_DONE) { + spin_unlock_irqrestore(&priv->spinlock, flags); + nxsem_wait(&priv->wait); + + flags = spin_lock_irqsave(&priv->spinlock); } wd_cancel(&priv->timeout); ret = count - priv->nmsg; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxmutex_unlock(&priv->lock); return ret; } diff --git a/arch/arm/src/lpc43xx/lpc43_i2c.c b/arch/arm/src/lpc43xx/lpc43_i2c.c index 8519c932d73cc..8d1c8a478ebee 100644 --- a/arch/arm/src/lpc43xx/lpc43_i2c.c +++ b/arch/arm/src/lpc43xx/lpc43_i2c.c @@ -59,7 +59,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -97,6 +97,7 @@ struct lpc43_i2cdev_s uint32_t base_freq; /* branch frequency */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for state machine completion */ volatile uint8_t state; /* State of state machine */ struct wdog_s timeout; /* watchdog to timeout when bus hung */ @@ -112,15 +113,17 @@ struct lpc43_i2cdev_s #ifdef CONFIG_LPC43_I2C0 static struct lpc43_i2cdev_s g_i2c0dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif #ifdef CONFIG_LPC43_I2C1 static struct lpc43_i2cdev_s g_i2c1dev = { - .lock = NXMUTEX_INITIALIZER, - .wait = SEM_INITIALIZER(0), + .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, + .wait = SEM_INITIALIZER(0), }; #endif @@ -241,10 +244,10 @@ static void lpc43_i2c_timeout(wdparm_t arg) { struct lpc43_i2cdev_s *priv = (struct lpc43_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->state = 0xff; nxsem_post(&priv->wait); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -459,7 +462,7 @@ struct i2c_master_s *lpc43_i2cbus_initialize(int port) irqstate_t flags; uint32_t regval; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); #ifdef CONFIG_LPC43_I2C0 if (port == 0) @@ -520,11 +523,11 @@ struct i2c_master_s *lpc43_i2cbus_initialize(int port) else #endif { - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return NULL; } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); putreg32(I2C_CONSET_I2EN, priv->base + LPC43_I2C_CONSET_OFFSET); diff --git a/arch/arm/src/rp2040/rp2040_i2c.c b/arch/arm/src/rp2040/rp2040_i2c.c index 54a680297e79f..50d8fc4d9200a 100644 --- a/arch/arm/src/rp2040/rp2040_i2c.c +++ b/arch/arm/src/rp2040/rp2040_i2c.c @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -79,6 +79,7 @@ struct rp2040_i2cdev_s uint32_t base_freq; /* branch frequency */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for transfer completion */ struct wdog_s timeout; /* watchdog to timeout when bus hung */ uint32_t frequency; /* Current I2C frequency */ @@ -98,6 +99,7 @@ static struct rp2040_i2cdev_s g_i2c0dev = .base = RP2040_I2C0_BASE, .irqid = RP2040_I2C0_IRQ, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -109,6 +111,7 @@ static struct rp2040_i2cdev_s g_i2c1dev = .base = RP2040_I2C1_BASE, .irqid = RP2040_I2C1_IRQ, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -267,11 +270,11 @@ static void rp2040_i2c_setfrequency(struct rp2040_i2cdev_s *priv, static void rp2040_i2c_timeout(wdparm_t arg) { struct rp2040_i2cdev_s *priv = (struct rp2040_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->error = -ENODEV; nxsem_post(&priv->wait); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -434,7 +437,7 @@ static int rp2040_i2c_receive(struct rp2040_i2cdev_s *priv, int last) RP2040_I2C_IC_DATA_CMD_CMD); } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); wd_start(&priv->timeout, I2C_TIMEOUT, rp2040_i2c_timeout, (wdparm_t)priv); @@ -447,7 +450,7 @@ static int rp2040_i2c_receive(struct rp2040_i2cdev_s *priv, int last) i2c_reg_rmw(priv, RP2040_I2C_IC_INTR_MASK_OFFSET, RP2040_I2C_IC_INTR_STAT_R_RX_FULL, RP2040_I2C_IC_INTR_STAT_R_RX_FULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxsem_wait_uninterruptible(&priv->wait); if (priv->error != OK) @@ -489,7 +492,7 @@ static int rp2040_i2c_send(struct rp2040_i2cdev_s *priv, int last) & RP2040_I2C_IC_STATUS_TFNF)) ; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); wd_start(&priv->timeout, I2C_TIMEOUT, rp2040_i2c_timeout, (wdparm_t)priv); i2c_reg_write(priv, RP2040_I2C_IC_DATA_CMD_OFFSET, @@ -501,7 +504,7 @@ static int rp2040_i2c_send(struct rp2040_i2cdev_s *priv, int last) i2c_reg_rmw(priv, RP2040_I2C_IC_INTR_MASK_OFFSET, RP2040_I2C_IC_INTR_STAT_R_TX_EMPTY, RP2040_I2C_IC_INTR_STAT_R_TX_EMPTY); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxsem_wait_uninterruptible(&priv->wait); return 0; diff --git a/arch/arm/src/rp23xx/rp23xx_i2c.c b/arch/arm/src/rp23xx/rp23xx_i2c.c index 77d92744d8ffd..cea2a8f48c5f6 100644 --- a/arch/arm/src/rp23xx/rp23xx_i2c.c +++ b/arch/arm/src/rp23xx/rp23xx_i2c.c @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include "chip.h" @@ -79,6 +79,7 @@ struct rp23xx_i2cdev_s uint32_t base_freq; /* branch frequency */ mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ sem_t wait; /* Place to wait for transfer completion */ struct wdog_s timeout; /* watchdog to timeout when bus hung */ uint32_t frequency; /* Current I2C frequency */ @@ -98,6 +99,7 @@ static struct rp23xx_i2cdev_s g_i2c0dev = .base = RP23XX_I2C0_BASE, .irqid = RP23XX_I2C0_IRQ, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -109,6 +111,7 @@ static struct rp23xx_i2cdev_s g_i2c1dev = .base = RP23XX_I2C1_BASE, .irqid = RP23XX_I2C1_IRQ, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .wait = SEM_INITIALIZER(0), .refs = 0, }; @@ -267,11 +270,11 @@ static void rp23xx_i2c_setfrequency(struct rp23xx_i2cdev_s *priv, static void rp23xx_i2c_timeout(wdparm_t arg) { struct rp23xx_i2cdev_s *priv = (struct rp23xx_i2cdev_s *)arg; - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); priv->error = -ENODEV; nxsem_post(&priv->wait); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } /**************************************************************************** @@ -434,7 +437,7 @@ static int rp23xx_i2c_receive(struct rp23xx_i2cdev_s *priv, int last) RP23XX_I2C_IC_DATA_CMD_CMD); } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); wd_start(&priv->timeout, I2C_TIMEOUT, rp23xx_i2c_timeout, (wdparm_t)priv); @@ -447,7 +450,7 @@ static int rp23xx_i2c_receive(struct rp23xx_i2cdev_s *priv, int last) i2c_reg_rmw(priv, RP23XX_I2C_IC_INTR_MASK_OFFSET, RP23XX_I2C_IC_INTR_STAT_R_RX_FULL, RP23XX_I2C_IC_INTR_STAT_R_RX_FULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxsem_wait_uninterruptible(&priv->wait); if (priv->error != OK) @@ -489,7 +492,7 @@ static int rp23xx_i2c_send(struct rp23xx_i2cdev_s *priv, int last) & RP23XX_I2C_IC_STATUS_TFNF)) ; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); wd_start(&priv->timeout, I2C_TIMEOUT, rp23xx_i2c_timeout, (wdparm_t)priv); i2c_reg_write(priv, RP23XX_I2C_IC_DATA_CMD_OFFSET, @@ -501,7 +504,7 @@ static int rp23xx_i2c_send(struct rp23xx_i2cdev_s *priv, int last) i2c_reg_rmw(priv, RP23XX_I2C_IC_INTR_MASK_OFFSET, RP23XX_I2C_IC_INTR_STAT_R_TX_EMPTY, RP23XX_I2C_IC_INTR_STAT_R_TX_EMPTY); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); nxsem_wait_uninterruptible(&priv->wait); return 0; diff --git a/arch/arm/src/stm32/stm32_i2c.c b/arch/arm/src/stm32/stm32_i2c.c index a8fd44c269fe6..89c3d72539037 100644 --- a/arch/arm/src/stm32/stm32_i2c.c +++ b/arch/arm/src/stm32/stm32_i2c.c @@ -66,7 +66,7 @@ #include #include -#include +#include #include #include #include @@ -244,6 +244,7 @@ struct stm32_i2c_priv_s int refs; /* Reference count */ mutex_t lock; /* Mutual exclusion lock */ + spinlock_t spinlock; /* Spinlock */ #ifndef CONFIG_I2C_POLLED sem_t sem_isr; /* Interrupt wait semaphore */ #endif @@ -381,6 +382,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 @@ -414,6 +416,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 @@ -447,6 +450,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 @@ -552,7 +556,7 @@ static inline 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 */ @@ -568,6 +572,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 @@ -586,6 +592,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. */ @@ -602,7 +610,7 @@ static inline 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 @@ -1207,7 +1215,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv) */ #ifdef CONFIG_I2C_POLLED - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); #endif /* Receive a byte */ @@ -1223,7 +1231,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv) } #ifdef CONFIG_I2C_POLLED - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); #endif } else diff --git a/arch/arm/src/stm32/stm32f40xxx_i2c.c b/arch/arm/src/stm32/stm32f40xxx_i2c.c index fac079150c54a..c7416cb1e76ff 100644 --- a/arch/arm/src/stm32/stm32f40xxx_i2c.c +++ b/arch/arm/src/stm32/stm32f40xxx_i2c.c @@ -65,7 +65,7 @@ #include #include -#include +#include #include #include #include @@ -274,6 +274,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 @@ -411,6 +412,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 @@ -453,6 +455,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 @@ -493,6 +496,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 @@ -605,7 +609,7 @@ static inline 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 */ @@ -621,6 +625,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 @@ -639,6 +645,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. */ @@ -655,7 +663,7 @@ static inline 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 diff --git a/arch/arm/src/stm32f0l0g0/stm32_i2c.c b/arch/arm/src/stm32f0l0g0/stm32_i2c.c index 93ba0f2f4c240..c203abbead0d5 100644 --- a/arch/arm/src/stm32f0l0g0/stm32_i2c.c +++ b/arch/arm/src/stm32f0l0g0/stm32_i2c.c @@ -226,7 +226,7 @@ #include #include -#include +#include #include #include #include @@ -396,6 +396,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 @@ -508,6 +509,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 @@ -543,6 +545,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 @@ -578,6 +581,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 @@ -613,6 +617,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 @@ -779,7 +784,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 */ @@ -796,6 +801,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_STM32F0L0G0_I2C_DYNTIMEO @@ -814,6 +821,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. */ @@ -828,7 +837,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 @@ -1730,7 +1739,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 */ @@ -1747,7 +1756,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 diff --git a/arch/arm/src/stm32f7/stm32_i2c.c b/arch/arm/src/stm32f7/stm32_i2c.c index ca4b3b2e9d356..41b537c090f7e 100644 --- a/arch/arm/src/stm32f7/stm32_i2c.c +++ b/arch/arm/src/stm32f7/stm32_i2c.c @@ -238,7 +238,7 @@ #include #include -#include +#include #include #include #include @@ -438,6 +438,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 @@ -554,6 +555,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 @@ -591,6 +593,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 @@ -628,6 +631,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 @@ -665,6 +669,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 @@ -820,7 +825,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 */ @@ -837,6 +842,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_STM32F7_I2C_DYNTIMEO @@ -855,6 +862,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. */ @@ -869,7 +878,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 @@ -1769,7 +1778,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 */ @@ -1786,7 +1795,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 diff --git a/arch/arm/src/stm32h5/stm32_i2c.c b/arch/arm/src/stm32h5/stm32_i2c.c index 91698c16da047..65d05ccbfa105 100644 --- a/arch/arm/src/stm32h5/stm32_i2c.c +++ b/arch/arm/src/stm32h5/stm32_i2c.c @@ -209,7 +209,7 @@ #include #include -#include +#include #include #include #include @@ -391,6 +391,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 @@ -506,6 +507,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 @@ -544,6 +546,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 @@ -582,6 +585,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 @@ -620,6 +624,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 @@ -785,7 +790,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 */ @@ -802,6 +807,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_STM32H5_I2C_DYNTIMEO @@ -820,6 +827,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. */ @@ -834,7 +843,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 @@ -1945,7 +1954,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 */ @@ -1962,7 +1971,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 diff --git a/arch/arm/src/stm32h7/stm32_i2c.c b/arch/arm/src/stm32h7/stm32_i2c.c index 9f96a33e53b83..33c010b9ffa79 100644 --- a/arch/arm/src/stm32h7/stm32_i2c.c +++ b/arch/arm/src/stm32h7/stm32_i2c.c @@ -207,7 +207,7 @@ #include #include -#include +#include #include #include #include @@ -394,6 +394,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 @@ -507,6 +508,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 @@ -543,6 +545,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 @@ -579,6 +582,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 @@ -615,6 +619,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 @@ -780,7 +785,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 */ @@ -797,6 +802,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_STM32H7_I2C_DYNTIMEO @@ -815,6 +822,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. */ @@ -829,7 +838,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 @@ -1732,7 +1741,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 */ @@ -1749,7 +1758,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 diff --git a/arch/arm/src/stm32l4/stm32l4_i2c.c b/arch/arm/src/stm32l4/stm32l4_i2c.c index a886a2edec085..15b43dfce086f 100644 --- a/arch/arm/src/stm32l4/stm32l4_i2c.c +++ b/arch/arm/src/stm32l4/stm32l4_i2c.c @@ -254,7 +254,7 @@ #include #include -#include +#include #include #include #include @@ -415,6 +415,7 @@ struct stm32l4_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 @@ -536,6 +537,7 @@ static struct stm32l4_i2c_priv_s stm32l4_i2c1_priv = .config = &stm32l4_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -572,6 +574,7 @@ static struct stm32l4_i2c_priv_s stm32l4_i2c2_priv = .config = &stm32l4_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -608,6 +611,7 @@ static struct stm32l4_i2c_priv_s stm32l4_i2c3_priv = .config = &stm32l4_i2c3_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -644,6 +648,7 @@ static struct stm32l4_i2c_priv_s stm32l4_i2c4_priv = .config = &stm32l4_i2c4_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -814,7 +819,7 @@ int stm32l4_i2c_sem_waitdone(struct stm32l4_i2c_priv_s *priv) irqstate_t flags; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Enable I2C interrupts */ @@ -831,6 +836,8 @@ int stm32l4_i2c_sem_waitdone(struct stm32l4_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_STM32L4_I2C_DYNTIMEO @@ -849,6 +856,8 @@ int stm32l4_i2c_sem_waitdone(struct stm32l4_i2c_priv_s *priv) break; } + + flags = spin_lock_irqsave(&priv->spinlock); } /* Loop until the interrupt level transfer is complete. */ @@ -863,7 +872,7 @@ int stm32l4_i2c_sem_waitdone(struct stm32l4_i2c_priv_s *priv) stm32l4_i2c_modifyreg32(priv, STM32L4_I2C_CR1_OFFSET, I2C_CR1_ALLINTS, 0); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return ret; } #else @@ -1922,7 +1931,7 @@ static int stm32l4_i2c_isr_process(struct stm32l4_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 */ @@ -1939,7 +1948,7 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv) priv->dcnt--; #ifdef CONFIG_I2C_POLLED - leave_critical_section(state); + spin_unlock_irqrestore(&priv->spinlock, state); #endif } else diff --git a/arch/arm/src/stm32u5/stm32_i2c.c b/arch/arm/src/stm32u5/stm32_i2c.c index b34c86a8f1225..68a4c697e0342 100644 --- a/arch/arm/src/stm32u5/stm32_i2c.c +++ b/arch/arm/src/stm32u5/stm32_i2c.c @@ -255,7 +255,7 @@ #include #include -#include +#include #include #include #include @@ -416,6 +416,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 @@ -537,6 +538,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 @@ -573,6 +575,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 @@ -609,6 +612,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 @@ -645,6 +649,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 @@ -815,7 +820,7 @@ 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 */ @@ -832,6 +837,8 @@ 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_STM32U5_I2C_DYNTIMEO @@ -850,6 +857,8 @@ 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. */ @@ -864,7 +873,7 @@ 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 @@ -1972,7 +1981,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 */ @@ -1989,7 +1998,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 diff --git a/arch/arm/src/stm32wb/stm32wb_i2c.c b/arch/arm/src/stm32wb/stm32wb_i2c.c index c92bda3c3ca58..e321e5bbc5841 100644 --- a/arch/arm/src/stm32wb/stm32wb_i2c.c +++ b/arch/arm/src/stm32wb/stm32wb_i2c.c @@ -172,7 +172,7 @@ #include #include -#include +#include #include #include #include @@ -327,6 +327,7 @@ struct stm32wb_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 @@ -448,6 +449,7 @@ static struct stm32wb_i2c_priv_s stm32wb_i2c1_priv = .config = &stm32wb_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -484,6 +486,7 @@ static struct stm32wb_i2c_priv_s stm32wb_i2c3_priv = .config = &stm32wb_i2c3_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -654,7 +657,7 @@ int stm32wb_i2c_sem_waitdone(struct stm32wb_i2c_priv_s *priv) irqstate_t flags; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Enable I2C interrupts */ @@ -671,6 +674,8 @@ int stm32wb_i2c_sem_waitdone(struct stm32wb_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_STM32WB_I2C_DYNTIMEO @@ -689,6 +694,8 @@ int stm32wb_i2c_sem_waitdone(struct stm32wb_i2c_priv_s *priv) break; } + + flags = spin_lock_irqsave(&priv->spinlock); } /* Loop until the interrupt level transfer is complete. */ @@ -703,7 +710,7 @@ int stm32wb_i2c_sem_waitdone(struct stm32wb_i2c_priv_s *priv) stm32wb_i2c_modifyreg32(priv, STM32WB_I2C_CR1_OFFSET, I2C_CR1_ALLINTS, 0); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return ret; } #else @@ -1597,7 +1604,7 @@ static int stm32wb_i2c_isr_process(struct stm32wb_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 */ @@ -1614,7 +1621,7 @@ static int stm32wb_i2c_isr_process(struct stm32wb_i2c_priv_s *priv) priv->dcnt--; #ifdef CONFIG_I2C_POLLED - leave_critical_section(state); + spin_unlock_irqrestore(&priv->spinlock, state); #endif } else diff --git a/arch/arm/src/tiva/common/tiva_i2c.c b/arch/arm/src/tiva/common/tiva_i2c.c index 93c901f72572a..88c001f2a0af3 100644 --- a/arch/arm/src/tiva/common/tiva_i2c.c +++ b/arch/arm/src/tiva/common/tiva_i2c.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include #include @@ -198,6 +198,7 @@ struct tiva_i2c_priv_s const struct tiva_i2c_config_s *config; mutex_t lock; /* Mutual exclusion mutex */ + spinlock_t spinlock; /* Spinlock */ #ifndef CONFIG_I2C_POLLED sem_t waitsem; /* Interrupt wait semaphore */ #endif @@ -323,6 +324,7 @@ static const struct tiva_i2c_config_s tiva_i2c0_config = static struct tiva_i2c_priv_s tiva_i2c0_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -350,6 +352,7 @@ static const struct tiva_i2c_config_s tiva_i2c1_config = static struct tiva_i2c_priv_s tiva_i2c1_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -377,6 +380,7 @@ static const struct tiva_i2c_config_s tiva_i2c2_config = static struct tiva_i2c_priv_s tiva_i2c2_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -404,6 +408,7 @@ static const struct tiva_i2c_config_s tiva_i2c3_config = static struct tiva_i2c_priv_s tiva_i2c3_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -431,6 +436,7 @@ static const struct tiva_i2c_config_s tiva_i2c4_config = static struct tiva_i2c_priv_s tiva_i2c4_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -458,6 +464,7 @@ static const struct tiva_i2c_config_s tiva_i2c5_config = static struct tiva_i2c_priv_s tiva_i2c5_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -485,6 +492,7 @@ static const struct tiva_i2c_config_s tiva_i2c6_config = static struct tiva_i2c_priv_s tiva_i2c6_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -512,6 +520,7 @@ static const struct tiva_i2c_config_s tiva_i2c7_config = static struct tiva_i2c_priv_s tiva_i2c7_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -539,6 +548,7 @@ static const struct tiva_i2c_config_s tiva_i2c8_config = static struct tiva_i2c_priv_s tiva_i2c8_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -566,6 +576,7 @@ static const struct tiva_i2c_config_s tiva_i2c9_config = static struct tiva_i2c_priv_s tiva_i2c9_priv = { .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .waitsem = SEM_INITIALIZER(0), #endif @@ -734,7 +745,7 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) irqstate_t flags; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Enable the master interrupt. The I2C master module generates an * interrupt when a transaction completes (either transmit or receive), @@ -750,6 +761,8 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) do { + spin_unlock_irqrestore(&priv->spinlock, flags); + /* Wait until either the transfer is complete or the timeout expires */ #ifdef CONFIG_TIVA_I2C_DYNTIMEO @@ -770,6 +783,8 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) tiva_i2c_getreg(priv, TIVA_I2CM_RIS_OFFSET)); break; } + + flags = spin_lock_irqsave(&priv->spinlock); } /* Loop until the interrupt level transfer is complete. */ @@ -784,7 +799,7 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv) tiva_i2c_putreg(priv, TIVA_I2CM_IMR_OFFSET, 0); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return ret; } #else diff --git a/arch/arm/src/xmc4/xmc4_i2c.c b/arch/arm/src/xmc4/xmc4_i2c.c index 6ae40a73d4546..9cb63c337a2ae 100644 --- a/arch/arm/src/xmc4/xmc4_i2c.c +++ b/arch/arm/src/xmc4/xmc4_i2c.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include "arm_internal.h" #include "chip.h" @@ -122,8 +122,9 @@ struct xmc4_i2cdev_s uint32_t sda_gpio; /* GPIO config of SDA */ uint32_t scl_gpio; /* GPIO config of SCL */ - mutex_t lock; /* Only one thread can access at a time */ - int refs; /* Reference count */ + mutex_t lock; /* Only one thread can access at a time */ + spinlock_t spinlock; /* Spinlock */ + int refs; /* Reference count */ }; /***************************************************************************** @@ -198,6 +199,7 @@ static struct xmc4_i2cdev_s g_i2c0 = .scl_gpio = GPIO_I2C0_SCL, /* See i2c_set_input_source */ .frequency = (uint32_t)I2C_DEFAULT_FREQUENCY, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .refs = 0, }; #endif @@ -214,6 +216,7 @@ static struct xmc4_i2cdev_s g_i2c1 = .scl_gpio = GPIO_I2C1_SCL, /* See i2c_set_input_source */ .frequency = (uint32_t)I2C_DEFAULT_FREQUENCY, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .refs = 0, }; #endif @@ -230,6 +233,7 @@ static struct xmc4_i2cdev_s g_i2c2 = .scl_gpio = GPIO_I2C2_SCL, /* See i2c_set_input_source */ .frequency = (uint32_t)I2C_DEFAULT_FREQUENCY, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .refs = 0, }; #endif @@ -246,6 +250,7 @@ static struct xmc4_i2cdev_s g_i2c3 = .scl_gpio = GPIO_I2C3_SCL, /* See i2c_set_input_source */ .frequency = (uint32_t)I2C_DEFAULT_FREQUENCY, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .refs = 0, }; #endif @@ -262,6 +267,7 @@ static struct xmc4_i2cdev_s g_i2c4 = .scl_gpio = GPIO_I2C4_SCL, /* See i2c_set_input_source */ .frequency = (uint32_t)I2C_DEFAULT_FREQUENCY, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .refs = 0, }; #endif @@ -278,6 +284,7 @@ static struct xmc4_i2cdev_s g_i2c5 = .scl_gpio = GPIO_I2C5_SCL, /* See i2c_set_input_source */ .frequency = (uint32_t)I2C_DEFAULT_FREQUENCY, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, .refs = 0, }; #endif @@ -817,7 +824,7 @@ static int i2c_transfer(struct i2c_master_s *dev, /* Enter critical section to avoid interrupts during i2c transfert */ - irqstate_t state = enter_critical_section(); + irqstate_t state = spin_lock_irqsave(&priv->spinlock); for (int i = 0; i < count; i++) { @@ -837,8 +844,8 @@ static int i2c_transfer(struct i2c_master_s *dev, } else { + spin_unlock_irqrestore(&priv->spinlock, state); i2cerr("Can't update frequency between Start & Stop symbols\n"); - leave_critical_section(state); nxmutex_unlock(&priv->lock); return -EINVAL; } @@ -926,7 +933,7 @@ static int i2c_transfer(struct i2c_master_s *dev, } } - leave_critical_section(state); + spin_unlock_irqrestore(&priv->spinlock, state); nxmutex_unlock(&priv->lock); return ret; } diff --git a/arch/mips/src/pic32mz/pic32mz_i2c.c b/arch/mips/src/pic32mz/pic32mz_i2c.c index 9b0324a423e10..56ee54a5eacc9 100644 --- a/arch/mips/src/pic32mz/pic32mz_i2c.c +++ b/arch/mips/src/pic32mz/pic32mz_i2c.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include #include @@ -189,6 +189,7 @@ struct pic32mz_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 @@ -337,6 +338,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c1_priv = .config = &pic32mz_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -369,6 +371,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c2_priv = .config = &pic32mz_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -401,6 +404,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c3_priv = .config = &pic32mz_i2c3_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -433,6 +437,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c4_priv = .config = &pic32mz_i2c4_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -465,6 +470,7 @@ static struct pic32mz_i2c_priv_s pic32mz_i2c5_priv = .config = &pic32mz_i2c5_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -682,7 +688,7 @@ pic32mz_i2c_sem_waitdone(struct pic32mz_i2c_priv_s *priv) irqstate_t flags; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Signal the interrupt handler that we are waiting */ @@ -690,6 +696,8 @@ pic32mz_i2c_sem_waitdone(struct pic32mz_i2c_priv_s *priv) do { + spin_unlock_irqrestore(&priv->spinlock, flags); + /* Wait until either the transfer is complete or the timeout expires */ #ifdef CONFIG_PIC32MZ_I2C_DYNTIMEO @@ -708,6 +716,8 @@ pic32mz_i2c_sem_waitdone(struct pic32mz_i2c_priv_s *priv) break; } + + flags = spin_lock_irqsave(&priv->spinlock); } /* Loop until the interrupt level transfer is complete. */ @@ -723,7 +733,7 @@ pic32mz_i2c_sem_waitdone(struct pic32mz_i2c_priv_s *priv) up_disable_irq(priv->config->ev_irq); up_disable_irq(priv->config->er_irq); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return ret; } @@ -982,7 +992,7 @@ static int pic32mz_i2c_isr_process(struct pic32mz_i2c_priv_s *priv) if (priv->dcnt > 1) { #ifdef CONFIG_I2C_POLLED - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); #endif *priv->ptr++ = pic32mz_i2c_receivebyte(priv); @@ -999,7 +1009,7 @@ static int pic32mz_i2c_isr_process(struct pic32mz_i2c_priv_s *priv) } #ifdef CONFIG_I2C_POLLED - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); #endif /* Go back and re-enable read mode to handle the rest of * the data. @@ -1014,7 +1024,7 @@ static int pic32mz_i2c_isr_process(struct pic32mz_i2c_priv_s *priv) else { #ifdef CONFIG_I2C_POLLED - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); #endif *priv->ptr++ = pic32mz_i2c_receivebyte(priv); @@ -1030,7 +1040,7 @@ static int pic32mz_i2c_isr_process(struct pic32mz_i2c_priv_s *priv) } #ifdef CONFIG_I2C_POLLED - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); #endif priv->process_state = PROCESS_STATE_FETCH_NEXT; } diff --git a/arch/risc-v/src/common/espressif/esp_i2c.c b/arch/risc-v/src/common/espressif/esp_i2c.c index 29ebbbc8b3c7c..8ef6f8b496f09 100644 --- a/arch/risc-v/src/common/espressif/esp_i2c.c +++ b/arch/risc-v/src/common/espressif/esp_i2c.c @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include #include @@ -218,6 +218,7 @@ struct esp_i2c_priv_s const struct esp_i2c_config_s *config; 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 */ @@ -349,6 +350,7 @@ static struct esp_i2c_priv_s esp_i2c0_priv = .config = &esp_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -399,6 +401,7 @@ static struct esp_i2c_priv_s esp_i2c1_priv = .config = &esp_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -1118,7 +1121,7 @@ static int esp_i2c_reset(struct i2c_master_s *dev) DEBUGASSERT(priv->refs > 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); esp_i2c_reset_fsmc(priv); @@ -1131,7 +1134,7 @@ static int esp_i2c_reset(struct i2c_master_s *dev) priv->bytes = 0; priv->ready_read = false; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return OK; } diff --git a/arch/risc-v/src/esp32c3-legacy/esp32c3_i2c.c b/arch/risc-v/src/esp32c3-legacy/esp32c3_i2c.c index 309392c1a3f7a..9995a369a668e 100644 --- a/arch/risc-v/src/esp32c3-legacy/esp32c3_i2c.c +++ b/arch/risc-v/src/esp32c3-legacy/esp32c3_i2c.c @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include #include @@ -223,6 +223,7 @@ struct esp32c3_i2c_priv_s const struct esp32c3_i2c_config_s *config; 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 */ @@ -333,6 +334,7 @@ static struct esp32c3_i2c_priv_s esp32c3_i2c0_priv = .config = &esp32c3_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -1098,7 +1100,7 @@ static int esp32c3_i2c_reset(struct i2c_master_s *dev) DEBUGASSERT(priv->refs > 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); esp32c3_i2c_reset_fsmc(priv); @@ -1111,7 +1113,7 @@ static int esp32c3_i2c_reset(struct i2c_master_s *dev) priv->bytes = 0; priv->ready_read = false; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return OK; } diff --git a/arch/xtensa/src/esp32s2/esp32s2_i2c.c b/arch/xtensa/src/esp32s2/esp32s2_i2c.c index d0c4f323ce065..433f685760242 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_i2c.c +++ b/arch/xtensa/src/esp32s2/esp32s2_i2c.c @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include #include @@ -212,6 +212,7 @@ struct esp32s2_i2c_priv_s const struct esp32s2_i2c_config_s *config; 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 */ @@ -320,6 +321,7 @@ static struct esp32s2_i2c_priv_s g_esp32s2_i2c0_priv = .config = &g_esp32s2_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -356,6 +358,7 @@ static struct esp32s2_i2c_priv_s g_esp32s2_i2c1_priv = .config = &g_esp32s2_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -1120,7 +1123,7 @@ static int i2c_reset(struct i2c_master_s *dev) DEBUGASSERT(dev != NULL); DEBUGASSERT(priv->refs > 0); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); i2c_reset_fsmc(priv); @@ -1133,7 +1136,7 @@ static int i2c_reset(struct i2c_master_s *dev) priv->bytes = 0; priv->ready_read = false; - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return OK; }