Check return from nxsem_wait_initialize()

Resolution of Issue 619 will require multiple steps, this part of the first step in that resolution:  Every call to nxsem_wait_uninterruptible() must handle the return value from nxsem_wait_uninterruptible properly.  This commit is for all I2C drivers under arch/.
This commit is contained in:
Gregory Nutt
2020-04-01 13:25:04 -06:00
committed by Abdelatif Guettouche
parent 4addf6c308
commit fc467021cf
23 changed files with 1769 additions and 1046 deletions
+66 -22
View File
@@ -38,7 +38,7 @@
/****************************************************************************
* Included Files
************************************************************************************/
****************************************************************************/
#include <nuttx/config.h>
@@ -80,7 +80,7 @@
/* Configuration ************************************************************/
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used.
( Instead, CPU-intensive polling will be used.
* Instead, CPU-intensive polling will be used.
*/
/* Interrupt wait timeout in seconds and milliseconds */
@@ -189,8 +189,14 @@ struct am335x_i2c_config_s
struct am335x_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct am335x_i2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct am335x_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -230,17 +236,22 @@ static inline void am335x_i2c_putreg(FAR struct am335x_i2c_priv_s *priv,
static inline void am335x_i2c_modifyreg(FAR struct am335x_i2c_priv_s *priv,
uint16_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void am335x_i2c_sem_wait(FAR struct am335x_i2c_priv_s *priv);
static inline int am335x_i2c_sem_wait(FAR struct am335x_i2c_priv_s *priv);
static int
am335x_i2c_sem_wait_uninterruptible(FAR struct am335x_i2c_priv_s *priv);
#ifdef CONFIG_AM335X_I2C_DYNTIMEO
static useconds_t am335x_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_AM335X_I2C_DYNTIMEO */
static inline int am335x_i2c_sem_waitdone(FAR struct am335x_i2c_priv_s *priv);
static inline bool am335x_i2c_sem_waitstop(FAR struct am335x_i2c_priv_s *priv);
static inline int
am335x_i2c_sem_waitdone(FAR struct am335x_i2c_priv_s *priv);
static inline bool
am335x_i2c_sem_waitstop(FAR struct am335x_i2c_priv_s *priv);
static inline void am335x_i2c_sem_post(FAR struct am335x_i2c_priv_s *priv);
static inline void am335x_i2c_sem_init(FAR struct am335x_i2c_priv_s *priv);
static inline void am335x_i2c_sem_destroy(FAR struct am335x_i2c_priv_s *priv);
static inline void
am335x_i2c_sem_destroy(FAR struct am335x_i2c_priv_s *priv);
#ifdef CONFIG_I2C_TRACE
static void am335x_i2c_tracereset(FAR struct am335x_i2c_priv_s *priv);
@@ -256,7 +267,8 @@ static void am335x_i2c_setclock(FAR struct am335x_i2c_priv_s *priv,
static inline void am335x_i2c_sendstart(FAR struct am335x_i2c_priv_s *priv,
uint16_t address);
static inline void am335x_i2c_sendstop(FAR struct am335x_i2c_priv_s *priv);
static inline uint32_t am335x_i2c_getstatus(FAR struct am335x_i2c_priv_s *priv);
static inline uint32_t
am335x_i2c_getstatus(FAR struct am335x_i2c_priv_s *priv);
static int am335x_i2c_isr_process(struct am335x_i2c_priv_s * priv);
@@ -448,13 +460,28 @@ static inline void am335x_i2c_modifyreg(FAR struct am335x_i2c_priv_s *priv,
* Name: am335x_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
* Take the exclusive access, waiting as necessary. May be interrupted by
* a signal.
*
****************************************************************************/
static inline void am335x_i2c_sem_wait(FAR struct am335x_i2c_priv_s *priv)
static inline int am335x_i2c_sem_wait(FAR struct am335x_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait(&priv->sem_excl);
}
/****************************************************************************
* Name: am335x_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary.
*
****************************************************************************/
static int
am335x_i2c_sem_wait_uninterruptible(FAR struct am335x_i2c_priv_s *priv)
{
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/****************************************************************************
@@ -655,7 +682,8 @@ static inline int am335x_i2c_sem_waitdone(FAR struct am335x_i2c_priv_s *priv)
*
****************************************************************************/
static inline bool am335x_i2c_sem_waitstop(FAR struct am335x_i2c_priv_s *priv)
static inline bool
am335x_i2c_sem_waitstop(FAR struct am335x_i2c_priv_s *priv)
{
clock_t start;
clock_t elapsed;
@@ -863,8 +891,10 @@ static void am335x_i2c_tracedump(FAR struct am335x_i2c_priv_s *priv)
{
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x TIME: %d\n",
i + 1, trace->status, trace->count, g_trace_names[trace->event],
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x "
"TIME: %d\n",
i + 1, trace->status, trace->count,
g_trace_names[trace->event],
trace->event, trace->parm, trace->time - priv->start_time);
}
}
@@ -1031,7 +1061,8 @@ static inline void am335x_i2c_sendstop(FAR struct am335x_i2c_priv_s *priv)
*
****************************************************************************/
static inline uint32_t am335x_i2c_getstatus(FAR struct am335x_i2c_priv_s *priv)
static inline uint32_t
am335x_i2c_getstatus(FAR struct am335x_i2c_priv_s *priv)
{
#ifndef CONFIG_I2C_POLLED
return am335x_i2c_getreg(priv, AM335X_I2C_IRQ_STAT_OFFSET);
@@ -1100,7 +1131,8 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv)
am335x_i2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->dcnt);
/* No interrupts or context switches should occur in the following
* sequence. Otherwise, additional bytes may be received by the device.
* sequence. Otherwise, additional bytes may be received by the
* device.
*/
#ifdef CONFIG_I2C_POLLED
@@ -1331,7 +1363,8 @@ static int am335x_i2c_init(FAR struct am335x_i2c_priv_s *priv)
/* Wait for I2C module comes out of reset */
while (!(am335x_i2c_getreg(priv, AM335X_I2C_SYSS_OFFSET) & I2C_SYSS_RST_DONE))
while (!(am335x_i2c_getreg(priv, AM335X_I2C_SYSS_OFFSET) &
I2C_SYSS_RST_DONE))
{
}
@@ -1382,16 +1415,21 @@ static int am335x_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct am335x_i2c_priv_s *priv = (struct am335x_i2c_priv_s *)dev;
int ret = -EBUSY;
int ret;
DEBUGASSERT(count > 0);
/* Ensure that address or flags don't change meanwhile */
am335x_i2c_sem_wait(priv);
ret = am335x_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
/* Wait for any STOP in progress */
ret = -EBUSY;
if (am335x_i2c_sem_waitstop(priv))
{
/* Clear any pending error interrupts */
@@ -1526,7 +1564,7 @@ static int am335x_i2c_reset(FAR struct i2c_master_s *dev)
gpio_pinset_t scl_gpio;
gpio_pinset_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -1536,7 +1574,13 @@ static int am335x_i2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
am335x_i2c_sem_wait(priv);
ret = am335x_i2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
+120 -84
View File
@@ -1,4 +1,4 @@
/************************************************************************************
/****************************************************************************
* arch/arm/src/efm32/efm32_i2c.c
* EFM32 I2C Hardware Layer - Device Driver
*
@@ -45,11 +45,11 @@
*
* Structure naming:
* - Device: structure as defined by the nuttx/i2c/i2c.h
* - Instance: represents each individual access to the I2C driver, obtained by
* the i2c_init(); it extends the Device structure from the nuttx/i2c/i2c.h;
* Instance points to OPS, to common I2C Hardware private data and contains
* its own private data, as frequency, address, mode of operation (in the
* future)
* - Instance: represents each individual access to the I2C driver,
* obtained by the i2c_init(); it extends the Device structure from the
* nuttx/i2c/i2c.h; Instance points to OPS, to common I2C Hardware
* private data and contains its own private data, as frequency,
* address, mode of operation (in the future)
* - Private: Private data of an I2C Hardware
*
*/
@@ -90,10 +90,10 @@
* Pre-processor Definitions
****************************************************************************/
/* Configuration **************************************************************/
/* Configuration ************************************************************/
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. Instead,
* CPU-intensive polling will be used.
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used.
* Instead, CPU-intensive polling will be used.
*/
#if !defined(CONFIG_EFM32_EFM32GG)
@@ -132,11 +132,11 @@
#define MKI2C_OUTPUT(p) (((p) & (GPIO_PORT_MASK | GPIO_PIN_MASK)) | I2C_OUTPUT)
/* Debug ****************************************************************************/
/* Debug ********************************************************************/
/* I2C event trace logic. NOTE: trace uses the internal, non-standard,
* low-level debug interface syslog() but does not require that any other debug
* is enabled.
* low-level debug interface syslog() but does not require that any other
* debug is enabled.
*/
#ifndef CONFIG_I2C_TRACE
@@ -151,16 +151,17 @@
/* Error flags indicating I2C transfer has failed somehow.
* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with
* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow)
* RXUF is only likely to occur with this SW if using a debugger peeking into
* RXDATA register. Thus, we ignore those types of fault.
* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive
* underflow). RXUF is only likely to occur with this SW if using a
* debugger peeking into RXDATA register. Thus, we ignore those types of
* fault.
*/
#define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST)
/************************************************************************************
/****************************************************************************
* Private Types
************************************************************************************/
****************************************************************************/
/* I2C result state */
@@ -227,9 +228,15 @@ struct efm32_i2c_config_s
struct efm32_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct efm32_i2c_config_s *config; /* Port configuration */
int refs; /* Referernce count */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct efm32_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
sem_t sem_isr; /* Interrupt wait semaphore */
@@ -272,7 +279,9 @@ static inline void efm32_i2c_putreg(FAR struct efm32_i2c_priv_s *priv,
static inline void efm32_i2c_modifyreg(FAR struct efm32_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void efm32_i2c_sem_wait(FAR struct efm32_i2c_priv_s *priv);
static inline int efm32_i2c_sem_wait(FAR struct efm32_i2c_priv_s *priv);
static int
efm32_i2c_sem_wait_uninterruptible(FAR struct efm32_i2c_priv_s *priv);
#ifdef CONFIG_EFM32_I2C_DYNTIMEOUT
static useconds_t efm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
@@ -473,13 +482,28 @@ static const char *efm32_i2c_state_str(int i2c_state)
* Name: efm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by
* a signal.
*
****************************************************************************/
static inline int efm32_i2c_sem_wait(FAR struct efm32_i2c_priv_s *priv)
{
return nxsem_wait(&priv->sem_excl);
}
/****************************************************************************
* Name: efm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
****************************************************************************/
static inline void efm32_i2c_sem_wait(FAR struct efm32_i2c_priv_s *priv)
static int
efm32_i2c_sem_wait_uninterruptible(FAR struct efm32_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/****************************************************************************
@@ -505,7 +529,8 @@ static useconds_t efm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs)
}
/* Then return a number of microseconds based on a user provided scaling
* factor. */
* factor.
*/
return (useconds_t) (CONFIG_EFM32_I2C_DYNTIMEO_USECPERBYTE * bytecount);
}
@@ -571,8 +596,9 @@ static inline int efm32_i2c_sem_waitdone(FAR struct efm32_i2c_priv_s *priv)
if (ret < 0)
{
/* Break out of the loop on irrecoverable errors. This would include
* timeouts and mystery errors reported by nxsem_timedwait.
/* Break out of the loop on irrecoverable errors. This would
* include timeouts and mystery errors reported by
* nxsem_timedwait.
*/
break;
@@ -821,8 +847,13 @@ static void efm32_i2c_setclock(FAR struct efm32_i2c_priv_s *priv,
#endif
<< _I2C_CTRL_CLHR_SHIFT);
/* Frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4),
* thus DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1
/* Frequency is given by:
*
* fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4),
*
* thus
*
* DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1
*/
#if defined(CONFIG_EFM32_I2C_CLHR_FAST)
@@ -840,7 +871,8 @@ static void efm32_i2c_setclock(FAR struct efm32_i2c_priv_s *priv,
* bus frequency).
*/
if ((efm32_i2c_getreg(priv, EFM32_I2C_CTRL_OFFSET) & I2C_CTRL_SLAVE) && !div)
if ((efm32_i2c_getreg(priv, EFM32_I2C_CTRL_OFFSET) & I2C_CTRL_SLAVE) &&
!div)
{
div = 1;
}
@@ -882,24 +914,25 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
{
if (priv->i2c_reg_if & I2C_IF_ARBLOST)
{
/* If arbitration fault, it indicates either a slave device not
* responding as expected, or other master which is not supported
* by this SW. */
/* If arbitration fault, it indicates either a slave device
* not responding as expected, or other master which is not
* supported by this SW.
*/
priv->result = I2CRESULT_ARBLOST;
}
else if (priv->i2c_reg_if & I2C_IF_BUSERR)
{
/* A bus error indicates a misplaced start or stop, which should
* not occur in master mode controlled by this SW.
/* A bus error indicates a misplaced start or stop, which
* should not occur in master mode controlled by this SW.
*/
priv->result = I2CRESULT_BUSERR;
}
/* If error situation occurred, it is difficult to know exact cause
* and how to resolve. It will be up to a wrapper to determine how to
* handle a fault/recovery if possible.
/* If error situation occurred, it is difficult to know exact
* cause and how to resolve. It will be up to a wrapper to
* determine how to handle a fault/recovery if possible.
*/
priv->i2c_state = I2CSTATE_DONE;
@@ -908,9 +941,7 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
switch (priv->i2c_state)
{
/***************************************************
* Send first start+address (first byte if 10 bit)
*/
/* Send first start+address (first byte if 10 bit) */
case I2CSTATE_STARTADDRSEND:
if (priv->flags & I2C_M_TEN)
@@ -949,9 +980,7 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
goto done;
/*******************************************************
* Wait for ACK/NACK on address (first byte if 10 bit)
*/
/* Wait for ACK/NACK on address (first byte if 10 bit) */
case I2CSTATE_ADDRWFACKNACK:
if (priv->i2c_reg_if & I2C_IF_NACK)
@@ -999,9 +1028,7 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
goto done;
/******************************************************
* Wait for ACK/NACK on second byte of 10 bit address
*/
/* Wait for ACK/NACK on second byte of 10 bit address */
case I2CSTATE_ADDRWF2NDACKNACK:
if (priv->i2c_reg_if & I2C_IF_NACK)
@@ -1030,14 +1057,13 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
{
priv->i2c_state = I2CSTATE_DATASEND;
}
continue;
}
goto done;
/*******************************
* Send repeated start+address
*/
/* Send repeated start+address */
case I2CSTATE_RSTARTADDRSEND:
if (priv->flags & I2C_M_TEN)
@@ -1078,8 +1104,7 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
efm32_i2c_putreg(priv, EFM32_I2C_TXDATA_OFFSET, regval);
goto done;
/***********************************************
* Wait for ACK/NACK on repeated start+address
/* Wait for ACK/NACK on repeated start+address
* (first byte if 10 bit)
*/
@@ -1110,11 +1135,10 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
goto done;
/*****************************
* Send a data byte to slave
*/
/* Send a data byte to slave */
case I2CSTATE_DATASEND:
/* Reached end of data buffer? */
if (priv->dcnt == 0)
@@ -1153,9 +1177,7 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
priv->i2c_state = I2CSTATE_DATAWFACKNACK;
goto done;
/*********************************************************
* Wait for ACK/NACK from slave after sending data to it
*/
/* Wait for ACK/NACK from slave after sending data to it */
case I2CSTATE_DATAWFACKNACK:
if (priv->i2c_reg_if & I2C_IF_NACK)
@@ -1171,11 +1193,10 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
priv->i2c_state = I2CSTATE_DATASEND;
continue;
}
goto done;
/****************************
* Wait for data from slave
*/
/* Wait for data from slave */
case I2CSTATE_WFDATA:
if (priv->i2c_reg_if & I2C_IF_RXDATAV)
@@ -1200,7 +1221,6 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
{
priv->i2c_state = I2CSTATE_WFSTOPSENT;
efm32_i2c_putreg(priv, EFM32_I2C_CMD_OFFSET, I2C_CMD_STOP);
}
else
{
@@ -1210,20 +1230,20 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
if (priv->dcnt == 1)
{
/* If there is more than one byte to receive and this is
* the next to last byte we need to transmit the NACK
* now, before receiving the last byte.
/* If there is more than one byte to receive and this
* is the next to last byte we need to transmit the
* NAK now, before receiving the last byte.
*/
efm32_i2c_putreg(priv, EFM32_I2C_CMD_OFFSET, I2C_CMD_NACK);
efm32_i2c_putreg(priv, EFM32_I2C_CMD_OFFSET,
I2C_CMD_NACK);
}
}
}
goto done;
/***********************************
* Wait for STOP to have been sent
*/
/* Wait for STOP to have been sent */
case I2CSTATE_WFSTOPSENT:
if (priv->i2c_reg_if & I2C_IF_MSTOP)
@@ -1234,9 +1254,7 @@ static int efm32_i2c_isr_process(struct efm32_i2c_priv_s *priv)
goto done;
/******************************/
/* Unexpected state, SW fault */
/******************************/
default:
priv->result = I2CRESULT_SWFAULT;
@@ -1294,12 +1312,18 @@ static int efm32_i2c_isr(int irq, void *context, FAR void *arg)
static void efm32_i2c_hwreset(FAR struct efm32_i2c_priv_s *priv)
{
efm32_i2c_putreg(priv, EFM32_I2C_CTRL_OFFSET, _I2C_CTRL_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_CLKDIV_OFFSET, _I2C_CLKDIV_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_SADDR_OFFSET, _I2C_SADDR_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_SADDRMASK_OFFSET, _I2C_SADDRMASK_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_IEN_OFFSET, _I2C_IEN_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_IFC_OFFSET, _I2C_IFC_MASK);
efm32_i2c_putreg(priv, EFM32_I2C_CTRL_OFFSET,
_I2C_CTRL_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_CLKDIV_OFFSET,
_I2C_CLKDIV_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_SADDR_OFFSET,
_I2C_SADDR_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_SADDRMASK_OFFSET,
_I2C_SADDRMASK_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_IEN_OFFSET,
_I2C_IEN_RESETVALUE);
efm32_i2c_putreg(priv, EFM32_I2C_IFC_OFFSET,
_I2C_IFC_MASK);
/* Do not reset route register, setting should be done independently */
}
@@ -1423,7 +1447,7 @@ static int efm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct efm32_i2c_priv_s *priv = (struct efm32_i2c_priv_s *)dev;
int ret = OK;
int ret;
DEBUGASSERT(count > 0);
@@ -1434,7 +1458,11 @@ static int efm32_i2c_transfer(FAR struct i2c_master_s *dev,
/* Ensure that address or flags don't change meanwhile */
efm32_i2c_sem_wait(priv);
ret = efm32_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
/* Reset ptr and dcnt to ensure an unexpected data interrupt doesn't
* overwrite stale data.
@@ -1486,8 +1514,9 @@ static int efm32_i2c_transfer(FAR struct i2c_master_s *dev,
efm32_i2c_putreg(priv, EFM32_I2C_IFC_OFFSET, _I2C_IFC_MASK);
/* Call once isr to start state machine. I2C interrupt are disabled and will
* be enabled in efm32_i2c_sem_waitdone if CONFIG_I2C_POLLED is NOT defined
/* Call once isr to start state machine. I2C interrupt are disabled and
* will be enabled in efm32_i2c_sem_waitdone if CONFIG_I2C_POLLED is NOT
* defined.
*/
efm32_i2c_isr_process(priv);
@@ -1564,7 +1593,7 @@ static int efm32_i2c_transfer(FAR struct i2c_master_s *dev,
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: efm32_i2c_reset
*
* Description:
@@ -1576,7 +1605,7 @@ static int efm32_i2c_transfer(FAR struct i2c_master_s *dev,
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_I2C_RESET
int efm32_i2c_reset(FAR struct i2c_master_s *dev)
@@ -1586,7 +1615,7 @@ int efm32_i2c_reset(FAR struct i2c_master_s *dev)
unsigned int stretch_count;
uint32_t scl_gpio;
uint32_t sda_gpio;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -1596,7 +1625,13 @@ int efm32_i2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
efm32_i2c_sem_wait(priv);
ret = efm32_i2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* De-init the port */
@@ -1676,6 +1711,7 @@ int efm32_i2c_reset(FAR struct i2c_master_s *dev)
ret = OK;
out:
/* Release the port for re-use by other clients */
efm32_i2c_sem_post(priv);
+77 -29
View File
@@ -191,8 +191,14 @@ struct imxrt_lpi2c_config_s
struct imxrt_lpi2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct imxrt_lpi2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct imxrt_lpi2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -225,24 +231,31 @@ struct imxrt_lpi2c_priv_s
* Private Function Prototypes
****************************************************************************/
static inline uint32_t imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv,
uint16_t offset);
static inline uint32_t
imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv, uint16_t offset);
static inline void imxrt_lpi2c_putreg(FAR struct imxrt_lpi2c_priv_s *priv,
uint16_t offset, uint32_t value);
static inline void imxrt_lpi2c_modifyreg(FAR struct imxrt_lpi2c_priv_s *priv,
uint16_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void imxrt_lpi2c_sem_wait(FAR struct imxrt_lpi2c_priv_s *priv);
static inline int imxrt_lpi2c_sem_wait(FAR struct imxrt_lpi2c_priv_s *priv);
static int
imxrt_lpi2c_sem_wait_uninterruptible(FAR struct imxrt_lpi2c_priv_s *priv);
#ifdef CONFIG_IMXRT_LPI2C_DYNTIMEO
static useconds_t imxrt_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_IMXRT_LPI2C_DYNTIMEO */
static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void imxrt_lpi2c_sem_waitstop(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void imxrt_lpi2c_sem_post(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void imxrt_lpi2c_sem_init(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv);
static inline int
imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void
imxrt_lpi2c_sem_waitstop(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void
imxrt_lpi2c_sem_post(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void
imxrt_lpi2c_sem_init(FAR struct imxrt_lpi2c_priv_s *priv);
static inline void
imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv);
#ifdef CONFIG_I2C_TRACE
static void imxrt_lpi2c_tracereset(FAR struct imxrt_lpi2c_priv_s *priv);
@@ -258,7 +271,8 @@ static void imxrt_lpi2c_setclock(FAR struct imxrt_lpi2c_priv_s *priv,
static inline void imxrt_lpi2c_sendstart(FAR struct imxrt_lpi2c_priv_s *priv,
uint8_t address);
static inline void imxrt_lpi2c_sendstop(FAR struct imxrt_lpi2c_priv_s *priv);
static inline uint32_t imxrt_lpi2c_getstatus(FAR struct imxrt_lpi2c_priv_s *priv);
static inline uint32_t
imxrt_lpi2c_getstatus(FAR struct imxrt_lpi2c_priv_s *priv);
static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s * priv);
@@ -472,8 +486,8 @@ static struct imxrt_lpi2c_priv_s imxrt_lpi2c4_priv =
*
****************************************************************************/
static inline uint32_t imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv,
uint16_t offset)
static inline uint32_t
imxrt_lpi2c_getreg(FAR struct imxrt_lpi2c_priv_s *priv, uint16_t offset)
{
return getreg32(priv->config->base + offset);
}
@@ -511,13 +525,28 @@ static inline void imxrt_lpi2c_modifyreg(FAR struct imxrt_lpi2c_priv_s *priv,
* Name: imxrt_lpi2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
* Take the exclusive access, waiting as necessary. May be interrupted by
* a signal.
*
****************************************************************************/
static inline void imxrt_lpi2c_sem_wait(FAR struct imxrt_lpi2c_priv_s *priv)
static inline int imxrt_lpi2c_sem_wait(FAR struct imxrt_lpi2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait(&priv->sem_excl);
}
/****************************************************************************
* Name: imxrt_lpi2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary.
*
****************************************************************************/
static int
imxrt_lpi2c_sem_wait_uninterruptible(FAR struct imxrt_lpi2c_priv_s *priv)
{
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/****************************************************************************
@@ -559,7 +588,8 @@ static useconds_t imxrt_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs)
****************************************************************************/
#ifndef CONFIG_I2C_POLLED
static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv)
static inline int
imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv)
{
struct timespec abstime;
irqstate_t flags;
@@ -671,7 +701,8 @@ static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv)
return ret;
}
#else
static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv)
static inline int
imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv)
{
clock_t timeout;
clock_t start;
@@ -730,7 +761,8 @@ static inline int imxrt_lpi2c_sem_waitdone(FAR struct imxrt_lpi2c_priv_s *priv)
*
****************************************************************************/
static inline void imxrt_lpi2c_sem_waitstop(FAR struct imxrt_lpi2c_priv_s *priv)
static inline void
imxrt_lpi2c_sem_waitstop(FAR struct imxrt_lpi2c_priv_s *priv)
{
clock_t start;
clock_t elapsed;
@@ -853,7 +885,8 @@ static inline void imxrt_lpi2c_sem_init(FAR struct imxrt_lpi2c_priv_s *priv)
*
****************************************************************************/
static inline void imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv)
static inline void
imxrt_lpi2c_sem_destroy(FAR struct imxrt_lpi2c_priv_s *priv)
{
nxsem_destroy(&priv->sem_excl);
#ifndef CONFIG_I2C_POLLED
@@ -969,8 +1002,10 @@ static void imxrt_lpi2c_tracedump(FAR struct imxrt_lpi2c_priv_s *priv)
{
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x TIME: %d\n",
i + 1, trace->status, trace->count, g_trace_names[trace->event],
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x "
"TIME: %d\n",
i + 1, trace->status, trace->count,
g_trace_names[trace->event],
trace->event, trace->parm, trace->time - priv->start_time);
}
}
@@ -1209,7 +1244,8 @@ static inline void imxrt_lpi2c_sendstop(FAR struct imxrt_lpi2c_priv_s *priv)
*
****************************************************************************/
static inline uint32_t imxrt_lpi2c_getstatus(FAR struct imxrt_lpi2c_priv_s *priv)
static inline uint32_t
imxrt_lpi2c_getstatus(FAR struct imxrt_lpi2c_priv_s *priv)
{
return imxrt_lpi2c_getreg(priv, IMXRT_LPI2C_MSR_OFFSET);
}
@@ -1240,7 +1276,8 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv)
/* Check if there is more bytes to send */
else if (((priv->flags & I2C_M_READ) == 0) && (status & LPI2C_MSR_TDF) != 0)
else if (((priv->flags & I2C_M_READ) == 0) &&
(status & LPI2C_MSR_TDF) != 0)
{
if (priv->dcnt > 0)
{
@@ -1259,7 +1296,8 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv)
/* Check if there is more bytes to read */
else if (((priv->flags & I2C_M_READ) != 0) && (status & LPI2C_MSR_RDF) != 0)
else if (((priv->flags & I2C_M_READ) != 0) &&
(status & LPI2C_MSR_RDF) != 0)
{
/* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
@@ -1628,13 +1666,17 @@ static int imxrt_lpi2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct imxrt_lpi2c_priv_s *priv = (struct imxrt_lpi2c_priv_s *)dev;
int ret = 0;
int ret;
DEBUGASSERT(count > 0);
/* Ensure that address or flags don't change meanwhile */
imxrt_lpi2c_sem_wait(priv);
ret = imxrt_lpi2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
/* Clear any pending error interrupts */
@@ -1743,7 +1785,7 @@ static int imxrt_lpi2c_reset(FAR struct i2c_master_s *dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -1753,7 +1795,13 @@ static int imxrt_lpi2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
imxrt_lpi2c_sem_wait(priv);
ret = imxrt_lpi2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
+47 -13
View File
@@ -113,8 +113,14 @@ struct kinetis_i2c_config_s
struct kinetis_i2cdev_s
{
struct i2c_master_s dev; /* Generic I2C device */
const struct kinetis_i2c_config_s *config; /* Port configuration */
/* Generic I2C device */
struct i2c_master_s dev;
/* Port configuration */
const struct kinetis_i2c_config_s *config;
uint32_t frequency; /* Current I2C frequency */
uint16_t nmsg; /* Number of transfer remaining */
uint16_t wrcnt; /* number of bytes sent to tx fifo */
@@ -143,8 +149,11 @@ static void kinetis_i2c_putreg(struct kinetis_i2cdev_s *priv,
/* Exclusion Helpers */
static inline void kinetis_i2c_sem_init(FAR struct kinetis_i2cdev_s *priv);
static inline void kinetis_i2c_sem_destroy(FAR struct kinetis_i2cdev_s *priv);
static inline void kinetis_i2c_sem_wait(FAR struct kinetis_i2cdev_s *priv);
static inline void
kinetis_i2c_sem_destroy(FAR struct kinetis_i2cdev_s *priv);
static inline int kinetis_i2c_sem_wait(FAR struct kinetis_i2cdev_s *priv);
static int
kinetis_i2c_sem_wait_uninterruptible(FAR struct kinetis_i2cdev_s *priv);
static inline void kinetis_i2c_sem_post(struct kinetis_i2cdev_s *priv);
/* Signal Helper */
@@ -344,13 +353,28 @@ static inline void kinetis_i2c_sem_destroy(FAR struct kinetis_i2cdev_s *priv)
* Name: kinetis_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by
* a signal.
*
****************************************************************************/
static inline int kinetis_i2c_sem_wait(FAR struct kinetis_i2cdev_s *priv)
{
return nxsem_wait(&priv->mutex);
}
/****************************************************************************
* Name: kinetis_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
****************************************************************************/
static inline void kinetis_i2c_sem_wait(FAR struct kinetis_i2cdev_s *priv)
static int
kinetis_i2c_sem_wait_uninterruptible(FAR struct kinetis_i2cdev_s *priv)
{
nxsem_wait_uninterruptible(&priv->mutex);
return nxsem_wait_uninterruptible(&priv->mutex);
}
/****************************************************************************
@@ -370,7 +394,7 @@ static inline void kinetis_i2c_sem_post(struct kinetis_i2cdev_s *priv)
* Name: kinetis_i2c_wait
*
* Description:
* Wait on the signaling semaphore
* Wait on the signaling semaphore. May be interrupted by a signal.
*
****************************************************************************/
@@ -1121,14 +1145,18 @@ static int kinetis_i2c_transfer(struct i2c_master_s *dev,
{
struct kinetis_i2cdev_s *priv = (struct kinetis_i2cdev_s *)dev;
int msg_n;
int rv;
int ret;
i2cinfo("msgs=%p count=%d\n", msgs, count);
DEBUGASSERT(dev != NULL && msgs != NULL && (unsigned)count <= UINT16_MAX);
/* Get exclusive access to the I2C bus */
kinetis_i2c_sem_wait(priv);
ret = kinetis_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
/* Set up for the transfer */
@@ -1210,13 +1238,13 @@ timeout:
/* Get the result before releasing the bus */
rv = (priv->state != STATE_OK) ? -EIO : 0;
ret = (priv->state != STATE_OK) ? -EIO : 0;
/* Release access to I2C bus */
kinetis_i2c_sem_post(priv);
return rv;
return ret;
}
/****************************************************************************
@@ -1242,7 +1270,7 @@ static int kinetis_i2c_reset(struct i2c_master_s *dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -1252,7 +1280,13 @@ static int kinetis_i2c_reset(struct i2c_master_s *dev)
/* Lock out other clients */
kinetis_i2c_sem_wait(priv);
ret = kinetis_i2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
+105 -59
View File
@@ -126,8 +126,14 @@ struct lc823450_i2c_config_s
struct lc823450_i2c_priv_s
{
FAR const struct i2c_ops_s *ops; /* Standard I2C operations */
FAR const struct lc823450_i2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
FAR const struct i2c_ops_s *ops;
/* Port configuration */
FAR const struct lc823450_i2c_config_s *config;
int refs; /* Referernce count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -150,20 +156,31 @@ struct lc823450_i2c_priv_s
* Private Function Prototypes
****************************************************************************/
static inline void lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv);
static inline void lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv);
static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv);
static inline int
lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv);
static inline void
lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv);
static inline int
lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv);
#ifndef CONFIG_I2C_POLLED
static inline void lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv);
static inline void lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv);
static inline void
lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv);
static inline void
lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv);
#endif
static inline bool lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv);
static inline bool lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv);
static inline void lc823450_i2c_prepxfer(FAR struct lc823450_i2c_priv_s *priv);
static inline void lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv);
static inline void lc823450_i2c_sendstop(FAR struct lc823450_i2c_priv_s *priv);
static inline uint32_t lc823450_i2c_readdata(FAR struct lc823450_i2c_priv_s *priv);
static inline bool
lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv);
static inline bool
lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv);
static inline void
lc823450_i2c_prepxfer(FAR struct lc823450_i2c_priv_s *priv);
static inline void
lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv);
static inline void
lc823450_i2c_sendstop(FAR struct lc823450_i2c_priv_s *priv);
static inline uint32_t
lc823450_i2c_readdata(FAR struct lc823450_i2c_priv_s *priv);
static void lc823450_i2c_starttransfer(FAR struct lc823450_i2c_priv_s *priv);
static int lc823450_i2c_poll(FAR struct lc823450_i2c_priv_s *priv);
@@ -172,7 +189,8 @@ static int lc823450_i2c_isr(int irq, FAR void *context, FAR void *arg);
#endif
static int lc823450_i2c_init(FAR struct lc823450_i2c_priv_s *priv, int port);
static int lc823450_i2c_deinit(FAR struct lc823450_i2c_priv_s *priv, int port);
static int
lc823450_i2c_deinit(FAR struct lc823450_i2c_priv_s *priv, int port);
static int lc823450_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
@@ -255,13 +273,14 @@ static struct lc823450_i2c_priv_s lc823450_i2c1_priv =
* Name: lc823450_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
* Take the exclusive access, waiting as necessary. May be interrupted by
* a signal.
*
****************************************************************************/
static inline void lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv)
static inline int lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait(&priv->sem_excl);
}
/****************************************************************************
@@ -272,7 +291,8 @@ static inline void lc823450_i2c_sem_wait(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline void lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv)
static inline void
lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv)
{
nxsem_post(&priv->sem_excl);
}
@@ -286,7 +306,8 @@ static inline void lc823450_i2c_sem_post(FAR struct lc823450_i2c_priv_s *priv)
****************************************************************************/
#ifndef CONFIG_I2C_POLLED
static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv)
static inline int
lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv)
{
struct timespec abstime;
int ret;
@@ -317,10 +338,10 @@ static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
if (ret < 0)
{
/* Break out of the loop on irrecoverable errors. This would
* include timeouts and mystery errors reported by nxsem_timedwait.
*/
break;
}
}
@@ -333,7 +354,8 @@ static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv
return ret;
}
#else
static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv)
static inline int
lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv)
{
uint32_t timeout;
clock_t start;
@@ -388,8 +410,11 @@ static inline int lc823450_i2c_sem_waitdone(FAR struct lc823450_i2c_priv_s *priv
static void lc823450_i2c_prepxfer(FAR struct lc823450_i2c_priv_s *priv)
{
uint32_t base = priv->config->base;
putreg32(((lc823450_get_systemfreq() / priv->msgv->frequency + 7) / 8) & 0xffff, base + I2CCKS);
putreg32((priv->msgv->addr << 1) | (priv->msgv->flags & I2C_M_READ), base + I2CTXD);
putreg32(((lc823450_get_systemfreq() / priv->msgv->frequency + 7) / 8) &
0xffff,
base + I2CCKS);
putreg32((priv->msgv->addr << 1) | (priv->msgv->flags & I2C_M_READ),
base + I2CTXD);
}
/****************************************************************************
@@ -400,7 +425,8 @@ static void lc823450_i2c_prepxfer(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline bool lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv)
static inline bool
lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv)
{
return (getreg32(priv->config->base + I2CSTR) & I2C_STR_BBSY) != 0;
}
@@ -413,7 +439,8 @@ static inline bool lc823450_i2c_checkbusy(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline bool lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv)
static inline bool
lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv)
{
return (getreg32(priv->config->base + I2CSTR) & I2C_STR_IREQ) != 0;
}
@@ -426,7 +453,8 @@ static inline bool lc823450_i2c_checkirq(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline bool lc823450_i2c_checkack(FAR struct lc823450_i2c_priv_s *priv)
static inline bool
lc823450_i2c_checkack(FAR struct lc823450_i2c_priv_s *priv)
{
return (getreg32(priv->config->base + I2CSTR) & I2C_STR_ACKD) != 0;
}
@@ -439,7 +467,8 @@ static inline bool lc823450_i2c_checkack(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline void lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv)
static inline void
lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv)
{
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_TRX, I2C_CTL_TRX);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ST, I2C_CTL_ST);
@@ -453,7 +482,8 @@ static inline void lc823450_i2c_sendstart(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline void lc823450_i2c_sendstop(FAR struct lc823450_i2c_priv_s *priv)
static inline void
lc823450_i2c_sendstop(FAR struct lc823450_i2c_priv_s *priv)
{
modifyreg32(priv->config->base + I2CSTR, I2C_STR_IREQ, 0);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_TRX, I2C_CTL_TRX);
@@ -502,7 +532,8 @@ static int lc823450_i2c_reset(FAR struct i2c_master_s *dev)
****************************************************************************/
#ifndef CONFIG_I2C_POLLED
static inline void lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv)
static inline void
lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv)
{
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_IREQEN, I2C_CTL_IREQEN);
}
@@ -517,7 +548,8 @@ static inline void lc823450_i2c_enableirq(FAR struct lc823450_i2c_priv_s *priv)
****************************************************************************/
#ifndef CONFIG_I2C_POLLED
static inline void lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv)
static inline void
lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv)
{
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_IREQEN, 0);
}
@@ -531,7 +563,8 @@ static inline void lc823450_i2c_disableirq(FAR struct lc823450_i2c_priv_s *priv)
*
****************************************************************************/
static inline uint32_t lc823450_i2c_readdata(FAR struct lc823450_i2c_priv_s *priv)
static inline uint32_t
lc823450_i2c_readdata(FAR struct lc823450_i2c_priv_s *priv)
{
return getreg32(priv->config->base + I2CRXD);
}
@@ -558,8 +591,10 @@ static void lc823450_i2c_starttransfer(FAR struct lc823450_i2c_priv_s *priv)
{
/* If the next byte to be received is not final, we have to send ACK. */
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, I2C_CTL_ACK);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK,
I2C_CTL_ACK);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG,
I2C_CTL_BTRIG);
}
else if (priv->dcnt == 1)
{
@@ -567,19 +602,20 @@ static void lc823450_i2c_starttransfer(FAR struct lc823450_i2c_priv_s *priv)
if (priv->msgc > 0 && priv->msgv->flags & I2C_M_READ)
{
/* But if there is a next message and the direction is READ, we have
* to send ACK.
/* But if there is a next message and the direction is READ,
* we have to send ACK.
*/
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, I2C_CTL_ACK);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK,
I2C_CTL_ACK);
}
else
{
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_ACK, 0);
}
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG,
I2C_CTL_BTRIG);
}
priv->irqstate = IRQSTATE_WRECV;
@@ -589,8 +625,10 @@ static void lc823450_i2c_starttransfer(FAR struct lc823450_i2c_priv_s *priv)
if (priv->dcnt > 0)
{
putreg32(*priv->ptr, priv->config->base + I2CTXD);
modifyreg32(priv->config->base + I2CCTL, I2C_CTL_BTRIG, I2C_CTL_BTRIG);
modifyreg32(priv->config->base + I2CCTL,
I2C_CTL_BTRIG, I2C_CTL_BTRIG);
}
priv->irqstate = IRQSTATE_WSEND;
}
}
@@ -660,7 +698,9 @@ static int lc823450_i2c_poll(FAR struct lc823450_i2c_priv_s *priv)
priv->msgv++;
priv->msgc--;
i2cinfo("WSTART (dcnt=%d flags=%xh msgc=%d)\n", priv->dcnt, priv->flags, priv->msgc);
i2cinfo("WSTART (dcnt=%d flags=%xh msgc=%d)\n",
priv->dcnt, priv->flags, priv->msgc);
lc823450_i2c_starttransfer(priv);
}
@@ -681,9 +721,9 @@ static int lc823450_i2c_poll(FAR struct lc823450_i2c_priv_s *priv)
}
else if (priv->irqstate == IRQSTATE_WRECV)
{
/* When the master is receiver, it shall send ACK instead of the slave when
* it receives data. In this case, it don't have to check if ACK comes,
* because the slave does not send ACK.
/* When the master is receiver, it shall send ACK instead of the slave
* when it receives data. In this case, it don't have to check if
* ACK comes, because the slave does not send ACK.
*/
*priv->ptr++ = lc823450_i2c_readdata(priv);
@@ -743,24 +783,25 @@ static int lc823450_i2c_poll(FAR struct lc823450_i2c_priv_s *priv)
}
else
{
/* We need restart from START condition. If transfer direction is different
* between current message and next message, restart is necessary.
/* We need restart from START condition. If transfer direction
* is different between current message and next message,
* restart is necessary.
*/
i2cinfo("re-START condition\n");
#ifdef CONFIG_I2C_RESET
/* Reset I2C bus by softreset. There is not description of the reset,
* but in order to recover I2C bus busy, it must be done.
* Please refer to macaron's code.
/* Reset I2C bus by softreset. There is not description of the
* reset, but in order to recover I2C bus busy, it must be
* done. Please refer to macaron's code.
*/
lc823450_i2c_reset((FAR struct i2c_master_s *)priv);
#endif
#ifndef CONFIG_I2C_POLLED
/* We have to enable interrupt again, because all registers are reset by
* lc823450_i2c_reset().
/* We have to enable interrupt again, because all registers
* are reset by lc823450_i2c_reset().
*/
lc823450_i2c_enableirq(priv);
@@ -774,8 +815,8 @@ static int lc823450_i2c_poll(FAR struct lc823450_i2c_priv_s *priv)
}
else if (priv->msgv)
{
/* There are no other message. We send STOP condition because all messages
* are transferred.
/* There are no other message. We send STOP condition because all
* messages are transferred.
*/
i2cinfo("STOP condition\n");
@@ -881,7 +922,8 @@ static int lc823450_i2c_init(FAR struct lc823450_i2c_priv_s *priv, int port)
*
****************************************************************************/
static int lc823450_i2c_deinit(FAR struct lc823450_i2c_priv_s *priv, int port)
static int lc823450_i2c_deinit(FAR struct lc823450_i2c_priv_s *priv,
int port)
{
/* Disable I2C */
@@ -962,9 +1004,13 @@ static int lc823450_i2c_transfer(FAR struct i2c_master_s *dev,
return -EINVAL;
}
/* ensure that address or flags don't change meanwhile */
/* Ensure that address or flags don't change meanwhile */
lc823450_i2c_sem_wait(priv);
ret = lc823450_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
priv->timedout = false;
@@ -1008,7 +1054,6 @@ static int lc823450_i2c_transfer(FAR struct i2c_master_s *dev,
if (lc823450_i2c_sem_waitdone(priv) < 0)
{
irqs = enter_critical_section();
ret = -ETIMEDOUT;
@@ -1032,7 +1077,8 @@ static int lc823450_i2c_transfer(FAR struct i2c_master_s *dev,
}
else
{
i2cerr("No need of timeout handling. It may be done in irq handler\n");
i2cerr("No need of timeout handling. "
"It may be done in irq handler\n");
leave_critical_section(irqs);
}
@@ -1058,7 +1104,6 @@ exit:
lc823450_i2c_sem_post(priv);
return ret;
}
/****************************************************************************
@@ -1185,7 +1230,8 @@ int lc823450_i2cbus_uninitialize(FAR struct i2c_master_s *dev)
* Name: lc823450_i2cbus_changetimeout
****************************************************************************/
void lc823450_i2cbus_changetimeout(FAR struct i2c_master_s *dev, uint32_t timeoms)
void lc823450_i2cbus_changetimeout(FAR struct i2c_master_s *dev,
uint32_t timeoms)
{
FAR struct lc823450_i2c_priv_s *priv = (struct lc823450_i2c_priv_s *)dev;
priv->timeoms = timeoms;
+125 -55
View File
@@ -166,11 +166,11 @@ enum s32k1xx_trace_e
struct s32k1xx_trace_s
{
uint32_t status; /* I2C 32-bit SR2|SR1 status */
uint32_t count; /* Interrupt count when status change */
uint32_t status; /* I2C 32-bit SR2|SR1 status */
uint32_t count; /* Interrupt count when status change */
enum s32k1xx_intstate_e event; /* Last event that occurred with this status */
uint32_t parm; /* Parameter associated with the event */
clock_t time; /* First of event or first status */
uint32_t parm; /* Parameter associated with the event */
clock_t time; /* First of event or first status */
};
/* I2C Device hardware configuration */
@@ -193,8 +193,14 @@ struct s32k1xx_lpi2c_config_s
struct s32k1xx_lpi2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct s32k1xx_lpi2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct s32k1xx_lpi2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -227,41 +233,58 @@ struct s32k1xx_lpi2c_priv_s
* Private Function Prototypes
****************************************************************************/
static inline uint32_t s32k1xx_lpi2c_getreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset);
static inline void s32k1xx_lpi2c_putreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t value);
static inline void s32k1xx_lpi2c_modifyreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void s32k1xx_lpi2c_sem_wait(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline uint32_t
s32k1xx_lpi2c_getreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset);
static inline void
s32k1xx_lpi2c_putreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t value);
static inline void
s32k1xx_lpi2c_modifyreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t clearbits,
uint32_t setbits);
static inline int
s32k1xx_lpi2c_sem_wait(FAR struct s32k1xx_lpi2c_priv_s *priv);
static int
s32k1xx_lpi2c_sem_wait_uninterruptible(
FAR struct s32k1xx_lpi2c_priv_s *priv);
#ifdef CONFIG_S32K1XX_I2C_DYNTIMEO
static useconds_t s32k1xx_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
static useconds_t
s32k1xx_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_S32K1XX_I2C_DYNTIMEO */
static inline int s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void s32k1xx_lpi2c_sem_waitstop(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void s32k1xx_lpi2c_sem_post(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void s32k1xx_lpi2c_sem_init(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void s32k1xx_lpi2c_sem_destroy(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline int
s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void
s32k1xx_lpi2c_sem_waitstop(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void
s32k1xx_lpi2c_sem_post(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void
s32k1xx_lpi2c_sem_init(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void
s32k1xx_lpi2c_sem_destroy(FAR struct s32k1xx_lpi2c_priv_s *priv);
#ifdef CONFIG_I2C_TRACE
static void s32k1xx_lpi2c_tracereset(FAR struct s32k1xx_lpi2c_priv_s *priv);
static void s32k1xx_lpi2c_tracenew(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint32_t status);
static void s32k1xx_lpi2c_traceevent(FAR struct s32k1xx_lpi2c_priv_s *priv,
enum s32k1xx_trace_e event, uint32_t parm);
enum s32k1xx_trace_e event,
uint32_t parm);
static void s32k1xx_lpi2c_tracedump(FAR struct s32k1xx_lpi2c_priv_s *priv);
#endif /* CONFIG_I2C_TRACE */
static uint32_t s32k1xx_lpi2c_pckfreq(uintptr_t base);
static void s32k1xx_lpi2c_setclock(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint32_t frequency);
static inline void s32k1xx_lpi2c_sendstart(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint8_t address);
static inline void s32k1xx_lpi2c_sendstop(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline uint32_t s32k1xx_lpi2c_getstatus(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline void
s32k1xx_lpi2c_sendstart(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint8_t address);
static inline void
s32k1xx_lpi2c_sendstop(FAR struct s32k1xx_lpi2c_priv_s *priv);
static inline uint32_t
s32k1xx_lpi2c_getstatus(FAR struct s32k1xx_lpi2c_priv_s *priv);
static int s32k1xx_lpi2c_isr_process(struct s32k1xx_lpi2c_priv_s * priv);
@@ -389,8 +412,9 @@ static struct s32k1xx_lpi2c_priv_s s32k1xx_lpi2c1_priv =
*
****************************************************************************/
static inline uint32_t s32k1xx_lpi2c_getreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset)
static inline uint32_t
s32k1xx_lpi2c_getreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset)
{
return getreg32(priv->config->base + offset);
}
@@ -403,8 +427,9 @@ static inline uint32_t s32k1xx_lpi2c_getreg(FAR struct s32k1xx_lpi2c_priv_s *pri
*
****************************************************************************/
static inline void s32k1xx_lpi2c_putreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t value)
static inline void
s32k1xx_lpi2c_putreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t value)
{
putreg32(value, priv->config->base + offset);
}
@@ -417,9 +442,10 @@ static inline void s32k1xx_lpi2c_putreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
*
****************************************************************************/
static inline void s32k1xx_lpi2c_modifyreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t clearbits,
uint32_t setbits)
static inline void
s32k1xx_lpi2c_modifyreg(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint16_t offset, uint32_t clearbits,
uint32_t setbits)
{
modifyreg32(priv->config->base + offset, clearbits, setbits);
}
@@ -428,13 +454,30 @@ static inline void s32k1xx_lpi2c_modifyreg(FAR struct s32k1xx_lpi2c_priv_s *priv
* Name: s32k1xx_lpi2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by
* a signal.
*
****************************************************************************/
static inline int
s32k1xx_lpi2c_sem_wait(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
return nxsem_wait(&priv->sem_excl);
}
/****************************************************************************
* Name: s32k1xx_lpi2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
****************************************************************************/
static inline void s32k1xx_lpi2c_sem_wait(FAR struct s32k1xx_lpi2c_priv_s *priv)
static int
s32k1xx_lpi2c_sem_wait_uninterruptible(
FAR struct s32k1xx_lpi2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/****************************************************************************
@@ -476,7 +519,8 @@ static useconds_t s32k1xx_lpi2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs)
****************************************************************************/
#ifndef CONFIG_I2C_POLLED
static inline int s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline int
s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
struct timespec abstime;
irqstate_t flags;
@@ -531,7 +575,9 @@ static inline int s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *pr
/* Add a value proportional to the number of bytes in the transfer */
#ifdef CONFIG_S32K1XX_I2C_DYNTIMEO
abstime.tv_nsec += 1000 * s32k1xx_lpi2c_tousecs(priv->msgc, priv->msgv);
abstime.tv_nsec +=
1000 * s32k1xx_lpi2c_tousecs(priv->msgc, priv->msgv);
if (abstime.tv_nsec >= 1000 * 1000 * 1000)
{
abstime.tv_sec++;
@@ -588,7 +634,8 @@ static inline int s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *pr
return ret;
}
#else
static inline int s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline int
s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
clock_t timeout;
clock_t start;
@@ -647,7 +694,8 @@ static inline int s32k1xx_lpi2c_sem_waitdone(FAR struct s32k1xx_lpi2c_priv_s *pr
*
****************************************************************************/
static inline void s32k1xx_lpi2c_sem_waitstop(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline void
s32k1xx_lpi2c_sem_waitstop(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
clock_t start;
clock_t elapsed;
@@ -748,7 +796,8 @@ static inline void s32k1xx_lpi2c_sem_post(struct s32k1xx_lpi2c_priv_s *priv)
*
****************************************************************************/
static inline void s32k1xx_lpi2c_sem_init(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline void
s32k1xx_lpi2c_sem_init(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
nxsem_init(&priv->sem_excl, 0, 1);
@@ -770,7 +819,8 @@ static inline void s32k1xx_lpi2c_sem_init(FAR struct s32k1xx_lpi2c_priv_s *priv)
*
****************************************************************************/
static inline void s32k1xx_lpi2c_sem_destroy(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline void
s32k1xx_lpi2c_sem_destroy(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
nxsem_destroy(&priv->sem_excl);
#ifndef CONFIG_I2C_POLLED
@@ -886,8 +936,10 @@ static void s32k1xx_lpi2c_tracedump(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x TIME: %d\n",
i + 1, trace->status, trace->count, g_trace_names[trace->event],
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x "
"TIME: %d\n",
i + 1, trace->status, trace->count,
g_trace_names[trace->event],
trace->event, trace->parm, trace->time - priv->start_time);
}
}
@@ -1090,8 +1142,9 @@ static void s32k1xx_lpi2c_setclock(FAR struct s32k1xx_lpi2c_priv_s *priv,
*
****************************************************************************/
static inline void s32k1xx_lpi2c_sendstart(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint8_t address)
static inline void
s32k1xx_lpi2c_sendstart(FAR struct s32k1xx_lpi2c_priv_s *priv,
uint8_t address)
{
uint32_t txcount = 0;
uint32_t status = 0;
@@ -1141,7 +1194,8 @@ static inline void s32k1xx_lpi2c_sendstart(FAR struct s32k1xx_lpi2c_priv_s *priv
*
****************************************************************************/
static inline void s32k1xx_lpi2c_sendstop(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline void
s32k1xx_lpi2c_sendstop(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
s32k1xx_lpi2c_putreg(priv, S32K1XX_LPI2C_MTDR_OFFSET, LPI2C_MTDR_CMD_STOP);
}
@@ -1154,7 +1208,8 @@ static inline void s32k1xx_lpi2c_sendstop(FAR struct s32k1xx_lpi2c_priv_s *priv)
*
****************************************************************************/
static inline uint32_t s32k1xx_lpi2c_getstatus(FAR struct s32k1xx_lpi2c_priv_s *priv)
static inline uint32_t
s32k1xx_lpi2c_getstatus(FAR struct s32k1xx_lpi2c_priv_s *priv)
{
return s32k1xx_lpi2c_getreg(priv, S32K1XX_LPI2C_MSR_OFFSET);
}
@@ -1185,7 +1240,8 @@ static int s32k1xx_lpi2c_isr_process(struct s32k1xx_lpi2c_priv_s *priv)
/* Check if there is more bytes to send */
else if (((priv->flags & I2C_M_READ) == 0) && (status & LPI2C_MSR_TDF) != 0)
else if (((priv->flags & I2C_M_READ) == 0) &&
(status & LPI2C_MSR_TDF) != 0)
{
if (priv->dcnt > 0)
{
@@ -1204,7 +1260,8 @@ static int s32k1xx_lpi2c_isr_process(struct s32k1xx_lpi2c_priv_s *priv)
/* Check if there is more bytes to read */
else if (((priv->flags & I2C_M_READ) != 0) && (status & LPI2C_MSR_RDF) != 0)
else if (((priv->flags & I2C_M_READ) != 0) &&
(status & LPI2C_MSR_RDF) != 0)
{
/* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
@@ -1222,8 +1279,10 @@ static int s32k1xx_lpi2c_isr_process(struct s32k1xx_lpi2c_priv_s *priv)
/* Receive a byte */
*priv->ptr++ = s32k1xx_lpi2c_getreg(priv, S32K1XX_LPI2C_MRDR_OFFSET) &
LPI2C_MRDR_DATA_MASK;
*priv->ptr++ =
s32k1xx_lpi2c_getreg(priv, S32K1XX_LPI2C_MRDR_OFFSET) &
LPI2C_MRDR_DATA_MASK;
priv->dcnt--;
#ifdef CONFIG_I2C_POLLED
@@ -1516,13 +1575,17 @@ static int s32k1xx_lpi2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct s32k1xx_lpi2c_priv_s *priv = (struct s32k1xx_lpi2c_priv_s *)dev;
int ret = 0;
int ret;
DEBUGASSERT(count > 0);
/* Ensure that address or flags don't change meanwhile */
s32k1xx_lpi2c_sem_wait(priv);
ret = s32k1xx_lpi2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
/* Clear any pending error interrupts */
@@ -1625,13 +1688,14 @@ static int s32k1xx_lpi2c_transfer(FAR struct i2c_master_s *dev,
#ifdef CONFIG_I2C_RESET
static int s32k1xx_lpi2c_reset(FAR struct i2c_master_s *dev)
{
FAR struct s32k1xx_lpi2c_priv_s *priv = (FAR struct s32k1xx_lpi2c_priv_s *)dev;
FAR struct s32k1xx_lpi2c_priv_s *priv =
(FAR struct s32k1xx_lpi2c_priv_s *)dev;
unsigned int clock_count;
unsigned int stretch_count;
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -1641,7 +1705,13 @@ static int s32k1xx_lpi2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
s32k1xx_lpi2c_sem_wait(priv);
ret = s32k1xx_lpi2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
+41 -25
View File
@@ -78,7 +78,8 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ***************************************************************/
/* Configuration ************************************************************/
#ifndef CONFIG_SAM34_TWIM0_FREQUENCY
# define CONFIG_SAM34_TWIM0_FREQUENCY 100000
@@ -92,12 +93,12 @@
# undef CONFIG_SAM34_TWI_REGDEBUG
#endif
/* Driver internal definitions *************************************************/
/* Driver internal definitions **********************************************/
#define TWI_TIMEOUT ((100 * CLK_TCK) / 1000) /* 100 mS */
/* Clocking to the TWO module(s) is provided by the main clocked, divided down
* as necessary.
/* Clocking to the TWO module(s) is provided by the main clocked, divided
* down as necessary.
*/
#define TWI_MAX_FREQUENCY 66000000 /* Maximum TWI frequency */
@@ -127,10 +128,10 @@ struct twi_dev_s
/* Debug stuff */
#ifdef CONFIG_SAM34_TWI_REGDEBUG
bool wrlast; /* Last was a write */
uint32_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
bool wrlast; /* Last was a write */
uint32_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
#endif
};
@@ -206,14 +207,14 @@ static const struct i2c_ops_s g_twiops =
};
/****************************************************************************
* Low-level Helpers
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: twi_takesem
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the receipt
* of signals).
* Take the wait semaphore. May be interrupted by a signal.
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
@@ -223,9 +224,9 @@ static const struct i2c_ops_s g_twiops =
*
****************************************************************************/
static void twi_takesem(sem_t *sem)
static int twi_takesem(sem_t *sem)
{
nxsem_wait_uninterruptible(sem);
return nxsem_wait(sem);
}
/****************************************************************************
@@ -333,7 +334,8 @@ static void twi_putabs(struct twi_dev_s *priv, uintptr_t address,
*
****************************************************************************/
static inline uint32_t twi_getrel(struct twi_dev_s *priv, unsigned int offset)
static inline uint32_t twi_getrel(struct twi_dev_s *priv,
unsigned int offset)
{
return twi_getabs(priv, priv->base + offset);
}
@@ -370,6 +372,8 @@ static inline void twi_putrel(struct twi_dev_s *priv, unsigned int offset,
static int twi_wait(struct twi_dev_s *priv)
{
int ret;
/* Start a timeout to avoid hangs */
wd_start(priv->timeout, TWI_TIMEOUT, twi_timeout, 1, (uint32_t)priv);
@@ -379,8 +383,14 @@ static int twi_wait(struct twi_dev_s *priv)
do
{
i2cinfo("TWI%d Waiting...\n", priv->twi);
twi_takesem(&priv->waitsem);
ret = twi_takesem(&priv->waitsem);
i2cinfo("TWI%d Awakened with result: %d\n", priv->twi, priv->result);
if (ret < 0)
{
wd_cancel(priv->timeout);
return ret;
}
}
while (priv->result == -EBUSY);
@@ -588,7 +598,8 @@ static void twi_startread(struct twi_dev_s *priv, struct i2c_msg_s *msg)
/* Set slave address and number of internal address bytes. */
twi_putrel(priv, SAM_TWI_MMR_OFFSET, 0);
twi_putrel(priv, SAM_TWI_MMR_OFFSET, TWI_MMR_IADRSZ_NONE | TWI_MMR_MREAD | TWI_MMR_DADR(msg->addr));
twi_putrel(priv, SAM_TWI_MMR_OFFSET,
TWI_MMR_IADRSZ_NONE | TWI_MMR_MREAD | TWI_MMR_DADR(msg->addr));
/* Set internal address bytes (not used) */
@@ -618,7 +629,8 @@ static void twi_startwrite(struct twi_dev_s *priv, struct i2c_msg_s *msg)
/* Set slave address and number of internal address bytes. */
twi_putrel(priv, SAM_TWI_MMR_OFFSET, 0);
twi_putrel(priv, SAM_TWI_MMR_OFFSET, TWI_MMR_IADRSZ_NONE | TWI_MMR_DADR(msg->addr));
twi_putrel(priv, SAM_TWI_MMR_OFFSET,
TWI_MMR_IADRSZ_NONE | TWI_MMR_DADR(msg->addr));
/* Set internal address bytes (not used) */
@@ -678,18 +690,22 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the device */
twi_takesem(&priv->exclsem);
ret = twi_takesem(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Setup the message transfer */
priv->msg = msgs;
priv->msgc = count;
/* Configure the I2C frequency.
* REVISIT: Note that the frequency is set only on the first message.
* This could be extended to support different transfer frequencies for
* each message segment.
*/
/* Configure the I2C frequency.
* REVISIT: Note that the frequency is set only on the first message.
* This could be extended to support different transfer frequencies for
* each message segment.
*/
twi_setfrequency(priv, msgs->frequency);
@@ -716,7 +732,7 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: twi_reset
*
* Description:
@@ -728,7 +744,7 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_I2C_RESET
static int twi_reset(FAR struct i2c_master_s * dev)
+76 -33
View File
@@ -78,7 +78,8 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ***************************************************************/
/* Configuration ************************************************************/
#ifndef CONFIG_SAMA5_TWI0_FREQUENCY
# define CONFIG_SAMA5_TWI0_FREQUENCY 100000
@@ -100,12 +101,14 @@
# undef CONFIG_SAMA5_TWI_REGDEBUG
#endif
/* Driver internal definitions *************************************************/
/* If verbose I2C debug output is enabled, then allow more time before we declare
* a timeout. The debug output from twi_interrupt will really slow things down!
/* Driver internal definitions **********************************************/
/* If verbose I2C debug output is enabled, then allow more time before we
* declare a timeout. The debug output from twi_interrupt will really slow
* things down!
*
* With a very slow clock (say 100,000 Hz), less than 100 usec would be required
* to transfer on byte. So these define a "long" timeout.
* With a very slow clock (say 100,000 Hz), less than 100 usec would be
* required to transfer on byte. So these define a "long" timeout.
*/
#ifdef CONFIG_DEBUG_I2C_INFO
@@ -131,6 +134,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
/* Invariant attributes of a TWI bus */
struct twi_attr_s
@@ -164,10 +168,10 @@ struct twi_dev_s
/* Debug stuff */
#ifdef CONFIG_SAMA5_TWI_REGDEBUG
bool wrlast; /* Last was a write */
uint32_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
bool wrlast; /* Last was a write */
uint32_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
#endif
};
@@ -177,7 +181,8 @@ struct twi_dev_s
/* Low-level helper functions */
static void twi_takesem(sem_t *sem);
static int twi_takesem(sem_t *sem);
static int twi_takesem_uninterruptible(sem_t *sem);
#define twi_givesem(sem) (nxsem_post(sem))
#ifdef CONFIG_SAMA5_TWI_REGDEBUG
@@ -290,14 +295,14 @@ static const struct i2c_ops_s g_twiops =
};
/****************************************************************************
* Low-level Helpers
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: twi_takesem
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the receipt
* of signals).
* Take the wait semaphore. May be interrupted by a signal.
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
@@ -307,9 +312,29 @@ static const struct i2c_ops_s g_twiops =
*
****************************************************************************/
static void twi_takesem(sem_t *sem)
static int twi_takesem(sem_t *sem)
{
nxsem_wait_uninterruptible(sem);
return nxsem_wait(sem);
}
/****************************************************************************
* Name: twi_takesem_uninterruptible
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the
* receipt of signals).
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
*
* Returned Value:
* None
*
****************************************************************************/
static int twi_takesem_uninterruptible(sem_t *sem)
{
return nxsem_wait_uninterruptible(sem);
}
/****************************************************************************
@@ -417,7 +442,8 @@ static void twi_putabs(struct twi_dev_s *priv, uintptr_t address,
*
****************************************************************************/
static inline uint32_t twi_getrel(struct twi_dev_s *priv, unsigned int offset)
static inline uint32_t twi_getrel(struct twi_dev_s *priv,
unsigned int offset)
{
return twi_getabs(priv, priv->attr->base + offset);
}
@@ -455,12 +481,14 @@ static inline void twi_putrel(struct twi_dev_s *priv, unsigned int offset,
static int twi_wait(struct twi_dev_s *priv, unsigned int size)
{
uint32_t timeout;
int ret;
/* Calculate a timeout value based on the size of the transfer
*
* ticks = msec-per-byte * bytes / msec-per-tick
*
* There is no concern about arithmetic overflow for reasonable transfer sizes.
* There is no concern about arithmetic overflow for reasonable transfer
* sizes.
*/
timeout = MSEC2TICK(TWI_TIMEOUT_MSPB);
@@ -469,8 +497,8 @@ static int twi_wait(struct twi_dev_s *priv, unsigned int size)
timeout = 1;
}
/* Then start the timeout. This timeout is needed to avoid hangs if/when an
* TWI transfer stalls.
/* Then start the timeout. This timeout is needed to avoid hangs if/when
* a TWI transfer stalls.
*/
wd_start(priv->timeout, timeout, twi_timeout, 1, (uint32_t)priv);
@@ -480,9 +508,15 @@ static int twi_wait(struct twi_dev_s *priv, unsigned int size)
do
{
i2cinfo("TWI%d Waiting...\n", priv->attr->twi);
twi_takesem(&priv->waitsem);
ret = twi_takesem(&priv->waitsem);
i2cinfo("TWI%d Awakened with result: %d\n",
priv->attr->twi, priv->result);
if (ret < 0)
{
wd_cancel(priv->timeout);
return ret;
}
}
while (priv->result == -EBUSY);
@@ -720,7 +754,8 @@ static void twi_startwrite(struct twi_dev_s *priv, struct i2c_msg_s *msg)
/* Set slave address and number of internal address bytes. */
twi_putrel(priv, SAM_TWI_MMR_OFFSET, 0);
twi_putrel(priv, SAM_TWI_MMR_OFFSET, TWI_MMR_IADRSZ_NONE | TWI_MMR_DADR(msg->addr));
twi_putrel(priv, SAM_TWI_MMR_OFFSET,
TWI_MMR_IADRSZ_NONE | TWI_MMR_DADR(msg->addr));
/* Set internal address bytes (not used) */
@@ -797,18 +832,22 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the device */
twi_takesem(&priv->exclsem);
ret = twi_takesem(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Setup the message transfer */
priv->msg = msgs;
priv->msgc = count;
/* Configure the I2C frequency.
* REVISIT: Note that the frequency is set only on the first message.
* This could be extended to support different transfer frequencies for
* each message segment.
*/
/* Configure the I2C frequency.
* REVISIT: Note that the frequency is set only on the first message.
* This could be extended to support different transfer frequencies for
* each message segment.
*/
twi_setfrequency(priv, msgs->frequency);
@@ -835,7 +874,7 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: twi_reset
*
* Description:
@@ -847,7 +886,7 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_I2C_RESET
static int twi_reset(FAR struct i2c_master_s *dev)
@@ -863,7 +902,11 @@ static int twi_reset(FAR struct i2c_master_s *dev)
/* Get exclusive access to the TWI device */
twi_takesem(&priv->exclsem);
ret = twi_takesem_uninterruptible(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Disable TWI interrupts */
@@ -1056,8 +1099,8 @@ static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
*
* Description:
* Initialize/Re-initialize the TWI peripheral. This logic performs only
* repeatable initialization after either (1) the one-time initialization, or
* (2) after each bus reset.
* repeatable initialization after either (1) the one-time initialization,
* or (2) after each bus reset.
*
****************************************************************************/
+46 -18
View File
@@ -163,12 +163,12 @@ struct i2c_attr_s
struct sam_i2c_dev_s
{
struct i2c_master_s dev; /* I2C master device */
const struct i2c_attr_s *attr; /* Invariant attributes of I2C device */
struct i2c_msg_s *msg; /* Current message being processed */
uint32_t frequency; /* I2C transfer clock frequency */
uint16_t flags; /* Transfer flags */
uint16_t nextflags; /* Next message flags */
struct i2c_master_s dev; /* I2C master device */
const struct i2c_attr_s *attr; /* Invariant attributes of I2C device */
struct i2c_msg_s *msg; /* Current message being processed */
uint32_t frequency; /* I2C transfer clock frequency */
uint16_t flags; /* Transfer flags */
uint16_t nextflags; /* Next message flags */
sem_t exclsem; /* Only one thread can access at a time */
sem_t waitsem; /* Wait for I2C transfer completion */
@@ -201,7 +201,8 @@ static uint32_t i2c_getreg32(struct sam_i2c_dev_s *priv, unsigned int offset);
static void i2c_putreg32(struct sam_i2c_dev_s *priv, uint32_t regval,
unsigned int offset);
static void i2c_takesem(sem_t * sem);
static int i2c_takesem(sem_t * sem);
static int i2c_takesem_uninterruptible(sem_t * sem);
#define i2c_givesem(sem) (nxsem_post(sem))
#ifdef CONFIG_SAM_I2C_REGDEBUG
@@ -363,7 +364,7 @@ struct i2c_ops_s g_i2cops =
};
/*******************************************************************************
* Low-level Helpers
* Private Functions
*******************************************************************************/
/*******************************************************************************
@@ -451,8 +452,7 @@ static void i2c_putreg32(struct sam_i2c_dev_s *priv, uint32_t regval,
* Name: i2c_takesem
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the receipt
* of signals).
* Take the wait semaphore. May be interrupted by a signal.
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
@@ -462,9 +462,29 @@ static void i2c_putreg32(struct sam_i2c_dev_s *priv, uint32_t regval,
*
*******************************************************************************/
static void i2c_takesem(sem_t *sem)
static int i2c_takesem(sem_t *sem)
{
nxsem_wait_uninterruptible(sem);
return nxsem_wait(sem);
}
/*******************************************************************************
* Name: i2c_takesem_uninterruptible
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the receipt
* of signals). May be interrupted by a signal.
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
*
* Returned Value:
* None
*
*******************************************************************************/
static int i2c_takesem_uninterruptible(sem_t *sem)
{
return nxsem_wait_uninterruptible(sem);
}
/*******************************************************************************
@@ -703,6 +723,7 @@ static int i2c_interrupt(int irq, FAR void *context, FAR void *arg)
i2c_wait_synchronization(priv);
/* STOP */
if ((priv->nextflags & I2C_M_NOSTART) == 0)
{
regval = i2c_getreg32(priv, SAM_I2C_CTRLB_OFFSET);
@@ -737,7 +758,6 @@ static int i2c_interrupt(int irq, FAR void *context, FAR void *arg)
/* Cancel timeout */
i2c_wakeup(priv, OK);
// i2cinfo("Got data = 0x%02X\n", msg->buffer[0]);
}
i2c_putreg8(priv, I2C_INT_SB, SAM_I2C_INTFLAG_OFFSET);
@@ -941,7 +961,7 @@ static int sam_i2c_transfer(FAR struct i2c_master_s *dev,
irqstate_t flags;
unsigned int size;
int i;
int ret = -EBUSY;
int ret;
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
@@ -970,10 +990,16 @@ static int sam_i2c_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the device */
i2c_takesem(&priv->exclsem);
ret = i2c_takesem(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Initiate the message transfer */
ret = -BUSY;
/* Initiate the transfer. The rest will be handled from interrupt logic.
* Interrupts must be disabled to prevent re-entrance from the interrupt
* level.
@@ -1040,8 +1066,6 @@ static uint32_t sam_i2c_setfrequency(struct sam_i2c_dev_s *priv,
uint32_t baud_hs = 0;
uint32_t ctrla;
// i2cinfo("sercom=%d frequency=%d\n", priv->attr->sercom, frequency);
/* Check if the configured BAUD is within the valid range */
maxfreq = (priv->attr->srcfreq >> 1);
@@ -1429,7 +1453,11 @@ int sam_i2c_reset(FAR struct i2c_master_s *dev)
/* Get exclusive access to the I2C device */
i2c_takesem(&priv->exclsem);
ret = i2c_takesem_uninterruptible(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Disable I2C interrupts */
+45 -16
View File
@@ -151,12 +151,12 @@ struct i2c_attr_s
struct sam_i2c_dev_s
{
struct i2c_master_s dev; /* I2C master device */
const struct i2c_attr_s *attr; /* Invariant attributes of I2C device */
struct i2c_msg_s *msg; /* Current message being processed */
uint32_t frequency; /* I2C transfer clock frequency */
uint16_t flags; /* Transfer flags */
uint16_t nextflags; /* Next message flags */
struct i2c_master_s dev; /* I2C master device */
const struct i2c_attr_s *attr; /* Invariant attributes of I2C device */
struct i2c_msg_s *msg; /* Current message being processed */
uint32_t frequency; /* I2C transfer clock frequency */
uint16_t flags; /* Transfer flags */
uint16_t nextflags; /* Next message flags */
sem_t exclsem; /* Only one thread can access at a time */
sem_t waitsem; /* Wait for I2C transfer completion */
@@ -189,7 +189,8 @@ static uint32_t i2c_getreg32(struct sam_i2c_dev_s *priv, unsigned int offset);
static void i2c_putreg32(struct sam_i2c_dev_s *priv, uint32_t regval,
unsigned int offset);
static void i2c_takesem(sem_t * sem);
static int i2c_takesem(sem_t * sem);
static int i2c_takesem_uninterruptible(sem_t * sem);
#define i2c_givesem(sem) (nxsem_post(sem))
#ifdef CONFIG_SAM_I2C_REGDEBUG
@@ -476,6 +477,25 @@ static void i2c_putreg32(struct sam_i2c_dev_s *priv, uint32_t regval,
* Name: i2c_takesem
*
* Description:
* Take the wait semaphore. May be interrupted by a signal.
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
*
* Returned Value:
* None
*
*******************************************************************************/
static int i2c_takesem(sem_t *sem)
{
return nxsem_wait(sem);
}
/*******************************************************************************
* Name: i2c_takesem_uninterruptible
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the receipt
* of signals).
*
@@ -487,9 +507,9 @@ static void i2c_putreg32(struct sam_i2c_dev_s *priv, uint32_t regval,
*
*******************************************************************************/
static void i2c_takesem(sem_t *sem)
static int i2c_takesem_uninterruptible(sem_t *sem)
{
nxsem_wait_uninterruptible(sem);
return nxsem_wait_uninterruptible(sem);
}
/*******************************************************************************
@@ -719,6 +739,7 @@ static int i2c_interrupt(int irq, FAR void *context, FAR void *arg)
i2c_wait_synchronization(priv);
/* STOP */
if ((priv->nextflags & I2C_M_NOSTART) == 0)
{
regval = i2c_getreg32(priv, SAM_I2C_CTRLB_OFFSET);
@@ -753,7 +774,6 @@ static int i2c_interrupt(int irq, FAR void *context, FAR void *arg)
/* Cancel timeout */
i2c_wakeup(priv, OK);
// i2cinfo("Got data = 0x%02X\n", msg->buffer[0]);
}
i2c_putreg8(priv, I2C_INT_SB, SAM_I2C_INTFLAG_OFFSET);
@@ -957,7 +977,7 @@ static int sam_i2c_transfer(FAR struct i2c_master_s *dev,
irqstate_t flags;
unsigned int size;
int i;
int ret = -EBUSY;
int ret;
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
@@ -986,10 +1006,16 @@ static int sam_i2c_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the device */
i2c_takesem(&priv->exclsem);
ret = i2c_takesem(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Initiate the message transfer */
ret = -EBUSY;
/* Initiate the transfer. The rest will be handled from interrupt logic.
* Interrupts must be disabled to prevent re-entrance from the interrupt
* level.
@@ -1052,8 +1078,6 @@ static uint32_t sam_i2c_setfrequency(struct sam_i2c_dev_s *priv,
uint32_t baud_hs = 0;
uint32_t ctrla;
// i2cinfo("sercom=%d frequency=%d\n", priv->attr->sercom, frequency);
/* Check if the configured BAUD is within the valid range */
maxfreq = (priv->attr->srcfreq >> 1);
@@ -1168,7 +1192,8 @@ static void i2c_hw_initialize(struct sam_i2c_dev_s *priv, uint32_t frequency)
regval = i2c_getreg32(priv, SAM_I2C_CTRLA_OFFSET);
if (regval & I2C_CTRLA_ENABLE)
{
i2cerr("ERROR: Cannot initialize I2C because it is already initialized!\n");
i2cerr("ERROR: Cannot initialize I2C "
"because it is already initialized!\n");
return;
}
@@ -1467,7 +1492,11 @@ int sam_i2c_reset(FAR struct i2c_master_s *dev)
/* Get exclusive access to the I2C device */
i2c_takesem(&priv->exclsem);
ret = i2c_takesem_uninterruptible(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Disable I2C interrupts */
+118 -75
View File
@@ -78,7 +78,8 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ***************************************************************/
/* Configuration ************************************************************/
#ifndef CONFIG_SAMV7_TWIHS0_FREQUENCY
# define CONFIG_SAMV7_TWIHS0_FREQUENCY 100000
@@ -96,12 +97,14 @@
# undef CONFIG_SAMV7_TWIHSHS_REGDEBUG
#endif
/* Driver internal definitions *************************************************/
/* If verbose I2C debug output is enable, then allow more time before we declare
* a timeout. The debug output from twi_interrupt will really slow things down!
/* Driver internal definitions **********************************************/
/* If verbose I2C debug output is enable, then allow more time before we
* declare a timeout. The debug output from twi_interrupt will really slow
* things down!
*
* With a very slow clock (say 100,000 Hz), less than 100 usec would be required
* to transfer on byte. So these define a "long" timeout.
* With a very slow clock (say 100,000 Hz), less than 100 usec would be
* required to transfer on byte. So these define a "long" timeout.
*/
#ifdef CONFIG_DEBUG_I2C_INFO
@@ -110,8 +113,8 @@
# define TWIHS_TIMEOUT_MSPB (5) /* 5 msec/byte */
#endif
/* Clocking to the TWIHS module(s) is provided by the main clock, divided down
* as necessary.
/* Clocking to the TWIHS module(s) is provided by the main clock, divided
* down as necessary.
* REVISIT -- This number came from the SAMA5Dx driver.
*/
@@ -128,6 +131,7 @@
/****************************************************************************
* Private Types
****************************************************************************/
/* Invariant attributes of a TWIHS bus */
struct twi_attr_s
@@ -163,10 +167,10 @@ struct twi_dev_s
/* Debug stuff */
#ifdef CONFIG_SAMV7_TWIHSHS_REGDEBUG
bool wrlast; /* Last was a write */
uint32_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
bool wrlast; /* Last was a write */
uint32_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
#endif
};
@@ -176,7 +180,8 @@ struct twi_dev_s
/* Low-level helper functions */
static void twi_takesem(sem_t *sem);
static int twi_takesem(sem_t *sem);
static int twi_takesem_uninterruptible(sem_t *sem);
#define twi_givesem(sem) (nxsem_post(sem))
#ifdef CONFIG_SAMV7_TWIHSHS_REGDEBUG
@@ -294,14 +299,14 @@ static const struct i2c_ops_s g_twiops =
};
/****************************************************************************
* Low-level Helpers
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: twi_takesem
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the receipt
* of signals).
* Take the wait semaphore. May be interrupted by a signal.
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
@@ -311,9 +316,29 @@ static const struct i2c_ops_s g_twiops =
*
****************************************************************************/
static void twi_takesem(sem_t *sem)
static int twi_takesem(sem_t *sem)
{
nxsem_wait_uninterruptible(sem);
return nxsem_wait(sem);
}
/****************************************************************************
* Name: twi_takesem_uninterruptible
*
* Description:
* Take the wait semaphore (handling false alarm wake-ups due to the
* receipt of signals).
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
*
* Returned Value:
* None
*
****************************************************************************/
static int twi_takesem_uninterruptible(sem_t *sem)
{
return nxsem_wait_uninterruptible(sem);
}
/****************************************************************************
@@ -421,7 +446,8 @@ static void twi_putabs(struct twi_dev_s *priv, uintptr_t address,
*
****************************************************************************/
static inline uint32_t twi_getrel(struct twi_dev_s *priv, unsigned int offset)
static inline uint32_t twi_getrel(struct twi_dev_s *priv,
unsigned int offset)
{
return twi_getabs(priv, priv->attr->base + offset);
}
@@ -430,8 +456,8 @@ static inline uint32_t twi_getrel(struct twi_dev_s *priv, unsigned int offset)
* Name: twi_putrel
*
* Description:
* Write a value to a TWIHS register using an offset relative to the TWIHS base
* address.
* Write a value to a TWIHS register using an offset relative to the TWIHS
* base address.
*
****************************************************************************/
@@ -459,12 +485,14 @@ static inline void twi_putrel(struct twi_dev_s *priv, unsigned int offset,
static int twi_wait(struct twi_dev_s *priv, unsigned int size)
{
uint32_t timeout;
int ret;
/* Calculate a timeout value based on the size of the transfer
*
* ticks = msec-per-byte * bytes / msec-per-tick
*
* There is no concern about arithmetic overflow for reasonable transfer sizes.
* There is no concern about arithmetic overflow for reasonable transfer
* sizes.
*/
timeout = MSEC2TICK(TWIHS_TIMEOUT_MSPB);
@@ -473,8 +501,8 @@ static int twi_wait(struct twi_dev_s *priv, unsigned int size)
timeout = 1;
}
/* Then start the timeout. This timeout is needed to avoid hangs if/when an
* TWIHS transfer stalls.
/* Then start the timeout. This timeout is needed to avoid hangs if/when
* a TWIHS transfer stalls.
*/
wd_start(priv->timeout, (timeout * size), twi_timeout, 1,
@@ -485,9 +513,15 @@ static int twi_wait(struct twi_dev_s *priv, unsigned int size)
do
{
i2cinfo("TWIHS%d Waiting...\n", priv->attr->twi);
twi_takesem(&priv->waitsem);
ret = twi_takesem(&priv->waitsem);
i2cinfo("TWIHS%d Awakened with result: %d\n",
priv->attr->twi, priv->result);
if (ret < 0)
{
wd_cancel(priv->timeout);
return ret;
}
}
while (priv->result == -EBUSY);
@@ -508,10 +542,10 @@ static int twi_wait(struct twi_dev_s *priv, unsigned int size)
* transfer has failed and should be repeated.
*/
if (priv->result == OK)
{
if (priv->result == OK)
{
priv->result = -EIO;
}
}
}
#endif
@@ -598,9 +632,9 @@ static int twi_interrupt(int irq, FAR void *context, FAR void *arg)
}
else
{
/* No.. just switch to the next message and continue receiving.
* On the next RXRDY, we will continue with the first byt of the
* next message.
/* No.. just switch to the next message and continue
* receiving. On the next RXRDY, we will continue with the
* first byte of the next message.
*/
DEBUGASSERT((next->flags & I2C_M_READ) != 0);
@@ -632,10 +666,10 @@ static int twi_interrupt(int irq, FAR void *context, FAR void *arg)
}
#ifdef CONFIG_I2C_RESET
/* If Single-Master Mode is enabled and we lost arbitration (someone else or
* an EMC-Pulse did something on the bus) something went very wrong. So we end
* the current transfer with an EUSERS. The wait function will then reset
* the bus so further communication can take place.
/* If Single-Master Mode is enabled and we lost arbitration (someone else
* or an EMC-Pulse did something on the bus) something went very wrong. So
* we end the current transfer with an EUSERS. The wait function will then
* reset the bus so further communication can take place.
*/
else if ((priv->attr->s_master) && ((pending & TWIHS_INT_ARBLST) != 0))
@@ -787,8 +821,9 @@ static void twi_startread(struct twi_dev_s *priv, struct i2c_msg_s *msg)
/* Set slave address and number of internal address bytes. */
twi_putrel(priv, SAM_TWIHS_MMR_OFFSET, 0);
twi_putrel(priv, SAM_TWIHS_MMR_OFFSET, TWIHS_MMR_IADRSZ_NONE | TWIHS_MMR_MREAD |
TWIHS_MMR_DADR(msg->addr));
twi_putrel(priv, SAM_TWIHS_MMR_OFFSET,
TWIHS_MMR_IADRSZ_NONE | TWIHS_MMR_MREAD |
TWIHS_MMR_DADR(msg->addr));
/* Set internal address bytes (not used) */
@@ -818,7 +853,8 @@ static void twi_startwrite(struct twi_dev_s *priv, struct i2c_msg_s *msg)
/* Set slave address and number of internal address bytes. */
twi_putrel(priv, SAM_TWIHS_MMR_OFFSET, 0);
twi_putrel(priv, SAM_TWIHS_MMR_OFFSET, TWIHS_MMR_IADRSZ_NONE | TWIHS_MMR_DADR(msg->addr));
twi_putrel(priv, SAM_TWIHS_MMR_OFFSET,
TWIHS_MMR_IADRSZ_NONE | TWIHS_MMR_DADR(msg->addr));
/* Set internal address bytes (not used) */
@@ -898,18 +934,22 @@ static int twi_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the device */
twi_takesem(&priv->exclsem);
ret = twi_takesem(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Setup the message transfer */
priv->msg = msgs;
priv->msgc = count;
/* Configure the I2C frequency.
* REVISIT: Note that the frequency is set only on the first message.
* This could be extended to support different transfer frequencies for
* each message segment.
*/
/* Configure the I2C frequency.
* REVISIT: Note that the frequency is set only on the first message.
* This could be extended to support different transfer frequencies for
* each message segment.
*/
twi_setfrequency(priv, msgs->frequency);
@@ -960,22 +1000,22 @@ errout:
return ret;
}
/************************************************************************************
* Name: twi_reset_internal
*
* Description:
* Perform an I2C bus reset in an attempt to break loose stuck I2C devices.
* This function can be called from inside the driver while the TWIHS device is
* already locked, so we must not handle any semaphores inside.
* To initiate a bus reset from outside the driver use twi_reset(dev).
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
************************************************************************************/
/****************************************************************************
* Name: twi_reset_internal
*
* Description:
* Perform an I2C bus reset in an attempt to break loose stuck I2C devices.
* This function can be called from inside the driver while the TWIHS
* device is already locked, so we must not handle any semaphores inside.
* To initiate a bus reset from outside the driver use twi_reset(dev).
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_I2C_RESET
static int twi_reset_internal(FAR struct i2c_master_s *dev)
@@ -1086,13 +1126,13 @@ errout:
}
#endif /* CONFIG_I2C_RESET */
/************************************************************************************
/****************************************************************************
* Name: twi_reset
*
* Description:
* Perform an I2C bus reset in an attempt to break loose stuck I2C devices.
* This function can be called from outside the driver, so lock the TWIHS Device
* and then let the internal reset function do the work.
* Perform an I2C bus reset in an attempt to break loose stuck I2C
* devices. This function can be called from outside the driver, so lock
* the TWIHS Device and then let the internal reset function do the work.
*
* Input Parameters:
* dev - Device-specific state data
@@ -1100,7 +1140,7 @@ errout:
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_I2C_RESET
static int twi_reset(FAR struct i2c_master_s *dev)
@@ -1116,15 +1156,18 @@ static int twi_reset(FAR struct i2c_master_s *dev)
/* Get exclusive access to the TWIHS device */
twi_takesem(&priv->exclsem);
ret = twi_takesem_uninterruptible(&priv->exclsem);
if (ret >= 0)
{
/* Do the reset-procedure */
/* Do the reset-procedure */
ret = twi_reset_internal(dev);
ret = twi_reset_internal(dev);
/* Release our lock on the bus */
/* Release our lock on the bus */
twi_givesem(&priv->exclsem);
}
twi_givesem(&priv->exclsem);
return ret;
}
#endif /* CONFIG_I2C_RESET */
@@ -1194,8 +1237,8 @@ static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
}
}
/* Then setup the TWIHS Clock Waveform Generator Register, using the same
* value for CLDIV and CHDIV (for 1:1 duty).
/* Then setup the TWIHS Clock Waveform Generator Register, using the
* same value for CLDIV and CHDIV (for 1:1 duty).
*/
twi_putrel(priv, SAM_TWIHS_CWGR_OFFSET, 0);
@@ -1215,9 +1258,9 @@ static void twi_setfrequency(struct twi_dev_s *priv, uint32_t frequency)
* Name: twi_hw_initialize
*
* Description:
* Initialize/Re-initialize the TWIHS peripheral. This logic performs only
* repeatable initialization after either (1) the one-time initialization, or
* (2) after each bus reset.
* Initialize/Re-initialize the TWIHS peripheral. This logic performs
* only repeatable initialization after either (1) the one-time
* initialization, or (2) after each bus reset.
*
****************************************************************************/
+63 -24
View File
@@ -100,8 +100,9 @@
#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || \
defined(CONFIG_STM32_I2C3)
/* This implementation is for the STM32 F1, F2, and F4 only */
/* Experimentally enabled for STM32L15XX */
/* This implementation is for the STM32 F1, F2, and F4 only.
* Experimentally enabled for STM32L15XX.
*/
#if defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) || \
defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F4XXX)
@@ -109,7 +110,9 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Configuration ********************************************************************/
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. Instead,
* CPU-intensive polling will be used.
*/
@@ -182,6 +185,7 @@
/************************************************************************************
* Private Types
************************************************************************************/
/* Interrupt state */
enum stm32_intstate_e
@@ -238,8 +242,14 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Referernce count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -274,12 +284,13 @@ struct stm32_i2c_priv_s
static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value);
static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t clearbits,
uint16_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv);
static inline int stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_sem_wait_uninterruptible(FAR struct stm32_i2c_priv_s *priv);
#ifdef CONFIG_STM32_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
@@ -319,8 +330,8 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
static int stm32_i2c_reset(FAR struct i2c_master_s *dev);
#endif
@@ -473,8 +484,8 @@ static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -498,13 +509,27 @@ static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline int stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
{
return nxsem_wait(&priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
static int stm32_i2c_sem_wait_uninterruptible(FAR struct stm32_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/************************************************************************************
@@ -838,7 +863,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t statu
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -879,7 +904,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -903,7 +928,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, g_trace_names[trace->event],
i + 1, trace->status, trace->count, g_trace_names[trace->event],
trace->event, trace->parm, trace->time - priv->start_time);
}
}
@@ -1193,7 +1218,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET,
(priv->flags & I2C_M_TEN) ?
0 : ((priv->msgv->addr << 1) | (priv->flags & I2C_M_READ)));
0 : ((priv->msgv->addr << 1) |
(priv->flags & I2C_M_READ)));
/* Set ACK for receive mode */
@@ -1230,7 +1256,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* Was address sent, continue with either sending or reading data */
else if ((priv->flags & I2C_M_READ) == 0 && (status & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 0)
else if ((priv->flags & I2C_M_READ) == 0 &&
(status & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 0)
{
if (priv->dcnt > 0)
{
@@ -1563,19 +1590,25 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev;
uint32_t status = 0;
#ifdef I2C1_FSMC_CONFLICT
uint32_t ahbenr;
#endif
int ret = 0;
int ret;
DEBUGASSERT(count > 0);
stm32_i2c_sem_wait(priv); /* Ensure that address or flags don't change meanwhile */
/* Ensure that address or flags don't change meanwhile */
ret = stm32_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
#ifdef I2C1_FSMC_CONFLICT
/* Disable FSMC that shares a pin with I2C1 (LBAR) */
@@ -1783,7 +1816,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -1793,7 +1826,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
stm32_i2c_sem_wait(priv);
ret = stm32_i2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
+78 -38
View File
@@ -107,8 +107,9 @@
#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || \
defined(CONFIG_STM32_I2C3)
/* This implementation is for the STM32 F1, F2, and F4 only */
/* Experimentally enabled for STM32L15XX */
/* This implementation is for the STM32 F1, F2, and F4 only.
* Experimentally enabled for STM32L15XX.
*/
#if defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) || \
defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F4XXX)
@@ -116,7 +117,9 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Configuration ********************************************************************/
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. Instead,
* CPU-intensive polling will be used.
*/
@@ -189,6 +192,7 @@
/************************************************************************************
* Private Types
************************************************************************************/
/* Interrupt state */
enum stm32_intstate_e
@@ -266,8 +270,14 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Referernce count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -281,7 +291,7 @@ struct stm32_i2c_priv_s
uint32_t frequency; /* Current I2C frequency */
int dcnt; /* Current message length */
uint16_t flags; /* Current message flags */
bool check_addr_ACK; /* Flag to signal if on next interrupt address has ACKed */
bool check_addr_ack; /* Flag to signal if on next interrupt address has ACKed */
uint8_t total_msg_len; /* Flag to signal a short read sequence */
/* I2C trace support */
@@ -304,12 +314,13 @@ struct stm32_i2c_priv_s
static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value);
static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t clearbits,
uint16_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv);
static inline int stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_sem_wait_uninterruptible(FAR struct stm32_i2c_priv_s *priv);
#ifdef CONFIG_STM32_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
@@ -349,8 +360,8 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
static int stm32_i2c_reset(FAR struct i2c_master_s *dev);
#endif
@@ -482,8 +493,8 @@ static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -507,13 +518,27 @@ static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline int stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
{
return nxsem_wait(&priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
static int stm32_i2c_sem_wait_uninterruptible(FAR struct stm32_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/************************************************************************************
@@ -847,7 +872,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint16_t statu
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -888,7 +913,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -912,7 +937,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %4d EVENT: %4d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
trace->time - priv->start_time);
}
}
@@ -1352,14 +1377,15 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET,
(priv->flags & I2C_M_TEN) ?
0 :((priv->msgv->addr << 1) | (priv->flags & I2C_M_READ)));
0 : ((priv->msgv->addr << 1) |
(priv->flags & I2C_M_READ)));
i2cinfo("Address sent. Addr=%#02x Write/Read bit=%i\n",
priv->msgv->addr, (priv->flags & I2C_M_READ));
/* Flag that address has just been sent */
priv->check_addr_ACK = true;
priv->check_addr_ack = true;
stm32_i2c_traceevent(priv, I2CEVENT_SENDADDR, priv->msgv->addr);
}
@@ -1367,7 +1393,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
{
/* TODO: untested!! */
i2cwarn("WARNING: An empty message has been detected, ignoring and passing to next message.\n");
i2cwarn("WARNING: An empty message has been detected, "
"ignoring and passing to next message.\n");
/* Trace event */
@@ -1411,7 +1438,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* Note: this commentary is found in both places.
*/
else if ((status & I2C_SR1_ADDR) == 0 && priv->check_addr_ACK)
else if ((status & I2C_SR1_ADDR) == 0 && priv->check_addr_ack)
{
i2cinfo("Invalid Address. Setting stop bit and clearing message\n");
i2cinfo("status %i\n", status);
@@ -1425,7 +1452,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* Reset flag to check for valid address */
priv->check_addr_ACK = false;
priv->check_addr_ack = false;
/* Send stop bit to clear bus */
@@ -1440,11 +1467,11 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* ACK in read mode, ACK in write mode is handled separately */
else if ((priv->flags & I2C_M_READ) != 0 && (status & I2C_SR1_ADDR) != 0 &&
priv->check_addr_ACK)
priv->check_addr_ack)
{
/* Reset check addr flag as we are handling this event */
priv->check_addr_ACK = false;
priv->check_addr_ack = false;
/* Clear ADDR flag by reading SR2 and adding it to status */
@@ -1524,7 +1551,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* Address has cleared so don't check on next call */
priv->check_addr_ACK = false;
priv->check_addr_ack = false;
/* Check if we have transmitted the whole message or we are after
* the last byte where the stop condition or else(according to the
@@ -1541,7 +1568,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_traceevent(priv, I2CEVENT_WRITE_TO_DR, priv->dcnt);
priv->dcnt--;
}
else if (priv->dcnt == 0)
{
@@ -1567,7 +1593,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
*/
else if (priv->msgc > 0 &&
(priv->msgv->flags == 0 || (priv->msgv[0].flags & I2C_M_READ) != 0))
(priv->msgv->flags == 0 ||
(priv->msgv[0].flags & I2C_M_READ) != 0))
{
stm32_i2c_sendstart(priv);
@@ -1595,9 +1622,9 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
else
{
i2cerr("ERROR: Write mode: next message has an unrecognized flag.\n");
stm32_i2c_traceevent(priv, I2CEVENT_WRITE_FLAG_ERROR, priv->msgv->flags);
stm32_i2c_traceevent(priv, I2CEVENT_WRITE_FLAG_ERROR,
priv->msgv->flags);
}
}
else
{
@@ -1659,14 +1686,17 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* Case total message length = 2 */
else if (priv->dcnt == 2 && priv->total_msg_len == 2 && !(status & I2C_SR1_BTF))
else if (priv->dcnt == 2 && priv->total_msg_len == 2 &&
!(status & I2C_SR1_BTF))
{
i2cinfo("short read N=2: DR full, SR empty. Waiting for more bytes.\n");
stm32_i2c_traceevent(priv, I2CEVENT_READ_SR_EMPTY, 0);
}
else if (priv->dcnt == 2 && priv->total_msg_len == 2 && (status & I2C_SR1_BTF))
else if (priv->dcnt == 2 && priv->total_msg_len == 2 &&
(status & I2C_SR1_BTF))
{
i2cinfo("short read N=2: DR and SR full setting stop bit and reading twice\n");
i2cinfo("short read N=2: "
"DR and SR full setting stop bit and reading twice\n");
stm32_i2c_sendstop(priv);
*priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
@@ -2011,21 +2041,25 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct stm32_i2c_priv_s *priv = (FAR struct stm32_i2c_priv_s *)dev;
uint32_t status = 0;
#ifdef I2C1_FSMC_CONFLICT
uint32_t ahbenr;
#endif
int ret = 0;
int ret;
DEBUGASSERT(dev != NULL && msgs != NULL && count > 0);
/* Ensure that address or flags don't change meanwhile */
stm32_i2c_sem_wait(priv);
ret = stm32_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
#ifdef I2C1_FSMC_CONFLICT
/* Disable FSMC that shares a pin with I2C1 (LBAR) */
@@ -2248,7 +2282,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2258,7 +2292,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
stm32_i2c_sem_wait(priv);
ret = stm32_i2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
+110 -78
View File
@@ -292,7 +292,7 @@
/* Unused bit in I2c_ISR used to communicate a bad state has occurred in
* the isr processing
*/
*/
#define I2C_INT_BAD_STATE 0x8000000
@@ -389,7 +389,10 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -437,14 +440,15 @@ struct stm32_i2c_inst_s
static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value);
static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint32_t value);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value);
static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t value);
static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static int stm32_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev);
#ifdef CONFIG_STM32_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_STM32_I2C_DYNTIMEO */
@@ -472,10 +476,10 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
#endif
@@ -666,8 +670,8 @@ static inline uint32_t stm32_i2c_getreg32(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -686,7 +690,6 @@ static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
putreg32(value, priv->config->base + offset);
}
/************************************************************************************
* Name: stm32_i2c_modifyreg32
*
@@ -706,13 +709,28 @@ static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
{
return nxsem_wait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
static int stm32_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev)
{
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
return
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
@@ -755,7 +773,8 @@ static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs)
#ifndef CONFIG_I2C_POLLED
static inline void stm32_i2c_enableinterrupts(struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0, (I2C_CR1_TXRX | I2C_CR1_NACKIE));
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0,
(I2C_CR1_TXRX | I2C_CR1_NACKIE));
}
#endif
@@ -821,6 +840,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv)
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
#endif
/* Wait until either the transfer is complete or the timeout expires */
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
@@ -912,7 +932,7 @@ static inline void
stm32_i2c_set_7bit_address(FAR struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_SADD7_MASK,
((priv->msgv->addr & 0x7F) << I2C_CR2_SADD7_SHIFT));
((priv->msgv->addr & 0x7f) << I2C_CR2_SADD7_SHIFT));
}
/************************************************************************************
@@ -982,7 +1002,6 @@ stm32_i2c_disable_reload(FAR struct stm32_i2c_priv_s *priv)
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_RELOAD, 0);
}
/************************************************************************************
* Name: stm32_i2c_sem_waitstop
*
@@ -1031,7 +1050,6 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
{
return;
}
}
/* Loop until the stop is complete or a timeout occurs. */
@@ -1140,7 +1158,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv,
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1181,7 +1199,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1205,7 +1223,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
(int)(trace->time - priv->start_time));
}
}
@@ -1278,7 +1296,6 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
if (frequency != priv->frequency)
{
/* The Speed and timing calculation are based on the following
* fI2CCLK = HSI and is 16Mhz
* Analog filter is on,
@@ -1287,39 +1304,38 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
* Mode is FastMode
*/
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
uint32_t timingr =
(presc << I2C_TIMINGR_PRESC_SHIFT) |
@@ -1593,10 +1609,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
if (status & I2C_INT_NACK)
{
if (priv->astart == true)
{
/* NACK received on first (address) byte: address is invalid */
i2cinfo("NACK: Address invalid: dcnt=%i msgc=%i status=0x%08x\n",
@@ -1658,7 +1672,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
else if ((priv->flags & (I2C_M_READ)) == 0 && (status & (I2C_ISR_TXIS)) != 0)
{
/* TXIS interrupt occurred, address valid, ready to transmit */
stm32_i2c_traceevent(priv, I2CEVENT_WRITE, 0);
@@ -1889,7 +1902,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->msgv++;
stm32_i2c_sendstart(priv);
}
else
{
@@ -1974,8 +1986,9 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->dcnt = priv->msgv->length;
priv->flags = priv->msgv->flags;
/* if this is the last message, disable reload so the
* TC event fires next time */
/* If this is the last message, disable reload so the
* TC event fires next time.
*/
if (priv->msgc == 0)
{
@@ -2101,8 +2114,9 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_traceevent(priv, I2CEVENT_ISR_SHUTDOWN, 0);
/* clear pointer to message content to reflect we are done
* with the current transaction */
/* Clear pointer to message content to reflect we are done
* with the current transaction.
*/
priv->msgv = NULL;
@@ -2271,7 +2285,8 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, int count)
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
FAR struct stm32_i2c_priv_s *priv = inst->priv;
@@ -2363,12 +2378,12 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
errval = ETIMEDOUT;
i2cerr("ERROR: Waitdone timed out CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status);
cr1, cr2, status);
}
else
{
i2cinfo("Waitdone success: CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status );
cr1, cr2, status);
}
UNUSED(cr1);
@@ -2467,7 +2482,7 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*/
clock_t start = clock_systimer();
clock_t timeout = USEC2TICK(USEC_PER_SEC/priv->frequency) + 1;
clock_t timeout = USEC2TICK(USEC_PER_SEC / priv->frequency) + 1;
status = stm32_i2c_getstatus(priv);
@@ -2500,11 +2515,20 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*
************************************************************************************/
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
return stm32_i2c_process(dev, msgs, count);
int ret;
/* Ensure that address or flags don't change meanwhile */
ret = stm32_i2c_sem_wait(dev);
if (ret >= 0)
{
ret = stm32_i2c_process(dev, msgs, count);
}
return ret;
}
/************************************************************************************
@@ -2524,7 +2548,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2538,7 +2562,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
stm32_i2c_sem_wait(dev);
ret = stm32_i2c_sem_wait_uninterruptible(dev);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
@@ -2685,6 +2715,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
case PM_STANDBY:
case PM_SLEEP:
/* Check if exclusive lock for I2C bus is held. */
if (nxsem_getvalue(&priv->sem_excl, &sval) < 0)
@@ -2703,6 +2734,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
break;
default:
/* Should not get here */
break;
@@ -2734,8 +2766,8 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
#endif
#if STM32_HSI_FREQUENCY != 8000000 || defined(INVALID_CLOCK_SOURCE)
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
#endif
/* Get I2C private structure */
@@ -2853,4 +2885,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
}
#endif /* CONFIG_STM32_I2C1 || CONFIG_STM32_I2C2 || \
CONFIG_STM32_I2C3 || CONFIG_STM32_I2C4 */
* CONFIG_STM32_I2C3 || CONFIG_STM32_I2C4 */
+117 -71
View File
@@ -100,8 +100,9 @@
#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || \
defined(CONFIG_STM32_I2C3)
/* This implementation is for the STM32 F1, F2, and F4 only */
/* Experimentally enabled for STM32L15XX */
/* This implementation is for the STM32 F1, F2, and F4 only.
* Experimentally enabled for STM32L15XX.
*/
#if defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) || \
defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F4XXX)
@@ -109,7 +110,9 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Configuration ********************************************************************/
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. Instead,
* CPU-intensive polling will be used.
*/
@@ -197,6 +200,7 @@
/************************************************************************************
* Private Types
************************************************************************************/
/* Interrupt state */
enum stm32_intstate_e
@@ -253,8 +257,14 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Referernce count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -268,7 +278,7 @@ struct stm32_i2c_priv_s
uint32_t frequency; /* Current I2C frequency */
volatile int dcnt; /* Current message length */
uint16_t flags; /* Current message flags */
bool check_addr_ACK; /* Flag to signal if on next interrupt address has ACKed */
bool check_addr_ack; /* Flag to signal if on next interrupt address has ACKed */
/* I2C trace support */
@@ -299,12 +309,13 @@ struct stm32_i2c_priv_s
static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value);
static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t clearbits,
uint16_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv);
static inline int stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_sem_wait_uninterruptible(FAR struct stm32_i2c_priv_s *priv);
#ifdef CONFIG_STM32_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
@@ -344,8 +355,8 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
static int stm32_i2c_reset(FAR struct i2c_master_s *dev);
#endif
@@ -528,8 +539,8 @@ static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -553,13 +564,28 @@ static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
static inline int stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
return nxsem_wait(&priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static int stm32_i2c_sem_wait_uninterruptible(FAR struct stm32_i2c_priv_s *priv)
{
return nxsem_wait_uninterruptible(&priv->sem_excl);
}
/************************************************************************************
@@ -786,7 +812,6 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
{
return;
}
}
/* Loop until the stop is complete or a timeout occurs. */
@@ -894,7 +919,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t statu
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -935,7 +960,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -959,7 +984,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, g_trace_names[trace->event],
i + 1, trace->status, trace->count, g_trace_names[trace->event],
trace->event, trace->parm, trace->time - priv->start_time);
}
}
@@ -1289,18 +1314,20 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
if (priv->dcnt == -1 && priv->msgc > 0)
{
/* Any new message should begin with "Start" condition
* However there were 2 situations where that was not true
* Situation 1: Next message continue transmission sequence of previous message
*
* Situation 2: If an error is injected that looks like a STOP the
* interrupt will be reentered with some status that will be incorrect. This
* will ensure that the error handler will clear the interrupt enables and
* return the error to the waiting task.
*/
/* Any new message should begin with "Start" condition
* However there were 2 situations where that was not true
* Situation 1: Next message continue transmission sequence of previous message
*
* Situation 2: If an error is injected that looks like a STOP the
* interrupt will be reentered with some status that will be incorrect. This
* will ensure that the error handler will clear the interrupt enables and
* return the error to the waiting task.
*/
if (((priv->msgv[0].flags & I2C_M_NOSTART) != 0 && (status & I2C_SR1_TXE) == 0) ||
((priv->msgv[0].flags & I2C_M_NOSTART) == 0 && (status & I2C_SR1_SB) == 0))
if (((priv->msgv[0].flags & I2C_M_NOSTART) != 0 &&
(status & I2C_SR1_TXE) == 0) ||
((priv->msgv[0].flags & I2C_M_NOSTART) == 0 &&
(status & I2C_SR1_SB) == 0))
{
#if defined(CONFIG_STM32_I2C_DMA) || defined(CONFIG_I2C_POLLED)
return OK;
@@ -1392,14 +1419,15 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET,
(priv->flags & I2C_M_TEN) ?
0 :((priv->msgv->addr << 1) | (priv->flags & I2C_M_READ)));
0 : ((priv->msgv->addr << 1) |
(priv->flags & I2C_M_READ)));
i2cinfo("Address sent. Addr=%#02x Write/Read bit=%i\n",
priv->msgv->addr, (priv->flags & I2C_M_READ));
/* Flag that address has just been sent */
priv->check_addr_ACK = true;
priv->check_addr_ack = true;
stm32_i2c_traceevent(priv, I2CEVENT_SENDADDR, priv->msgv->addr);
}
@@ -1407,7 +1435,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
{
/* TODO: untested!! */
i2cwarn(" An empty message has been detected, ignoring and passing to next message.\n");
i2cwarn(" An empty message has been detected, "
"ignoring and passing to next message.\n");
/* Trace event */
@@ -1432,7 +1461,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* received the address is valid and transmission can continue.
*/
/* Check for NACK after an address*/
/* Check for NACK after an address */
#ifndef CONFIG_I2C_POLLED
/* When polling the i2c ISR it's not possible to determine when
@@ -1453,7 +1482,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* Note: this commentary is found in both places.
*/
else if ((status & I2C_SR1_ADDR) == 0 && priv->check_addr_ACK)
else if ((status & I2C_SR1_ADDR) == 0 && priv->check_addr_ack)
{
i2cinfo("Invalid Address. Setting stop bit and clearing message\n");
i2cinfo("status %i\n", status);
@@ -1467,7 +1496,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* Reset flag to check for valid address */
priv->check_addr_ACK = false;
priv->check_addr_ack = false;
/* Send stop bit to clear bus */
@@ -1479,14 +1508,14 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
}
#endif
/* ACK in read mode, ACK in write mode is handled separately */
/* ACK in read mode, ACK in write mode is handled separately */
else if ((priv->flags & I2C_M_READ) != 0 && (status & I2C_SR1_ADDR) != 0 &&
priv->check_addr_ACK)
priv->check_addr_ack)
{
/* Reset check addr flag as we are handling this event */
priv->check_addr_ACK = false;
priv->check_addr_ack = false;
/* Note:
*
@@ -1584,13 +1613,14 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* The DMAEN bit must be set in the I2C_CR2 register before the ADDR event.
*/
stm32_dmasetup(priv->rxdma, priv->config->base+STM32_I2C_DR_OFFSET,
(uint32_t) priv->ptr, priv->dcnt,
DMA_SCR_DIR_P2M |
DMA_SCR_MSIZE_8BITS |
DMA_SCR_PSIZE_8BITS |
DMA_SCR_MINC |
I2C_DMA_PRIO);
stm32_dmasetup(priv->rxdma,
priv->config->base + STM32_I2C_DR_OFFSET,
(uint32_t)priv->ptr, priv->dcnt,
DMA_SCR_DIR_P2M |
DMA_SCR_MSIZE_8BITS |
DMA_SCR_PSIZE_8BITS |
DMA_SCR_MINC |
I2C_DMA_PRIO);
/* Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is
* used.
@@ -1702,7 +1732,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* Address has cleared so don't check on next call */
priv->check_addr_ACK = false;
priv->check_addr_ack = false;
/* Check if we have transmitted the whole message or we are after
* the last byte where the stop condition or else(according to the
@@ -1723,13 +1753,14 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* before the ADDR event.
*/
stm32_dmasetup(priv->txdma, priv->config->base+STM32_I2C_DR_OFFSET,
stm32_dmasetup(priv->txdma,
priv->config->base + STM32_I2C_DR_OFFSET,
(uint32_t) priv->ptr, priv->dcnt,
DMA_SCR_DIR_M2P |
DMA_SCR_MSIZE_8BITS |
DMA_SCR_PSIZE_8BITS |
DMA_SCR_MINC |
I2C_DMA_PRIO );
I2C_DMA_PRIO);
/* Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is
* used.
@@ -1796,12 +1827,13 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
}
#endif
if (priv->dcnt == 0 &&
priv->msgc > 0 && (priv->msgv->flags & I2C_M_NOSTART) != 0)
{
/* Set condition to get to next message */
priv->dcnt =- 1;
priv->dcnt = -1;
stm32_i2c_traceevent(priv, I2CEVENT_WRITE_NO_RESTART, priv->dcnt);
}
}
@@ -1839,7 +1871,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
(status & (I2C_SR1_RXNE | I2C_SR1_BTF)) != 0)
{
/* When read flag is set and the receive buffer is not empty
*(RXNE is set) then the driver can read from the data register.
* (RXNE is set) then the driver can read from the data register.
*/
status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
@@ -1924,7 +1956,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* device wasn't ready yet.
*/
else
else
{
#ifdef CONFIG_I2C_POLLED
stm32_i2c_traceevent(priv, I2CEVENT_POLL_DEV_NOT_RDY, 0);
@@ -2034,13 +2066,13 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg)
}
#endif
/*****************************************************************************
/************************************************************************************
* Name: stm32_i2c_dmarxcallback
*
* Description:
* Called when the RX DMA completes
*
*****************************************************************************/
************************************************************************************/
#ifdef CONFIG_STM32_I2C_DMA
static void stm32_i2c_dmarxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
@@ -2088,13 +2120,13 @@ static void stm32_i2c_dmarxcallback(DMA_HANDLE handle, uint8_t status, void *arg
}
#endif /* ifdef CONFIG_STM32_I2C_DMA */
/*****************************************************************************
/************************************************************************************
* Name: stm32_i2c_dmarxcallback
*
* Description:
* Called when the RX DMA completes
*
*****************************************************************************/
************************************************************************************/
#ifdef CONFIG_STM32_I2C_DMA
static void stm32_i2c_dmatxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
@@ -2244,21 +2276,28 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev;
uint32_t status = 0;
#ifdef I2C1_FSMC_CONFLICT
uint32_t ahbenr;
#endif
int ret = 0;
int ret;
DEBUGASSERT(count);
stm32_i2c_sem_wait(priv); /* Ensure that address or flags don't change meanwhile */
/* Ensure that address or flags don't change meanwhile */
ret = stm32_i2c_sem_wait(priv);
if (ret < 0)
{
return ret;
}
#ifdef CONFIG_STM32_I2C_DMA
/* stop DMA just in case */
/* Stop DMA just in case */
stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_DMAEN, 0);
stm32_dmastop(priv->rxdma);
@@ -2472,7 +2511,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2482,7 +2521,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
stm32_i2c_sem_wait(priv);
ret = stm32_i2c_sem_wait_uninterruptible(priv);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
@@ -2642,17 +2687,18 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
stm32_i2c_init(priv);
#ifdef CONFIG_STM32_I2C_DMA
/* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA channel.
* if the channel is not available, then stm32_dmachannel() will block and wait
* until the channel becomes available. WARNING: If you have another device sharing
* a DMA channel with SPI and the code never releases that channel, then the call
* to stm32_dmachannel() will hang forever in this function! Don't let your
* design do that!
*/
/* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA
* channel. If the channel is not available, then stm32_dmachannel() will
* block and wait until the channel becomes available. WARNING: If you
* have another device sharing a DMA channel with SPI and the code never
* releases that channel, then the call to stm32_dmachannel() will hang
* forever in this function! Don't let your design do that!
*/
priv->rxdma = stm32_dmachannel(priv->rxch);
priv->txdma = stm32_dmachannel(priv->txch);
DEBUGASSERT(priv->rxdma && priv->txdma);
#endif /* #ifdef CONFIG_STM32_I2C_DMA */
#endif /* CONFIG_STM32_I2C_DMA */
}
leave_critical_section(flags);
+115 -79
View File
@@ -163,16 +163,19 @@
* CONFIG_STM32F0L0G0_I2C3
* CONFIG_STM32F0L0G0_I2C4
*
* To configure the ISR timeout using fixed values (CONFIG_STM32F0L0G0_I2C_DYNTIMEO=n):
* To configure the ISR timeout using fixed values
* (CONFIG_STM32F0L0G0_I2C_DYNTIMEO=n):
*
* CONFIG_STM32F0L0G0_I2CTIMEOSEC (Timeout in seconds)
* CONFIG_STM32F0L0G0_I2CTIMEOMS (Timeout in milliseconds)
* CONFIG_STM32F0L0G0_I2CTIMEOTICKS (Timeout in ticks)
*
* To configure the ISR timeout using dynamic values (CONFIG_STM32F0L0G0_I2C_DYNTIMEO=y):
* To configure the ISR timeout using dynamic values
* (CONFIG_STM32F0L0G0_I2C_DYNTIMEO=y):
*
* CONFIG_STM32F0L0G0_I2C_DYNTIMEO_USECPERBYTE (Timeout in microseconds per byte)
* CONFIG_STM32F0L0G0_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in milliseconds)
* CONFIG_STM32F0L0G0_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in
* milliseconds)
*
* Debugging output enabled with:
*
@@ -292,7 +295,7 @@
/* Unused bit in I2c_ISR used to communicate a bad state has occurred in
* the isr processing
*/
*/
#define I2C_INT_BAD_STATE 0x8000000
@@ -388,8 +391,12 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
sem_t sem_isr; /* Interrupt wait semaphore */
@@ -436,14 +443,15 @@ struct stm32_i2c_inst_s
static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value);
static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint32_t value);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value);
static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t value);
static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static int stm32_i2c_sem_wait_uninterruptble(FAR struct i2c_master_s *dev);
#ifdef CONFIG_STM32F0L0G0_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_STM32F0L0G0_I2C_DYNTIMEO */
@@ -471,10 +479,10 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
#endif
@@ -661,8 +669,8 @@ static inline uint32_t stm32_i2c_getreg32(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -681,7 +689,6 @@ static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
putreg32(value, priv->config->base + offset);
}
/************************************************************************************
* Name: stm32_i2c_modifyreg32
*
@@ -701,13 +708,28 @@ static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
{
return nxsem_wait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptble
*
* Description:
* Take the exclusive access, waiting as necessary
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
static int stm32_i2c_sem_wait_uninterruptble(FAR struct i2c_master_s *dev)
{
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
return
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
@@ -750,7 +772,8 @@ static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs)
#ifndef CONFIG_I2C_POLLED
static inline void stm32_i2c_enableinterrupts(struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0, (I2C_CR1_TXRX | I2C_CR1_NACKIE));
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0,
(I2C_CR1_TXRX | I2C_CR1_NACKIE));
}
#endif
@@ -816,6 +839,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv)
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
#endif
/* Wait until either the transfer is complete or the timeout expires */
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
@@ -907,7 +931,7 @@ static inline void
stm32_i2c_set_7bit_address(FAR struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_SADD7_MASK,
((priv->msgv->addr & 0x7F) << I2C_CR2_SADD7_SHIFT));
((priv->msgv->addr & 0x7f) << I2C_CR2_SADD7_SHIFT));
}
/************************************************************************************
@@ -977,7 +1001,6 @@ stm32_i2c_disable_reload(FAR struct stm32_i2c_priv_s *priv)
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_RELOAD, 0);
}
/************************************************************************************
* Name: stm32_i2c_sem_waitstop
*
@@ -1026,7 +1049,6 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
{
return;
}
}
/* Loop until the stop is complete or a timeout occurs. */
@@ -1135,7 +1157,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv,
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1176,7 +1198,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1200,7 +1222,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
(int)(trace->time - priv->start_time));
}
}
@@ -1273,7 +1295,6 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
if (frequency != priv->frequency)
{
/* The Speed and timing calculation are based on the following
* fI2CCLK = HSI and is 16Mhz
* Analog filter is on,
@@ -1282,39 +1303,38 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
* Mode is FastMode
*/
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
uint32_t timingr =
(presc << I2C_TIMINGR_PRESC_SHIFT) |
@@ -1588,10 +1608,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
if (status & I2C_INT_NACK)
{
if (priv->astart == true)
{
/* NACK received on first (address) byte: address is invalid */
i2cinfo("NACK: Address invalid: dcnt=%i msgc=%i status=0x%08x\n",
@@ -1653,7 +1671,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
else if ((priv->flags & (I2C_M_READ)) == 0 && (status & (I2C_ISR_TXIS)) != 0)
{
/* TXIS interrupt occurred, address valid, ready to transmit */
stm32_i2c_traceevent(priv, I2CEVENT_WRITE, 0);
@@ -1884,7 +1901,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->msgv++;
stm32_i2c_sendstart(priv);
}
else
{
@@ -1970,7 +1986,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->flags = priv->msgv->flags;
/* if this is the last message, disable reload so the
* TC event fires next time */
* TC event fires next time.
*/
if (priv->msgc == 0)
{
@@ -2097,7 +2114,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_traceevent(priv, I2CEVENT_ISR_SHUTDOWN, 0);
/* clear pointer to message content to reflect we are done
* with the current transaction */
* with the current transaction.
*/
priv->msgv = NULL;
@@ -2262,7 +2280,8 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, int count)
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
FAR struct stm32_i2c_priv_s *priv = inst->priv;
@@ -2354,12 +2373,12 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
errval = ETIMEDOUT;
i2cerr("ERROR: Waitdone timed out CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status);
cr1, cr2, status);
}
else
{
i2cinfo("Waitdone success: CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status );
cr1, cr2, status);
}
UNUSED(cr1);
@@ -2458,7 +2477,7 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*/
clock_t start = clock_systimer();
clock_t timeout = USEC2TICK(USEC_PER_SEC/priv->frequency) + 1;
clock_t timeout = USEC2TICK(USEC_PER_SEC / priv->frequency) + 1;
status = stm32_i2c_getstatus(priv);
@@ -2491,11 +2510,20 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*
************************************************************************************/
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
return stm32_i2c_process(dev, msgs, count);
int ret;
/* Ensure that address or flags don't change meanwhile */
ret = stm32_i2c_sem_wait(dev);
if (ret >= 0)
{
ret = stm32_i2c_process(dev, msgs, count);
}
return ret;
}
/************************************************************************************
@@ -2515,7 +2543,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2529,7 +2557,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
stm32_i2c_sem_wait(dev);
ret = stm32_i2c_sem_wait_uninterruptble(dev);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
@@ -2676,6 +2710,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
case PM_STANDBY:
case PM_SLEEP:
/* Check if exclusive lock for I2C bus is held. */
if (nxsem_getvalue(&priv->sem_excl, &sval) < 0)
@@ -2694,6 +2729,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
break;
default:
/* Should not get here */
break;
@@ -2726,8 +2762,8 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
#if 0 /* REVISIT: this is not true for all STM32 M0 */
#if STM32_HSI_FREQUENCY != 8000000 || defined(INVALID_CLOCK_SOURCE)
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
#endif
#endif
@@ -2846,4 +2882,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
}
#endif /* CONFIG_STM32F0L0G0_I2C1 || CONFIG_STM32F0L0G0_I2C2 || \
CONFIG_STM32F0L0G0_I2C3 || CONFIG_STM32F0L0G0_I2C4 */
* CONFIG_STM32F0L0G0_I2C3 || CONFIG_STM32F0L0G0_I2C4 */
+114 -79
View File
@@ -181,10 +181,12 @@
* CONFIG_STM32F7_I2CTIMEOMS (Timeout in milliseconds)
* CONFIG_STM32F7_I2CTIMEOTICKS (Timeout in ticks)
*
* To configure the ISR timeout using dynamic values (CONFIG_STM32F7_I2C_DYNTIMEO=y):
* To configure the ISR timeout using dynamic values
* (CONFIG_STM32F7_I2C_DYNTIMEO=y):
*
* CONFIG_STM32F7_I2C_DYNTIMEO_USECPERBYTE (Timeout in microseconds per byte)
* CONFIG_STM32F7_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in milliseconds)
* CONFIG_STM32F7_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in
* milliseconds)
*
* Debugging output enabled with:
*
@@ -328,7 +330,7 @@
/* Unused bit in I2c_ISR used to communicate a bad state has occurred in
* the isr processing
*/
*/
#define I2C_INT_BAD_STATE 0x8000000
@@ -425,7 +427,10 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -473,14 +478,15 @@ struct stm32_i2c_inst_s
static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value);
static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint32_t value);
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value);
static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t value);
static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static int stm32_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev);
#ifdef CONFIG_STM32F7_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_STM32F7_I2C_DYNTIMEO */
@@ -508,10 +514,10 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
#endif
@@ -702,8 +708,8 @@ static inline uint32_t stm32_i2c_getreg32(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -722,7 +728,6 @@ static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
putreg32(value, priv->config->base + offset);
}
/************************************************************************************
* Name: stm32_i2c_modifyreg32
*
@@ -742,13 +747,29 @@ static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
{
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
return nxsem_wait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static int stm32_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev)
{
return
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
@@ -791,7 +812,8 @@ static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs)
#ifndef CONFIG_I2C_POLLED
static inline void stm32_i2c_enableinterrupts(struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0, (I2C_CR1_TXRX | I2C_CR1_NACKIE));
stm32_i2c_modifyreg32(priv, STM32_I2C_CR1_OFFSET, 0,
(I2C_CR1_TXRX | I2C_CR1_NACKIE));
}
#endif
@@ -857,6 +879,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv)
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
#endif
/* Wait until either the transfer is complete or the timeout expires */
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
@@ -948,7 +971,7 @@ static inline void
stm32_i2c_set_7bit_address(FAR struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_SADD7_MASK,
((priv->msgv->addr & 0x7F) << I2C_CR2_SADD7_SHIFT));
((priv->msgv->addr & 0x7f) << I2C_CR2_SADD7_SHIFT));
}
/************************************************************************************
@@ -1018,7 +1041,6 @@ stm32_i2c_disable_reload(FAR struct stm32_i2c_priv_s *priv)
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_RELOAD, 0);
}
/************************************************************************************
* Name: stm32_i2c_sem_waitstop
*
@@ -1067,7 +1089,6 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
{
return;
}
}
/* Loop until the stop is complete or a timeout occurs. */
@@ -1176,7 +1197,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv,
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1217,7 +1238,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1241,7 +1262,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
(int)(trace->time - priv->start_time));
}
}
@@ -1314,7 +1335,6 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
if (frequency != priv->frequency)
{
/* The Speed and timing calculation are based on the following
* fI2CCLK = HSI and is 16Mhz
* Analog filter is on,
@@ -1323,39 +1343,38 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
* Mode is FastMode
*/
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
uint32_t timingr =
(presc << I2C_TIMINGR_PRESC_SHIFT) |
@@ -1629,10 +1648,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
if (status & I2C_INT_NACK)
{
if (priv->astart == true)
{
/* NACK received on first (address) byte: address is invalid */
i2cinfo("NACK: Address invalid: dcnt=%i msgc=%i status=0x%08x\n",
@@ -1694,7 +1711,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
else if ((priv->flags & (I2C_M_READ)) == 0 && (status & (I2C_ISR_TXIS)) != 0)
{
/* TXIS interrupt occurred, address valid, ready to transmit */
stm32_i2c_traceevent(priv, I2CEVENT_WRITE, 0);
@@ -1925,7 +1941,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->msgv++;
stm32_i2c_sendstart(priv);
}
else
{
@@ -2011,7 +2026,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->flags = priv->msgv->flags;
/* if this is the last message, disable reload so the
* TC event fires next time */
* TC event fires next time.
*/
if (priv->msgc == 0)
{
@@ -2138,7 +2154,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_traceevent(priv, I2CEVENT_ISR_SHUTDOWN, 0);
/* clear pointer to message content to reflect we are done
* with the current transaction */
* with the current transaction.
*/
priv->msgv = NULL;
@@ -2307,7 +2324,8 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, int count)
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
FAR struct stm32_i2c_priv_s *priv = inst->priv;
@@ -2399,12 +2417,12 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
errval = ETIMEDOUT;
i2cerr("ERROR: Waitdone timed out CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status);
cr1, cr2, status);
}
else
{
i2cinfo("Waitdone success: CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status );
cr1, cr2, status);
}
UNUSED(cr1);
@@ -2503,7 +2521,7 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*/
clock_t start = clock_systimer();
clock_t timeout = USEC2TICK(USEC_PER_SEC/priv->frequency) + 1;
clock_t timeout = USEC2TICK(USEC_PER_SEC / priv->frequency) + 1;
status = stm32_i2c_getstatus(priv);
@@ -2536,11 +2554,20 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*
************************************************************************************/
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
return stm32_i2c_process(dev, msgs, count);
int ret;
/* Ensure that address or flags don't change meanwhile */
ret = stm32_i2c_sem_wait(dev);
if (ret >= 0)
{
ret = stm32_i2c_process(dev, msgs, count);
}
return ret;
}
/************************************************************************************
@@ -2560,7 +2587,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2574,7 +2601,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
stm32_i2c_sem_wait(dev);
ret = stm32_i2c_sem_wait_uninterruptible(dev);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
@@ -2721,6 +2754,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
case PM_STANDBY:
case PM_SLEEP:
/* Check if exclusive lock for I2C bus is held. */
if (nxsem_getvalue(&priv->sem_excl, &sval) < 0)
@@ -2739,6 +2773,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
break;
default:
/* Should not get here */
break;
@@ -2770,8 +2805,8 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
#endif
#if STM32_HSI_FREQUENCY != 16000000 || defined(INVALID_CLOCK_SOURCE)
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
#endif
/* Get I2C private structure */
@@ -2889,4 +2924,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
}
#endif /* CONFIG_STM32F7_I2C1 || CONFIG_STM32F7_I2C2 || \
CONFIG_STM32F7_I2C3 || CONFIG_STM32F7_I2C4 */
* CONFIG_STM32F7_I2C3 || CONFIG_STM32F7_I2C4 */
+93 -61
View File
@@ -178,7 +178,8 @@
* CONFIG_STM32H7_I2CTIMEOMS (Timeout in milliseconds)
* CONFIG_STM32H7_I2CTIMEOTICKS (Timeout in ticks)
*
* To configure the ISR timeout using dynamic values (CONFIG_STM32H7_I2C_DYNTIMEO=y):
* To configure the ISR timeout using dynamic values
* (CONFIG_STM32H7_I2C_DYNTIMEO=y):
*
* CONFIG_STM32H7_I2C_DYNTIMEO_USECPERBYTE (Timeout in microseconds per byte)
* CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in msec)
@@ -379,7 +380,10 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct stm32_i2c_config_s *config; /* Port configuration */
/* Port configuration */
const struct stm32_i2c_config_s *config;
int refs; /* Referernce count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -434,7 +438,8 @@ static inline void stm32_i2c_putreg32(FAR struct stm32_i2c_priv_s *priv,
static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev);
static int stm32_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev);
#ifdef CONFIG_STM32H7_I2C_DYNTIMEO
static useconds_t stm32_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_STM32H7_I2C_DYNTIMEO */
@@ -462,8 +467,8 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg);
static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv);
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
@@ -656,8 +661,8 @@ static inline uint32_t stm32_i2c_getreg32(FAR struct stm32_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -695,13 +700,29 @@ static inline void stm32_i2c_modifyreg32(FAR struct stm32_i2c_priv_s *priv,
* Name: stm32_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline void stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
static inline int stm32_i2c_sem_wait(FAR struct i2c_master_s *dev)
{
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
return nxsem_wait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
* Name: stm32_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static int stm32_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev)
{
return
nxsem_wait_uninterruptible(&((struct stm32_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
@@ -811,6 +832,7 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv)
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
#endif
/* Wait until either the transfer is complete or the timeout expires */
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
@@ -902,7 +924,7 @@ static inline void
stm32_i2c_set_7bit_address(FAR struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg32(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_SADD7_MASK,
((priv->msgv->addr & 0x7F) << I2C_CR2_SADD7_SHIFT));
((priv->msgv->addr & 0x7f) << I2C_CR2_SADD7_SHIFT));
}
/************************************************************************************
@@ -1020,7 +1042,6 @@ static inline void stm32_i2c_sem_waitstop(FAR struct stm32_i2c_priv_s *priv)
{
return;
}
}
/* Loop until the stop is complete or a timeout occurs. */
@@ -1129,7 +1150,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv,
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1170,7 +1191,7 @@ static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1194,7 +1215,7 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
trace->time - priv->start_time);
}
}
@@ -1278,39 +1299,38 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
* Mode is FastMode
*/
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
if (frequency == 100000)
{
presc = 0;
scl_delay = 5;
sda_delay = 0;
scl_h_period = 61;
scl_l_period = 89;
}
else if (frequency == 400000)
{
presc = 0;
scl_delay = 3;
sda_delay = 0;
scl_h_period = 6;
scl_l_period = 24;
}
else if (frequency == 1000000)
{
presc = 0;
scl_delay = 2;
sda_delay = 0;
scl_h_period = 1;
scl_l_period = 5;
}
else
{
presc = 7;
scl_delay = 0;
sda_delay = 0;
scl_h_period = 35;
scl_l_period = 162;
}
uint32_t timingr =
(presc << I2C_TIMINGR_PRESC_SHIFT) |
@@ -1586,10 +1606,8 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
if (status & I2C_INT_NACK)
{
if (priv->astart == true)
{
/* NACK received on first (address) byte: address is invalid */
i2cinfo("NACK: Address invalid: dcnt=%i msgc=%i status=0x%08x\n",
@@ -1651,7 +1669,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
else if ((priv->flags & (I2C_M_READ)) == 0 && (status & (I2C_ISR_TXIS)) != 0)
{
/* TXIS interrupt occurred, address valid, ready to transmit */
stm32_i2c_traceevent(priv, I2CEVENT_WRITE, 0);
@@ -1877,7 +1894,6 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->msgv++;
stm32_i2c_sendstart(priv);
}
else
{
@@ -2253,8 +2269,8 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
*
************************************************************************************/
static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32_i2c_process(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
FAR struct stm32_i2c_priv_s *priv = inst->priv;
@@ -2450,7 +2466,7 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
*/
uint32_t start = clock_systimer();
uint32_t timeout = USEC2TICK(USEC_PER_SEC/priv->frequency) + 1;
uint32_t timeout = USEC2TICK(USEC_PER_SEC / priv->frequency) + 1;
status = stm32_i2c_getstatus(priv);
@@ -2486,8 +2502,17 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
static int stm32_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
return stm32_i2c_process(dev, msgs, count);
int ret;
/* Ensure that address or flags don't change meanwhile */
ret = stm32_i2c_sem_wait(dev);
if (ret >= 0)
{
ret = stm32_i2c_process(dev, msgs, count);
}
return ret;
}
/************************************************************************************
@@ -2507,7 +2532,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2521,7 +2546,13 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
stm32_i2c_sem_wait(dev);
ret = stm32_i2c_sem_wait_uninterruptible(dev);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
@@ -2668,6 +2699,7 @@ static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
case PM_STANDBY:
case PM_SLEEP:
/* Check if exclusive lock for I2C bus is held. */
if (nxsem_getvalue(&priv->sem_excl, &sval) < 0)
@@ -2713,7 +2745,7 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
#if STM32_HSI_FREQUENCY != 16000000 || defined(INVALID_CLOCK_SOURCE)
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
return NULL;
return NULL;
#endif
/* Get I2C private structure */
@@ -2831,4 +2863,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
}
#endif /* CONFIG_STM32H7_I2C1 || CONFIG_STM32H7_I2C2 || \
CONFIG_STM32H7_I2C3 || CONFIG_STM32H7_I2C4 */
* CONFIG_STM32H7_I2C3 || CONFIG_STM32H7_I2C4 */
+80 -44
View File
@@ -201,10 +201,12 @@
* CONFIG_STM32L4_I2CTIMEOMS (Timeout in milliseconds)
* CONFIG_STM32L4_I2CTIMEOTICKS (Timeout in ticks)
*
* To configure the ISR timeout using dynamic values (CONFIG_STM32L4_I2C_DYNTIMEO=y):
* To configure the ISR timeout using dynamic values
* (CONFIG_STM32L4_I2C_DYNTIMEO=y):
*
* CONFIG_STM32L4_I2C_DYNTIMEO_USECPERBYTE (Timeout in microseconds per byte)
* CONFIG_STM32L4_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in milliseconds)
* CONFIG_STM32L4_I2C_DYNTIMEO_STARTSTOP (Timeout for start/stop in
* milliseconds)
*
* Debugging output enabled with:
*
@@ -418,7 +420,10 @@ struct stm32l4_i2c_config_s
struct stm32l4_i2c_priv_s
{
const struct stm32l4_i2c_config_s *config; /* Port configuration */
/* Port configuration */
const struct stm32l4_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
@@ -473,7 +478,8 @@ static inline void stm32l4_i2c_putreg32(FAR struct stm32l4_i2c_priv_s *priv,
static inline void stm32l4_i2c_modifyreg32(FAR struct stm32l4_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void stm32l4_i2c_sem_wait(FAR struct i2c_master_s *dev);
static inline int stm32l4_i2c_sem_wait(FAR struct i2c_master_s *dev);
static int stm32l4_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev);
#ifdef CONFIG_STM32L4_I2C_DYNTIMEO
static useconds_t stm32l4_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
#endif /* CONFIG_STM32L4_I2C_DYNTIMEO */
@@ -696,8 +702,8 @@ static inline uint32_t stm32l4_i2c_getreg32(FAR struct stm32l4_i2c_priv_s *priv,
*
************************************************************************************/
static inline void stm32l4_i2c_putreg(FAR struct stm32l4_i2c_priv_s *priv, uint8_t offset,
uint16_t value)
static inline void stm32l4_i2c_putreg(FAR struct stm32l4_i2c_priv_s *priv,
uint8_t offset, uint16_t value)
{
putreg16(value, priv->config->base + offset);
}
@@ -716,7 +722,6 @@ static inline void stm32l4_i2c_putreg32(FAR struct stm32l4_i2c_priv_s *priv,
putreg32(value, priv->config->base + offset);
}
/************************************************************************************
* Name: stm32l4_i2c_modifyreg32
*
@@ -736,13 +741,28 @@ static inline void stm32l4_i2c_modifyreg32(FAR struct stm32l4_i2c_priv_s *priv,
* Name: stm32l4_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary. May be interrupted by a
* signal.
*
************************************************************************************/
static inline int stm32l4_i2c_sem_wait(FAR struct i2c_master_s *dev)
{
return nxsem_wait(&((struct stm32l4_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
* Name: stm32l4_i2c_sem_wait_uninterruptible
*
* Description:
* Take the exclusive access, waiting as necessary
*
************************************************************************************/
static inline void stm32l4_i2c_sem_wait(FAR struct i2c_master_s *dev)
static int stm32l4_i2c_sem_wait_uninterruptible(FAR struct i2c_master_s *dev)
{
nxsem_wait_uninterruptible(&((struct stm32l4_i2c_inst_s *)dev)->priv->sem_excl);
return
nxsem_wait_uninterruptible(&((struct stm32l4_i2c_inst_s *)dev)->priv->sem_excl);
}
/************************************************************************************
@@ -852,6 +872,7 @@ static inline int stm32l4_i2c_sem_waitdone(FAR struct stm32l4_i2c_priv_s *priv)
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
#endif
/* Wait until either the transfer is complete or the timeout expires */
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
@@ -943,7 +964,7 @@ static inline void
stm32l4_i2c_set_7bit_address(FAR struct stm32l4_i2c_priv_s *priv)
{
stm32l4_i2c_modifyreg32(priv, STM32L4_I2C_CR2_OFFSET, I2C_CR2_SADD7_MASK,
((priv->msgv->addr & 0x7F) << I2C_CR2_SADD7_SHIFT));
((priv->msgv->addr & 0x7f) << I2C_CR2_SADD7_SHIFT));
}
/************************************************************************************
@@ -1013,7 +1034,6 @@ stm32l4_i2c_disable_reload(FAR struct stm32l4_i2c_priv_s *priv)
stm32l4_i2c_modifyreg32(priv, STM32L4_I2C_CR2_OFFSET, I2C_CR2_RELOAD, 0);
}
/************************************************************************************
* Name: stm32l4_i2c_sem_waitstop
*
@@ -1062,7 +1082,6 @@ static inline void stm32l4_i2c_sem_waitstop(FAR struct stm32l4_i2c_priv_s *priv)
{
return;
}
}
/* Loop until the stop is complete or a timeout occurs. */
@@ -1107,7 +1126,8 @@ static inline void stm32l4_i2c_sem_init(FAR struct i2c_master_s *dev)
*/
nxsem_init(&((struct stm32l4_i2c_inst_s *)dev)->priv->sem_isr, 0, 0);
nxsem_setprotocol(&((struct stm32l4_i2c_inst_s *)dev)->priv->sem_isr, SEM_PRIO_NONE);
nxsem_setprotocol(&((struct stm32l4_i2c_inst_s *)dev)->priv->sem_isr,
SEM_PRIO_NONE);
#endif
}
@@ -1171,7 +1191,7 @@ static void stm32l4_i2c_tracenew(FAR struct stm32l4_i2c_priv_s *priv,
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1212,7 +1232,7 @@ static void stm32l4_i2c_traceevent(FAR struct stm32l4_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: Trace table overflow\n");
return;
@@ -1236,7 +1256,7 @@ static void stm32l4_i2c_tracedump(FAR struct stm32l4_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
(int)(trace->time - priv->start_time));
}
}
@@ -1347,7 +1367,7 @@ static void stm32l4_i2c_setclock(FAR struct stm32l4_i2c_priv_s *priv,
scl_delay = 0x0d; /* SCLDEL - (+1) data setup time from SDA edge to SCL rising edge */
}
else if (frequency == 400000)
{
{
/* 400 KHz values from I2C timing tool for clock of 80 MHz */
presc = 0x01; /* PRESC - (+1) prescale I2CCLK */
@@ -1355,9 +1375,9 @@ static void stm32l4_i2c_setclock(FAR struct stm32l4_i2c_priv_s *priv,
scl_h_period = 0x13; /* SCLH - SCL high period in master mode */
sda_delay = 0x00; /* SDADEL - (+1) data hold time after SCL falling edge */
scl_delay = 0x07; /* SCLDEL - (+1) data setup time from SDA edge to SCL rising edge */
}
}
else if (frequency == 1000000)
{
{
/* 1000 KHz values from I2C timing tool for clock of 80 MHz */
presc = 0x01; /* PRESC - (+1) prescale I2CCLK */
@@ -1365,7 +1385,7 @@ static void stm32l4_i2c_setclock(FAR struct stm32l4_i2c_priv_s *priv,
scl_h_period = 0x13; /* SCLH - SCL high period in master mode */
sda_delay = 0x00; /* SDADEL - (+1) data hold time after SCL falling edge */
scl_delay = 0x05; /* SCLDEL - (+1) data setup time from SDA edge to SCL rising edge */
}
}
else
{
/* 10 KHz values from I2C timing tool with clock 80 MHz */
@@ -1398,17 +1418,17 @@ static void stm32l4_i2c_setclock(FAR struct stm32l4_i2c_priv_s *priv,
scl_l_period = 230;
}
else if (frequency == 400000)
{
{
/* 400 KHz values from I2C timing tool for clock of 120 MHz */
presc = 2;
scl_delay = 8;
sda_delay = 0;
scl_h_period = 21;
scl_l_period = 66;
}
presc = 2;
scl_delay = 8;
sda_delay = 0;
scl_h_period = 21;
scl_l_period = 66;
}
else if (frequency == 1000000)
{
{
/* 1000 KHz values from I2C timing tool for clock of 120 MHz */
presc = 2;
@@ -1416,7 +1436,7 @@ static void stm32l4_i2c_setclock(FAR struct stm32l4_i2c_priv_s *priv,
sda_delay = 0;
scl_h_period = 7;
scl_l_period = 20;
}
}
else
{
/* 10 KHz values not supported */
@@ -1746,10 +1766,8 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
if (status & I2C_INT_NACK)
{
if (priv->astart == true)
{
/* NACK received on first (address) byte: address is invalid */
i2cinfo("NACK: Address invalid: dcnt=%i msgc=%i status=0x%08x\n",
@@ -1811,7 +1829,6 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
else if ((priv->flags & (I2C_M_READ)) == 0 && (status & (I2C_ISR_TXIS)) != 0)
{
/* TXIS interrupt occurred, address valid, ready to transmit */
stm32l4_i2c_traceevent(priv, I2CEVENT_WRITE, 0);
@@ -2037,7 +2054,6 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
priv->msgv++;
stm32l4_i2c_sendstart(priv);
}
else
{
@@ -2123,7 +2139,8 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
priv->flags = priv->msgv->flags;
/* if this is the last message, disable reload so the
* TC event fires next time */
* TC event fires next time.
*/
if (priv->msgc == 0)
{
@@ -2249,7 +2266,8 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
stm32l4_i2c_traceevent(priv, I2CEVENT_ISR_SHUTDOWN, 0);
/* clear pointer to message content to reflect we are done
* with the current transaction */
* with the current transaction.
*/
priv->msgv = NULL;
@@ -2524,12 +2542,12 @@ static int stm32l4_i2c_process(FAR struct i2c_master_s *dev,
errval = ETIMEDOUT;
i2cerr("ERROR: Waitdone timed out CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status);
cr1, cr2, status);
}
else
{
i2cinfo("Waitdone success: CR1: 0x%08x CR2: 0x%08x status: 0x%08x\n",
cr1, cr2,status );
cr1, cr2, status);
}
UNUSED(cr1);
@@ -2628,7 +2646,7 @@ static int stm32l4_i2c_process(FAR struct i2c_master_s *dev,
*/
clock_t start = clock_systimer();
clock_t timeout = USEC2TICK(USEC_PER_SEC/priv->frequency) + 1;
clock_t timeout = USEC2TICK(USEC_PER_SEC / priv->frequency) + 1;
status = stm32l4_i2c_getstatus(priv);
@@ -2661,11 +2679,21 @@ static int stm32l4_i2c_process(FAR struct i2c_master_s *dev,
*
************************************************************************************/
static int stm32l4_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count)
static int stm32l4_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs,
int count)
{
stm32l4_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
return stm32l4_i2c_process(dev, msgs, count);
int ret;
/* Ensure that address or flags don't change meanwhile */
ret = stm32l4_i2c_sem_wait(dev);
if (ret >= 0)
{
ret = stm32l4_i2c_process(dev, msgs, count);
}
return ret;
}
/************************************************************************************
@@ -2685,7 +2713,7 @@ static int stm32l4_i2c_reset(FAR struct i2c_master_s * dev)
uint32_t scl_gpio;
uint32_t sda_gpio;
uint32_t frequency;
int ret = ERROR;
int ret;
DEBUGASSERT(dev);
@@ -2699,7 +2727,13 @@ static int stm32l4_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
stm32l4_i2c_sem_wait(dev);
ret = stm32l4_i2c_sem_wait_uninterruptible(dev);
if (ret < 0)
{
return ret;
}
ret = -EIO;
/* Save the current frequency */
@@ -2843,6 +2877,7 @@ static int stm32l4_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
case PM_STANDBY:
case PM_SLEEP:
/* Check if exclusive lock for I2C bus is held. */
if (nxsem_getvalue(&priv->sem_excl, &sval) < 0)
@@ -2861,6 +2896,7 @@ static int stm32l4_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
break;
default:
/* Should not get here */
break;
+29 -26
View File
@@ -82,7 +82,9 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Configuration ********************************************************************/
/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used. Instead,
* CPU-intensive polling will be used.
*/
@@ -110,6 +112,7 @@
#endif
/* GPIO pins ************************************************************************/
/* Macros to convert a I2C pin to a GPIO output */
#define I2C_INPUT (GPIO_FUNC_INPUT)
@@ -143,6 +146,7 @@
/************************************************************************************
* Private Types
************************************************************************************/
/* Interrupt state */
enum tiva_intstate_e
@@ -203,8 +207,13 @@ struct tiva_i2c_config_s
struct tiva_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct tiva_i2c_config_s *config; /* Port configuration */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct tiva_i2c_config_s *config;
sem_t exclsem; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
sem_t waitsem; /* Interrupt wait semaphore */
@@ -223,10 +232,10 @@ struct tiva_i2c_priv_s
#ifdef CONFIG_TIVA_I2C_REGDEBUG
/* Register level debug */
bool wrlast; /* Last was a write */
uintptr_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
bool wrlast; /* Last was a write */
uintptr_t addrlast; /* Last address */
uint32_t vallast; /* Last value */
int ntimes; /* Number of times */
#endif
#ifdef CONFIG_I2C_TRACE
@@ -259,7 +268,6 @@ static inline uint32_t tiva_i2c_getreg(struct tiva_i2c_priv_s *priv,
static inline void tiva_i2c_putreg(struct tiva_i2c_priv_s *priv,
unsigned int offset, uint32_t value);
#endif
static inline void tiva_i2c_sem_wait(struct tiva_i2c_priv_s *priv);
#ifdef CONFIG_TIVA_I2C_DYNTIMEO
static useconds_t tiva_i2c_tousecs(int msgc, struct i2c_msg_s *msgv);
@@ -635,19 +643,6 @@ static inline void tiva_i2c_putreg(struct tiva_i2c_priv_s *priv,
}
#endif
/************************************************************************************
* Name: tiva_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
*
************************************************************************************/
static inline void tiva_i2c_sem_wait(struct tiva_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->exclsem);
}
/************************************************************************************
* Name: tiva_i2c_tousecs
*
@@ -919,7 +914,7 @@ static void tiva_i2c_tracenew(struct tiva_i2c_priv_s *priv, uint32_t status)
{
/* Yes.. bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: I2C%d trace table overflow\n", priv->config->devno);
return;
@@ -968,7 +963,7 @@ static void tiva_i2c_traceevent(struct tiva_i2c_priv_s *priv,
/* Bump up the trace index (unless we are out of trace entries) */
if (priv->tndx >= (CONFIG_I2C_NTRACE-1))
if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
{
i2cerr("ERROR: I2C%d trace table overflow\n", priv->config->devno);
return;
@@ -1003,7 +998,7 @@ static void tiva_i2c_tracedump(struct tiva_i2c_priv_s *priv)
trace = &priv->trace[i];
syslog(LOG_DEBUG,
"%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
i + 1, trace->status, trace->count, trace->event, trace->parm,
trace->time - priv->ttime);
}
}
@@ -1602,12 +1597,16 @@ static int tiva_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgv,
{
struct tiva_i2c_priv_s *priv = (struct tiva_i2c_priv_s *)dev;
uint32_t regval;
int ret = OK;
int ret;
DEBUGASSERT(priv && priv->config && msgv && msgc > 0);
i2cinfo("I2C%d: msgc=%d\n", priv->config->devno, msgc);
tiva_i2c_sem_wait(priv); /* Ensure that address or flags don't change meanwhile */
ret = nxsem_wait(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Reset mptr and mcnt to ensure an unexpected data interrupt doesn't
* overwrite stale data.
@@ -1764,7 +1763,11 @@ static int tiva_i2c_reset(FAR struct i2c_master_s * dev)
/* Lock out other clients */
tiva_i2c_sem_wait(priv);
ret = nxsem_wait_uninterruptible(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Un-initialize the port */
+47 -41
View File
@@ -99,7 +99,7 @@
TICK2USEC(CONFIG_PIC32MZ_I2CTIMEOTICKS)
#endif
/* Debug *********************************************************************/
/* Debug ********************************************************************/
/* I2C event trace logic. */
@@ -192,22 +192,29 @@ struct pic32mz_i2c_config_s
struct pic32mz_i2c_priv_s
{
const struct i2c_ops_s *ops; /* Standard I2C operations */
const struct pic32mz_i2c_config_s *config; /* Port configuration */
int refs; /* Referernce count */
sem_t sem_excl; /* Mutual exclusion semaphore */
/* Standard I2C operations */
const struct i2c_ops_s *ops;
/* Port configuration */
const struct pic32mz_i2c_config_s *config;
int refs; /* Reference count */
sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
sem_t sem_isr; /* Interrupt wait semaphore */
sem_t sem_isr; /* Interrupt wait semaphore */
#endif
volatile uint8_t intstate; /* Interrupt handshake (see enum pic32mz_intstate_e) */
volatile uint8_t intstate; /* Interrupt handshake (see enum
* pic32mz_intstate_e) */
volatile uint8_t process_state; /* State of the isr process */
uint8_t msgc; /* Message count */
struct i2c_msg_s *msgv; /* Message list */
uint8_t *ptr; /* Current message buffer */
uint32_t frequency; /* Current I2C frequency */
int dcnt; /* Current message length */
uint16_t flags; /* Current message flags */
uint8_t msgc; /* Message count */
struct i2c_msg_s *msgv; /* Message list */
uint8_t *ptr; /* Current message buffer */
uint32_t frequency; /* Current I2C frequency */
int dcnt; /* Current message length */
uint16_t flags; /* Current message flags */
/* I2C trace support */
@@ -227,14 +234,14 @@ struct pic32mz_i2c_priv_s
* Private Function Prototypes
****************************************************************************/
static inline uint32_t pic32mz_i2c_getreg(FAR struct pic32mz_i2c_priv_s *priv,
uint8_t offset);
static inline uint32_t
pic32mz_i2c_getreg(FAR struct pic32mz_i2c_priv_s *priv,
uint8_t offset);
static inline void pic32mz_i2c_putreg(FAR struct pic32mz_i2c_priv_s *priv,
uint8_t offset, uint32_t value);
static inline void pic32mz_i2c_modifyreg(FAR struct pic32mz_i2c_priv_s *priv,
uint8_t offset, uint32_t clearbits,
uint32_t setbits);
static inline void pic32mz_i2c_sem_wait(FAR struct pic32mz_i2c_priv_s *priv);
#ifdef CONFIG_PICM32MZ_I2C_DYNTIMEO
static useconds_t pic32mz_i2c_tousecs(int msgc, FAR struct i2c_msg_s *msgs);
@@ -253,16 +260,19 @@ static inline void
static void pic32mz_i2c_tracereset(FAR struct pic32mz_i2c_priv_s *priv);
static void pic32mz_i2c_tracenew(FAR struct pic32mz_i2c_priv_s *priv,
uint32_t status);
static void pic32mz_i2c_traceevent(FAR struct pic32mz_i2c_priv_s *priv,
enum pic32mz_trace_e event, uint32_t parm);
static void
pic32mz_i2c_traceevent(FAR struct pic32mz_i2c_priv_s *priv,
enum pic32mz_trace_e event, uint32_t parm);
static void pic32mz_i2c_tracedump(FAR struct pic32mz_i2c_priv_s *priv);
#endif /* CONFIG_I2C_TRACE */
static inline int pic32mz_i2c_setbaudrate(FAR struct pic32mz_i2c_priv_s *priv,
uint32_t frequency);
static inline int
pic32mz_i2c_setbaudrate(FAR struct pic32mz_i2c_priv_s *priv,
uint32_t frequency);
static inline void
pic32mz_i2c_send_start(FAR struct pic32mz_i2c_priv_s *priv);
static inline void pic32mz_i2c_send_stop(FAR struct pic32mz_i2c_priv_s *priv);
static inline void
pic32mz_i2c_send_stop(FAR struct pic32mz_i2c_priv_s *priv);
static inline void
pic32mz_i2c_send_repeatedstart(FAR struct pic32mz_i2c_priv_s *priv);
static inline void pic32mz_i2c_send_ack(FAR struct pic32mz_i2c_priv_s *priv,
@@ -586,8 +596,8 @@ static void pic32mz_i2c_tracedump(FAR struct pic32mz_i2c_priv_s *priv)
*
****************************************************************************/
static inline uint32_t pic32mz_i2c_getreg(FAR struct pic32mz_i2c_priv_s *priv,
uint8_t offset)
static inline uint32_t
pic32mz_i2c_getreg(FAR struct pic32mz_i2c_priv_s *priv, uint8_t offset)
{
return getreg32(priv->config->base + offset);
}
@@ -621,19 +631,6 @@ static inline void pic32mz_i2c_modifyreg(FAR struct pic32mz_i2c_priv_s *priv,
modifyreg32(priv->config->base + offset, clearbits, setbits);
}
/****************************************************************************
* Name: pic32mz_i2c_sem_wait
*
* Description:
* Take the exclusive access, waiting as necessary
*
****************************************************************************/
static inline void pic32mz_i2c_sem_wait(FAR struct pic32mz_i2c_priv_s *priv)
{
nxsem_wait_uninterruptible(&priv->sem_excl);
}
/****************************************************************************
* Name: pic32mz_i2c_tousecs
*
@@ -1315,8 +1312,9 @@ static int pic32mz_i2c_isr(int irq, void *context, FAR void *arg)
*
****************************************************************************/
static inline int pic32mz_i2c_setbaudrate(FAR struct pic32mz_i2c_priv_s *priv,
uint32_t frequency)
static inline int
pic32mz_i2c_setbaudrate(FAR struct pic32mz_i2c_priv_s *priv,
uint32_t frequency)
{
uint32_t baudrate;
@@ -1602,12 +1600,16 @@ static int pic32mz_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count)
{
FAR struct pic32mz_i2c_priv_s *priv = (struct pic32mz_i2c_priv_s *)dev;
int ret = OK;
uint32_t status = 0;
int ret;
/* Acquire the semaphore. */
pic32mz_i2c_sem_wait(priv);
ret = nxsem_wait(&priv->sem_excl);
if (ret < 0)
{
return ret;
}
/* Wait for the bus to be in an idle state. */
@@ -1732,7 +1734,11 @@ static int pic32mz_i2c_reset(FAR struct i2c_master_s *dev)
/* Lock out other clients */
pic32mz_i2c_sem_wait(priv);
ret = nxsem_wait_uninterruptible(&priv->sem_excl);
if (ret < 0)
{
return ret;
}
/* Save the current frequency */
+10 -8
View File
@@ -115,13 +115,11 @@ const struct i2c_ops_s g_ops =
*
****************************************************************************/
static void ez80_i2c_semtake(void)
static int ez80_i2c_semtake(void)
{
nxsem_wait_uninterruptible(&g_i2csem);
return nxsem_wait(&g_i2csem);
}
#define ez80_i2c_semgive() nxsem_post(&g_i2csem)
/****************************************************************************
* Name: ez80_i2c_setccr
*
@@ -808,7 +806,7 @@ static int ez80_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msg;
bool nostop;
uint8_t flags;
int ret = OK;
int ret;
int i;
/* Perform each segment of the transfer, message at a time */
@@ -817,9 +815,13 @@ static int ez80_i2c_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the I2C bus */
ez80_i2c_semtake();
ret = nxsem_wait(&g_i2csem);
if (ret < 0)
{
return ret;
}
/* The process each message seqment */
/* The process each message segment */
for (i = 0; i < count; i++)
{
@@ -885,7 +887,7 @@ static int ez80_i2c_transfer(FAR struct i2c_master_s *dev,
flags = (nostop) ? EZ80_NOSTART : 0;
}
ez80_i2c_semgive();
nxsem_post(&g_i2csem);
return ret;
}
+47 -68
View File
@@ -1,35 +1,20 @@
/****************************************************************************
* arch/z80/src/z8/z8_i2c.c
*
* Copyright(C) 2009, 2011, 2013, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* http://www.apache.org/licenses/LICENSE-2.0
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
@@ -124,26 +109,6 @@ const struct i2c_ops_s g_ops =
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: z8_i2c_semtake/z8_i2c_semgive
*
* Description:
* Take/Give the I2C semaphore.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void z8_i2c_semtake(void)
{
nxsem_wait_uninterruptible(&g_i2csem);
}
#define z8_i2c_semgive() nxsem_post(&g_i2csem)
/****************************************************************************
* Name: z8_i2c_waittxempty
@@ -182,7 +147,12 @@ static void z8_i2c_waittxempty(void)
static void z8_i2c_waitrxavail(void)
{
int i;
for (i = 0; i <= 10000 && (I2CSTAT & (I2C_STAT_RDRF | I2C_STAT_NCKI)) == 0; i++);
for (i = 0;
i <= 10000 && (I2CSTAT & (I2C_STAT_RDRF | I2C_STAT_NCKI)) == 0;
i++)
{
}
}
/****************************************************************************
@@ -225,10 +195,10 @@ static uint16_t z8_i2c_getbrg(uint32_t frequency)
/* Max is 400 Kb/sec */
if (frequency > 400*1000)
if (frequency > 400 * 1000)
{
_err("ERROR: Invalid inputs\n");
frequency = 400*1000;
frequency = 400 * 1000;
}
/* BRG = sysclock / (4 * frequency) */
@@ -247,7 +217,8 @@ static uint16_t z8_i2c_getbrg(uint32_t frequency)
*
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to a buffer of data to receive the data from the device
* buffer - A pointer to a buffer of data to receive the data from the
* device
* buflen - The requested number of bytes to be read
* flags - Determines is a START and/or STOP indication is needed.
*
@@ -357,7 +328,8 @@ static int z8_i2c_read_transfer(FAR struct z8_i2cdev_s *priv,
*
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the read-only buffer of data to be written to device
* buffer - A pointer to the read-only buffer of data to be written to
* device
* buflen - The number of bytes to send from the buffer
* flags - Determines is a START and/or STOP indication is needed.
*
@@ -474,16 +446,18 @@ static void z8_i2c_setfrequency(FAR struct z8_i2cdev_s *priv,
/* Has the frequency changed? */
if (priv->frequency != frequency)
{
/* Calculate and save the BRG (we won't apply it until the first transfer) */
{
/* Calculate and save the BRG (we won't apply it until the first
* transfer)
*/
brg = z8_i2c_getbrg(frequency);
z8_i2c_setbrg(brg);
brg = z8_i2c_getbrg(frequency);
z8_i2c_setbrg(brg);
/* Save the new I2C frequency */
/* Save the new I2C frequency */
priv->frequency = frequency;
}
priv->frequency = frequency;
}
}
/****************************************************************************
@@ -512,7 +486,7 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msg;
bool nostop;
uint8_t flags;
int ret = OK;
int ret;
int i;
/* Perform each segment of the transfer, message at a time */
@@ -521,9 +495,13 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
/* Get exclusive access to the I2C bus */
z8_i2c_semtake();
ret = nxsem_wait(&g_i2csem);
if (ret < 0)
{
return ret;
}
/* The process each message seqment */
/* The process each message segment */
for (i = 0; i < count; i++)
{
@@ -540,7 +518,7 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
nostop = false;
if (i < (count - 1))
{
{
FAR struct i2c_msg_s *next;
/* No... Check if the next message should have a repeated start or
@@ -553,7 +531,8 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
next = &msgs[i + 1];
if ((msg->flags & I2C_M_NOSTART) != 0 &&
(msg->flags & (I2C_M_READ | I2C_M_TEN)) == (next->flags & (I2C_M_READ | I2C_M_TEN)) &&
(msg->flags & (I2C_M_READ | I2C_M_TEN)) ==
(next->flags & (I2C_M_READ | I2C_M_TEN)) &&
msg->addr == next->addr)
{
nostop = true;
@@ -586,11 +565,11 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
flags = (nostop) ? Z8_NOSTART : 0;
}
z8_i2c_semgive();
nxsem_post(&g_i2csem);
return ret;
}
/************************************************************************************
/****************************************************************************
* Name: z8_i2c_reset
*
* Description:
@@ -602,7 +581,7 @@ static int z8_i2c_transfer(FAR struct i2c_master_s *dev,
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
************************************************************************************/
****************************************************************************/
#ifdef CONFIG_I2C_RESET
static int z8_i2c_reset(FAR struct i2c_master_s * dev)
@@ -640,7 +619,7 @@ FAR struct i2c_master_s *z8_i2cbus_initialize(int port)
{
/* Set up some initial BRG value */
uint16_t brg = z8_i2c_getbrg(100*1000);
uint16_t brg = z8_i2c_getbrg(100 * 1000);
z8_i2c_setbrg(brg);
/* Make sure that GPIOs are configured for the alternate function (this