drivers/video/isx012: Add exclusive controls for I2C access

Add exclusive control to prevent from I2C write(for sending requst) and
I2C read(for receiving response).
This commit is contained in:
SPRESENSE 2022-02-25 12:21:09 +09:00 committed by Petro Karashchenko
parent bea6d3a7ef
commit 1613ded060

View File

@ -30,6 +30,7 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/semaphore.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/signal.h> #include <nuttx/signal.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
@ -168,6 +169,7 @@ typedef struct isx012_reg_s isx012_reg_t;
struct isx012_dev_s struct isx012_dev_s
{ {
sem_t i2c_lock;
FAR struct i2c_master_s *i2c; /* I2C interface */ FAR struct i2c_master_s *i2c; /* I2C interface */
uint8_t i2c_addr; /* I2C address */ uint8_t i2c_addr; /* I2C address */
int i2c_freq; /* Frequency */ int i2c_freq; /* Frequency */
@ -635,6 +637,16 @@ static struct imgsensor_ops_s g_isx012_ops =
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
static void i2c_lock(void)
{
nxsem_wait_uninterruptible(&g_isx012_private.i2c_lock);
}
static void i2c_unlock(void)
{
nxsem_post(&g_isx012_private.i2c_lock);
}
static uint16_t isx012_getreg(isx012_dev_t *priv, static uint16_t isx012_getreg(isx012_dev_t *priv,
uint16_t regaddr, uint16_t regsize) uint16_t regaddr, uint16_t regsize)
{ {
@ -651,25 +663,32 @@ static uint16_t isx012_getreg(isx012_dev_t *priv,
buffer[0] = regaddr >> 8; buffer[0] = regaddr >> 8;
buffer[1] = regaddr & 0xff; buffer[1] = regaddr & 0xff;
i2c_lock();
/* Write the register address */ /* Write the register address */
ret = i2c_write(priv->i2c, &config, (uint8_t *)buffer, 2); ret = i2c_write(priv->i2c, &config, (uint8_t *)buffer, 2);
if (ret < 0) if (ret < 0)
{ {
verr("i2c_write failed: %d\n", ret); verr("i2c_write failed: %d\n", ret);
return 0;
} }
else
/* Restart and read 16bits from the register */
ret = i2c_read(priv->i2c, &config, (uint8_t *)buffer, regsize);
if (ret < 0)
{ {
verr("i2c_read failed: %d\n", ret); /* Restart and read 16bits from the register */
return 0;
ret = i2c_read(priv->i2c, &config, (uint8_t *)buffer, regsize);
if (ret < 0)
{
verr("i2c_read failed: %d\n", ret);
}
} }
memcpy((uint8_t *)&regval, (uint8_t *)buffer, regsize); i2c_unlock();
if (ret >= 0)
{
memcpy((uint8_t *)&regval, (uint8_t *)buffer, regsize);
}
return regval; return regval;
} }
@ -694,6 +713,8 @@ static int isx012_putreg(isx012_dev_t *priv,
memcpy((uint8_t *)&buffer[2], (uint8_t *)&regval, regsize); memcpy((uint8_t *)&buffer[2], (uint8_t *)&regval, regsize);
i2c_lock();
/* And do it */ /* And do it */
ret = i2c_write(priv->i2c, &config, ret = i2c_write(priv->i2c, &config,
@ -703,6 +724,8 @@ static int isx012_putreg(isx012_dev_t *priv,
verr("i2c_write failed: %d\n", ret); verr("i2c_write failed: %d\n", ret);
} }
i2c_unlock();
return ret; return ret;
} }
@ -2924,6 +2947,8 @@ int isx012_initialize(void)
priv->state = STATE_ISX012_POWEROFF; priv->state = STATE_ISX012_POWEROFF;
nxsem_init(&priv->i2c_lock, 0, 1);
return OK; return OK;
} }