forked from nuttx/nuttx-update
Check return from nxsem_wait_uninterruptible
This commit is only for those files under drivers/1wire, drivers/bch, drivers/can and drivers/mmcsd.
This commit is contained in:
parent
986e594563
commit
997d4fabb0
9 changed files with 355 additions and 109 deletions
|
@ -143,7 +143,7 @@ static inline void onewire_sem_destroy(FAR struct onewire_sem_s *sem)
|
||||||
nxsem_destroy(&sem->sem);
|
nxsem_destroy(&sem->sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: onewire_pm_prepare
|
* Name: onewire_pm_prepare
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
|
@ -170,7 +170,7 @@ static inline void onewire_sem_destroy(FAR struct onewire_sem_s *sem)
|
||||||
* power state change). Drivers are not permitted to return non-zero
|
* power state change). Drivers are not permitted to return non-zero
|
||||||
* values when reverting back to higher power consumption modes!
|
* values when reverting back to higher power consumption modes!
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int onewire_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
static int onewire_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
enum pm_state_e pmstate)
|
enum pm_state_e pmstate)
|
||||||
|
@ -190,6 +190,7 @@ static int onewire_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
|
|
||||||
case PM_STANDBY:
|
case PM_STANDBY:
|
||||||
case PM_SLEEP:
|
case PM_SLEEP:
|
||||||
|
|
||||||
/* Check if exclusive lock for the bus master is held. */
|
/* Check if exclusive lock for the bus master is held. */
|
||||||
|
|
||||||
if (nxsem_getvalue(&master->devsem.sem, &sval) < 0)
|
if (nxsem_getvalue(&master->devsem.sem, &sval) < 0)
|
||||||
|
@ -208,6 +209,7 @@ static int onewire_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* Should not get here */
|
/* Should not get here */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -229,9 +231,10 @@ static int onewire_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void onewire_sem_wait(FAR struct onewire_master_s *master)
|
int onewire_sem_wait(FAR struct onewire_master_s *master)
|
||||||
{
|
{
|
||||||
pid_t me;
|
pid_t me;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Do we already hold the semaphore? */
|
/* Do we already hold the semaphore? */
|
||||||
|
|
||||||
|
@ -248,13 +251,19 @@ void onewire_sem_wait(FAR struct onewire_master_s *master)
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nxsem_wait_uninterruptible(&master->devsem.sem);
|
ret = nxsem_wait(master->devsem.sem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we hold the semaphore */
|
/* Now we hold the semaphore */
|
||||||
|
|
||||||
master->devsem.holder = me;
|
master->devsem.holder = me;
|
||||||
master->devsem.count = 1;
|
master->devsem.count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -298,7 +307,10 @@ void onewire_sem_post(FAR struct onewire_master_s *master)
|
||||||
int onewire_reset_resume(FAR struct onewire_master_s *master)
|
int onewire_reset_resume(FAR struct onewire_master_s *master)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t buf[] = { ONEWIRE_CMD_RESUME };
|
uint8_t buf[] =
|
||||||
|
{
|
||||||
|
ONEWIRE_CMD_RESUME
|
||||||
|
};
|
||||||
|
|
||||||
ret = ONEWIRE_RESET(master->dev);
|
ret = ONEWIRE_RESET(master->dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -320,8 +332,16 @@ int onewire_reset_select(FAR struct onewire_slave_s *slave)
|
||||||
{
|
{
|
||||||
FAR struct onewire_master_s *master = slave->master;
|
FAR struct onewire_master_s *master = slave->master;
|
||||||
uint64_t tmp;
|
uint64_t tmp;
|
||||||
uint8_t skip_rom[1] = { ONEWIRE_CMD_SKIP_ROM };
|
uint8_t skip_rom[1] =
|
||||||
uint8_t match_rom[9] = { ONEWIRE_CMD_MATCH_ROM, 0 };
|
{
|
||||||
|
ONEWIRE_CMD_SKIP_ROM
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t match_rom[9] =
|
||||||
|
{
|
||||||
|
ONEWIRE_CMD_MATCH_ROM, 0
|
||||||
|
};
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ONEWIRE_RESET(master->dev);
|
ret = ONEWIRE_RESET(master->dev);
|
||||||
|
@ -355,8 +375,16 @@ int onewire_reset_select(FAR struct onewire_slave_s *slave)
|
||||||
|
|
||||||
int onewire_readrom(FAR struct onewire_master_s *master, FAR uint64_t *rom)
|
int onewire_readrom(FAR struct onewire_master_s *master, FAR uint64_t *rom)
|
||||||
{
|
{
|
||||||
uint8_t txbuf[] = { ONEWIRE_CMD_READ_ROM };
|
uint8_t txbuf[] =
|
||||||
uint8_t rxbuf[8] = { 0 };
|
{
|
||||||
|
ONEWIRE_CMD_READ_ROM
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t rxbuf[8] =
|
||||||
|
{
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
uint64_t tmp = -1;
|
uint64_t tmp = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -492,7 +520,9 @@ int onewire_triplet(FAR struct onewire_master_s *master,
|
||||||
int onewire_search(FAR struct onewire_master_s *master,
|
int onewire_search(FAR struct onewire_master_s *master,
|
||||||
int family,
|
int family,
|
||||||
bool alarmonly,
|
bool alarmonly,
|
||||||
CODE void (*cb_search)(int family, uint64_t romcode, FAR void *arg),
|
CODE void (*cb_search)(int family,
|
||||||
|
uint64_t romcode,
|
||||||
|
FAR void *arg),
|
||||||
FAR void *arg)
|
FAR void *arg)
|
||||||
{
|
{
|
||||||
FAR struct onewire_dev_s *dev = master->dev;
|
FAR struct onewire_dev_s *dev = master->dev;
|
||||||
|
@ -704,7 +734,8 @@ FAR struct onewire_master_s *
|
||||||
DEBUGASSERT(dev != NULL);
|
DEBUGASSERT(dev != NULL);
|
||||||
DEBUGASSERT(maxslaves > 0);
|
DEBUGASSERT(maxslaves > 0);
|
||||||
|
|
||||||
master = (FAR struct onewire_master_s *)kmm_malloc(sizeof(struct onewire_master_s));
|
master = (FAR struct onewire_master_s *)
|
||||||
|
kmm_malloc(sizeof(struct onewire_master_s));
|
||||||
if (master == NULL)
|
if (master == NULL)
|
||||||
{
|
{
|
||||||
i2cerr("ERROR: Failed to allocate\n");
|
i2cerr("ERROR: Failed to allocate\n");
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool onewire_check_crc16(FAR const uint8_t *input, uint16_t len,
|
||||||
|
|
||||||
/* Rest are from 1wire.c */
|
/* Rest are from 1wire.c */
|
||||||
|
|
||||||
void onewire_sem_wait(FAR struct onewire_master_s *master);
|
int onewire_sem_wait(FAR struct onewire_master_s *master);
|
||||||
void onewire_sem_post(FAR struct onewire_master_s *master);
|
void onewire_sem_post(FAR struct onewire_master_s *master);
|
||||||
|
|
||||||
int onewire_addslave(FAR struct onewire_master_s *master,
|
int onewire_addslave(FAR struct onewire_master_s *master,
|
||||||
|
@ -163,7 +163,9 @@ int onewire_triplet(FAR struct onewire_master_s *master,
|
||||||
int onewire_search(FAR struct onewire_master_s *master,
|
int onewire_search(FAR struct onewire_master_s *master,
|
||||||
int family,
|
int family,
|
||||||
bool alarmonly,
|
bool alarmonly,
|
||||||
CODE void (*cb_search)(int family, uint64_t romcode, FAR void *arg),
|
CODE void (*cb_search)(int family,
|
||||||
|
uint64_t romcode,
|
||||||
|
FAR void *arg),
|
||||||
FAR void *arg);
|
FAR void *arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
|
@ -160,7 +160,7 @@ static const struct i2c_ops_s ds_i2c_ops =
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void ds_i2c_sem_wait(FAR struct i2c_master_s *i2cdev)
|
static inline int ds_i2c_sem_wait(FAR struct i2c_master_s *i2cdev)
|
||||||
{
|
{
|
||||||
FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
|
FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
|
||||||
FAR struct onewire_master_s *master = inst->master;
|
FAR struct onewire_master_s *master = inst->master;
|
||||||
|
@ -205,11 +205,13 @@ static int ds_error(uint8_t buf[])
|
||||||
i2cerr("I2C device not responding\n");
|
i2cerr("I2C device not responding\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] & DS_STATUS_START)
|
if (buf[0] & DS_STATUS_START)
|
||||||
{
|
{
|
||||||
i2cerr("I2C status start\n");
|
i2cerr("I2C status start\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] != 0 || buf[1] != 0)
|
if (buf[0] != 0 || buf[1] != 0)
|
||||||
{
|
{
|
||||||
i2cerr("I2C IO error\n");
|
i2cerr("I2C IO error\n");
|
||||||
|
@ -286,7 +288,8 @@ static int ds_busywait(FAR struct ds_i2c_inst_s *inst, size_t length)
|
||||||
|
|
||||||
up_udelay(delay);
|
up_udelay(delay);
|
||||||
}
|
}
|
||||||
} while (retries-- > 0);
|
}
|
||||||
|
while (retries-- > 0);
|
||||||
|
|
||||||
i2cwarn("busywait timeout\n");
|
i2cwarn("busywait timeout\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
@ -461,7 +464,8 @@ static int ds_i2c_write(FAR struct ds_i2c_inst_s *inst, uint16_t i2c_addr,
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int ds_i2c_write_read(FAR struct ds_i2c_inst_s *inst, uint16_t i2c_addr,
|
static int ds_i2c_write_read(FAR struct ds_i2c_inst_s *inst,
|
||||||
|
uint16_t i2c_addr,
|
||||||
FAR const uint8_t *wbuffer, ssize_t wlength,
|
FAR const uint8_t *wbuffer, ssize_t wlength,
|
||||||
FAR uint8_t *rbuffer, ssize_t rlength)
|
FAR uint8_t *rbuffer, ssize_t rlength)
|
||||||
{
|
{
|
||||||
|
@ -552,7 +556,8 @@ static int ds_i2c_write_read(FAR struct ds_i2c_inst_s *inst, uint16_t i2c_addr,
|
||||||
return ONEWIRE_READ(master->dev, rbuffer, rlength);
|
return ONEWIRE_READ(master->dev, rbuffer, rlength);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ds_i2c_setfrequency(FAR struct ds_i2c_inst_s *inst, uint32_t frequency)
|
static int ds_i2c_setfrequency(FAR struct ds_i2c_inst_s *inst,
|
||||||
|
uint32_t frequency)
|
||||||
{
|
{
|
||||||
FAR struct onewire_master_s *master = inst->master;
|
FAR struct onewire_master_s *master = inst->master;
|
||||||
uint8_t buf[2];
|
uint8_t buf[2];
|
||||||
|
@ -645,15 +650,15 @@ static int ds_i2c_process(FAR struct i2c_master_s *i2cdev,
|
||||||
* the common case of write followed by read to a same address.
|
* the common case of write followed by read to a same address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (i < count - 1 && msgs[i].addr == msgs[i+1].addr &&
|
if (i < count - 1 && msgs[i].addr == msgs[i + 1].addr &&
|
||||||
(msgs[i].flags & I2C_M_READ) == 0 &&
|
(msgs[i].flags & I2C_M_READ) == 0 &&
|
||||||
(msgs[i+1].flags & I2C_M_READ))
|
(msgs[i + 1].flags & I2C_M_READ))
|
||||||
{
|
{
|
||||||
/* Write-read combined transfer. */
|
/* Write-read combined transfer. */
|
||||||
|
|
||||||
ret = ds_i2c_write_read(inst, msgs[i].addr,
|
ret = ds_i2c_write_read(inst, msgs[i].addr,
|
||||||
msgs[i].buffer, msgs[i].length,
|
msgs[i].buffer, msgs[i].length,
|
||||||
msgs[i+1].buffer, msgs[i+1].length);
|
msgs[i + 1].buffer, msgs[i + 1].length);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
i = ret;
|
i = ret;
|
||||||
|
@ -668,7 +673,8 @@ static int ds_i2c_process(FAR struct i2c_master_s *i2cdev,
|
||||||
{
|
{
|
||||||
/* Read transfer. */
|
/* Read transfer. */
|
||||||
|
|
||||||
ret = ds_i2c_read(inst, msgs[i].addr, msgs[i].buffer, msgs[i].length);
|
ret = ds_i2c_read(inst, msgs[i].addr, msgs[i].buffer,
|
||||||
|
msgs[i].length);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
i = ret;
|
i = ret;
|
||||||
|
@ -681,8 +687,8 @@ static int ds_i2c_process(FAR struct i2c_master_s *i2cdev,
|
||||||
{
|
{
|
||||||
/* Write transfer. Stop condition only for last transfer. */
|
/* Write transfer. Stop condition only for last transfer. */
|
||||||
|
|
||||||
ret = ds_i2c_write(inst, msgs[i].addr, msgs[i].buffer, msgs[i].length,
|
ret = ds_i2c_write(inst, msgs[i].addr, msgs[i].buffer,
|
||||||
i == (count-1));
|
msgs[i].length, i == (count - 1));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
i = ret;
|
i = ret;
|
||||||
|
@ -696,8 +702,9 @@ static int ds_i2c_process(FAR struct i2c_master_s *i2cdev,
|
||||||
|
|
||||||
if (i < count)
|
if (i < count)
|
||||||
{
|
{
|
||||||
/* Yes. Resume to same DS28E17. */
|
/* Yes. Resume to same DS28E17.
|
||||||
/* Oddness: Skip-ROM does not set RS-bit needed by resume. */
|
* Oddness: Skip-ROM does not set RS-bit needed by resume.
|
||||||
|
*/
|
||||||
|
|
||||||
if (master->nslaves > 1)
|
if (master->nslaves > 1)
|
||||||
{
|
{
|
||||||
|
@ -707,6 +714,7 @@ static int ds_i2c_process(FAR struct i2c_master_s *i2cdev,
|
||||||
{
|
{
|
||||||
ret = onewire_reset_select(&inst->slave);
|
ret = onewire_reset_select(&inst->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
i = ret;
|
i = ret;
|
||||||
|
@ -734,7 +742,12 @@ static int ds_i2c_reset(FAR struct i2c_master_s *i2cdev)
|
||||||
FAR struct onewire_master_s *master = inst->master;
|
FAR struct onewire_master_s *master = inst->master;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ds_i2c_sem_wait(i2cdev);
|
ret = ds_i2c_sem_wait(i2cdev);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ONEWIRE_RESET(master->dev);
|
ret = ONEWIRE_RESET(master->dev);
|
||||||
ds_i2c_sem_post(i2cdev);
|
ds_i2c_sem_post(i2cdev);
|
||||||
|
|
||||||
|
@ -756,7 +769,12 @@ static int ds_i2c_transfer(FAR struct i2c_master_s *i2cdev,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ds_i2c_sem_wait(i2cdev);
|
ret = ds_i2c_sem_wait(i2cdev);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ds_i2c_process(i2cdev, msgs, count);
|
ret = ds_i2c_process(i2cdev, msgs, count);
|
||||||
ds_i2c_sem_post(i2cdev);
|
ds_i2c_sem_post(i2cdev);
|
||||||
|
|
||||||
|
@ -773,8 +791,16 @@ static int ds_i2c_transfer(FAR struct i2c_master_s *i2cdev,
|
||||||
static int ds28e17_selftest(FAR struct ds_i2c_inst_s *inst)
|
static int ds28e17_selftest(FAR struct ds_i2c_inst_s *inst)
|
||||||
{
|
{
|
||||||
FAR struct onewire_master_s *master = inst->master;
|
FAR struct onewire_master_s *master = inst->master;
|
||||||
uint8_t txbuf[] = { ONEWIRE_CMD_READ_ROM };
|
uint8_t txbuf[] =
|
||||||
uint8_t rxbuf[8] = { 0 };
|
{
|
||||||
|
ONEWIRE_CMD_READ_ROM
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t rxbuf[8] =
|
||||||
|
{
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
uint64_t rom;
|
uint64_t rom;
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -843,7 +869,9 @@ static int ds28e17_selftest(FAR struct ds_i2c_inst_s *inst)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int ds28e17_search(FAR struct ds28e17_dev_s *priv,
|
int ds28e17_search(FAR struct ds28e17_dev_s *priv,
|
||||||
void (*cb_search)(int family, uint64_t romcode, void *arg),
|
void (*cb_search)(int family,
|
||||||
|
uint64_t romcode,
|
||||||
|
void *arg),
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
FAR struct onewire_master_s *master = (FAR struct onewire_master_s *)priv;
|
FAR struct onewire_master_s *master = (FAR struct onewire_master_s *)priv;
|
||||||
|
@ -851,7 +879,12 @@ int ds28e17_search(FAR struct ds28e17_dev_s *priv,
|
||||||
|
|
||||||
DEBUGASSERT(master != NULL && cb_search != NULL);
|
DEBUGASSERT(master != NULL && cb_search != NULL);
|
||||||
|
|
||||||
onewire_sem_wait(master);
|
ret = onewire_sem_wait(master);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = onewire_search(master, DS_FAMILY, false, cb_search, arg);
|
ret = onewire_search(master, DS_FAMILY, false, cb_search, arg);
|
||||||
onewire_sem_post(master);
|
onewire_sem_post(master);
|
||||||
|
|
||||||
|
@ -881,6 +914,7 @@ FAR struct i2c_master_s *
|
||||||
{
|
{
|
||||||
FAR struct ds_i2c_inst_s *inst; /* device, single instance */
|
FAR struct ds_i2c_inst_s *inst; /* device, single instance */
|
||||||
FAR struct onewire_master_s *master = (FAR struct onewire_master_s *)priv;
|
FAR struct onewire_master_s *master = (FAR struct onewire_master_s *)priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(master != NULL);
|
DEBUGASSERT(master != NULL);
|
||||||
|
|
||||||
|
@ -903,7 +937,13 @@ FAR struct i2c_master_s *
|
||||||
|
|
||||||
/* We need a recursive lock as this may be called from a search callback. */
|
/* We need a recursive lock as this may be called from a search callback. */
|
||||||
|
|
||||||
onewire_sem_wait(master);
|
ret = onewire_sem_wait(master);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
kmm_free(inst);
|
||||||
|
i2cerr("ERROR: Failed to acquire lock\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (onewire_addslave(master, &inst->slave) < 0)
|
if (onewire_addslave(master, &inst->slave) < 0)
|
||||||
{
|
{
|
||||||
|
@ -953,7 +993,11 @@ int ds28e17_lower_half_unregister(FAR struct ds28e17_dev_s *priv,
|
||||||
FAR struct onewire_master_s *master = inst->master;
|
FAR struct onewire_master_s *master = inst->master;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
onewire_sem_wait(master);
|
ret = onewire_sem_wait(master);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = onewire_removeslave(master, &inst->slave);
|
ret = onewire_removeslave(master, &inst->slave);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -97,7 +97,7 @@ EXTERN const struct file_operations bch_fops;
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
EXTERN void bchlib_semtake(FAR struct bchlib_s *bch);
|
EXTERN int bchlib_semtake(FAR struct bchlib_s *bch);
|
||||||
EXTERN int bchlib_flushsector(FAR struct bchlib_s *bch);
|
EXTERN int bchlib_flushsector(FAR struct bchlib_s *bch);
|
||||||
EXTERN int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector);
|
EXTERN int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector);
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,12 @@ static int bch_open(FAR struct file *filep)
|
||||||
|
|
||||||
/* Increment the reference count */
|
/* Increment the reference count */
|
||||||
|
|
||||||
bchlib_semtake(bch);
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (bch->refs == MAX_OPENCNT)
|
if (bch->refs == MAX_OPENCNT)
|
||||||
{
|
{
|
||||||
ret = -EMFILE;
|
ret = -EMFILE;
|
||||||
|
@ -170,9 +175,16 @@ static int bch_close(FAR struct file *filep)
|
||||||
DEBUGASSERT(inode && inode->i_private);
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||||
|
|
||||||
|
/* Get exclusive access */
|
||||||
|
|
||||||
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Flush any dirty pages remaining in the cache */
|
/* Flush any dirty pages remaining in the cache */
|
||||||
|
|
||||||
bchlib_semtake(bch);
|
|
||||||
bchlib_flushsector(bch);
|
bchlib_flushsector(bch);
|
||||||
|
|
||||||
/* Decrement the reference count (I don't use bchlib_decref() because I
|
/* Decrement the reference count (I don't use bchlib_decref() because I
|
||||||
|
@ -231,7 +243,11 @@ static off_t bch_seek(FAR struct file *filep, off_t offset, int whence)
|
||||||
DEBUGASSERT(inode && inode->i_private);
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
|
|
||||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||||
bchlib_semtake(bch);
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (off_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine the new, requested file position */
|
/* Determine the new, requested file position */
|
||||||
|
|
||||||
|
@ -298,7 +314,12 @@ static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||||
DEBUGASSERT(inode && inode->i_private);
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||||
|
|
||||||
bchlib_semtake(bch);
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ssize_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = bchlib_read(bch, buffer, filep->f_pos, len);
|
ret = bchlib_read(bch, buffer, filep->f_pos, len);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
|
@ -325,7 +346,12 @@ static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
|
|
||||||
if (!bch->readonly)
|
if (!bch->readonly)
|
||||||
{
|
{
|
||||||
bchlib_semtake(bch);
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ssize_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = bchlib_write(bch, buffer, filep->f_pos, len);
|
ret = bchlib_write(bch, buffer, filep->f_pos, len);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
|
@ -366,7 +392,12 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||||
FAR struct bchlib_s **bchr =
|
FAR struct bchlib_s **bchr =
|
||||||
(FAR struct bchlib_s **)((uintptr_t)arg);
|
(FAR struct bchlib_s **)((uintptr_t)arg);
|
||||||
|
|
||||||
bchlib_semtake(bch);
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bchr || bch->refs == MAX_OPENCNT)
|
if (!bchr || bch->refs == MAX_OPENCNT)
|
||||||
{
|
{
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -454,7 +485,11 @@ static int bch_unlink(FAR struct inode *inode)
|
||||||
|
|
||||||
/* Get exclusive access to the BCH device */
|
/* Get exclusive access to the BCH device */
|
||||||
|
|
||||||
bchlib_semtake(bch);
|
ret = bchlib_semtake(bch);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Indicate that the driver has been unlinked */
|
/* Indicate that the driver has been unlinked */
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
* Name: bch_semtake
|
* Name: bch_semtake
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void bchlib_semtake(FAR struct bchlib_s *bch)
|
int bchlib_semtake(FAR struct bchlib_s *bch)
|
||||||
{
|
{
|
||||||
nxsem_wait_uninterruptible(&bch->sem);
|
return nxsem_wait(&bch->sem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,25 +211,25 @@ enum can_state_s
|
||||||
struct mcp2515_can_s
|
struct mcp2515_can_s
|
||||||
{
|
{
|
||||||
struct mcp2515_config_s *config; /* The constant configuration */
|
struct mcp2515_config_s *config; /* The constant configuration */
|
||||||
uint8_t state; /* See enum can_state_s */
|
uint8_t state; /* See enum can_state_s */
|
||||||
uint8_t nalloc; /* Number of allocated filters */
|
uint8_t nalloc; /* Number of allocated filters */
|
||||||
sem_t locksem; /* Enforces mutually exclusive access */
|
sem_t locksem; /* Enforces mutually exclusive access */
|
||||||
sem_t txfsem; /* Used to wait for TX FIFO availability */
|
sem_t txfsem; /* Used to wait for TX FIFO availability */
|
||||||
uint32_t btp; /* Current bit timing */
|
uint32_t btp; /* Current bit timing */
|
||||||
uint8_t rxints; /* Configured RX interrupts */
|
uint8_t rxints; /* Configured RX interrupts */
|
||||||
uint8_t txints; /* Configured TX interrupts */
|
uint8_t txints; /* Configured TX interrupts */
|
||||||
#ifdef CONFIG_CAN_ERRORS
|
#ifdef CONFIG_CAN_ERRORS
|
||||||
uint32_t olderrors; /* Used to detect the changes in error states */
|
uint32_t olderrors; /* Used to detect the changes in error states */
|
||||||
#endif
|
#endif
|
||||||
uint8_t filters; /* Standard/Extende filter bit allocator. */
|
uint8_t filters; /* Standard/Extende filter bit allocator. */
|
||||||
uint8_t txbuffers; /* TX Buffers bit allocator. */
|
uint8_t txbuffers; /* TX Buffers bit allocator. */
|
||||||
|
|
||||||
FAR uint8_t *spi_txbuf;
|
FAR uint8_t *spi_txbuf;
|
||||||
FAR uint8_t *spi_rxbuf;
|
FAR uint8_t *spi_rxbuf;
|
||||||
#ifdef CONFIG_MCP2515_REGDEBUG
|
#ifdef CONFIG_MCP2515_REGDEBUG
|
||||||
uintptr_t regaddr; /* Last register address read */
|
uintptr_t regaddr; /* Last register address read */
|
||||||
uint32_t regval; /* Last value read from the register */
|
uint32_t regval; /* Last value read from the register */
|
||||||
unsigned int count; /* Number of times that the value was read */
|
unsigned int count; /* Number of times that the value was read */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -241,10 +241,11 @@ struct mcp2515_can_s
|
||||||
|
|
||||||
static void mcp2515_readregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
static void mcp2515_readregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
||||||
FAR uint8_t *buffer, uint8_t len);
|
FAR uint8_t *buffer, uint8_t len);
|
||||||
static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv,
|
||||||
|
uint8_t regaddr,
|
||||||
FAR const uint8_t *buffer, uint8_t len);
|
FAR const uint8_t *buffer, uint8_t len);
|
||||||
static void mcp2515_modifyreg(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
static void mcp2515_modifyreg(FAR struct mcp2515_can_s *priv,
|
||||||
uint8_t mask, uint8_t value);
|
uint8_t regaddr, uint8_t mask, uint8_t value);
|
||||||
#ifdef CONFIG_MCP2515_REGDEBUG
|
#ifdef CONFIG_MCP2515_REGDEBUG
|
||||||
static void mcp2515_dumpregs(FAR struct mcp2515_can_s *priv,
|
static void mcp2515_dumpregs(FAR struct mcp2515_can_s *priv,
|
||||||
FAR const char *msg);
|
FAR const char *msg);
|
||||||
|
@ -254,7 +255,7 @@ static void mcp2515_dumpregs(FAR struct mcp2515_can_s *priv,
|
||||||
|
|
||||||
/* Semaphore helpers */
|
/* Semaphore helpers */
|
||||||
|
|
||||||
static void mcp2515_dev_lock(FAR struct mcp2515_can_s *priv);
|
static int mcp2515_dev_lock(FAR struct mcp2515_can_s *priv);
|
||||||
#define mcp2515_dev_unlock(priv) nxsem_post(&priv->locksem)
|
#define mcp2515_dev_unlock(priv) nxsem_post(&priv->locksem)
|
||||||
|
|
||||||
/* MCP2515 helpers */
|
/* MCP2515 helpers */
|
||||||
|
@ -427,7 +428,8 @@ static void mcp2515_transfer(FAR struct mcp2515_can_s *priv, uint8_t len)
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv,
|
||||||
|
uint8_t regaddr,
|
||||||
FAR const uint8_t *buffer, uint8_t len)
|
FAR const uint8_t *buffer, uint8_t len)
|
||||||
{
|
{
|
||||||
FAR struct mcp2515_config_s *config = priv->config;
|
FAR struct mcp2515_config_s *config = priv->config;
|
||||||
|
@ -480,8 +482,8 @@ static void mcp2515_writeregs(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void mcp2515_modifyreg(FAR struct mcp2515_can_s *priv, uint8_t regaddr,
|
static void mcp2515_modifyreg(FAR struct mcp2515_can_s *priv,
|
||||||
uint8_t mask, uint8_t value)
|
uint8_t regaddr, uint8_t mask, uint8_t value)
|
||||||
{
|
{
|
||||||
FAR struct mcp2515_config_s *config = priv->config;
|
FAR struct mcp2515_config_s *config = priv->config;
|
||||||
uint8_t wr[4] =
|
uint8_t wr[4] =
|
||||||
|
@ -543,9 +545,9 @@ static void mcp2515_dumpregs(FAR struct mcp2515_can_s *priv,
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void mcp2515_dev_lock(FAR struct mcp2515_can_s *priv)
|
static int mcp2515_dev_lock(FAR struct mcp2515_can_s *priv)
|
||||||
{
|
{
|
||||||
nxsem_wait_uninterruptible(&priv->locksem);
|
return nxsem_wait(&priv->locksem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -573,13 +575,18 @@ static int mcp2515_add_extfilter(FAR struct mcp2515_can_s *priv,
|
||||||
uint8_t offset;
|
uint8_t offset;
|
||||||
uint8_t mode = CAN_FILTER_MASK;
|
uint8_t mode = CAN_FILTER_MASK;
|
||||||
int ndx;
|
int ndx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
||||||
config = priv->config;
|
config = priv->config;
|
||||||
|
|
||||||
/* Get exclusive excess to the MCP2515 hardware */
|
/* Get exclusive excess to the MCP2515 hardware */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find an unused standard filter */
|
/* Find an unused standard filter */
|
||||||
|
|
||||||
|
@ -684,7 +691,8 @@ static int mcp2515_add_extfilter(FAR struct mcp2515_can_s *priv,
|
||||||
/* STD0 - STD2 */
|
/* STD0 - STD2 */
|
||||||
|
|
||||||
regval = (regval) |
|
regval = (regval) |
|
||||||
(uint8_t)(((extconfig->xf_id1 & 0x1c0000) >> 16) << 3);
|
(uint8_t)(((extconfig->xf_id1 &
|
||||||
|
0x1c0000) >> 16) << 3);
|
||||||
mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset +
|
mcp2515_writeregs(priv, MCP2515_RXF0SIDL + offset +
|
||||||
((priv->nalloc - 1) * 4), ®val, 1);
|
((priv->nalloc - 1) * 4), ®val, 1);
|
||||||
|
|
||||||
|
@ -714,7 +722,8 @@ static int mcp2515_add_extfilter(FAR struct mcp2515_can_s *priv,
|
||||||
/* STD0 - STD2 */
|
/* STD0 - STD2 */
|
||||||
|
|
||||||
regval = (regval) |
|
regval = (regval) |
|
||||||
(uint8_t)(((extconfig->xf_id2 & 0x1c0000) >> 16) << 3);
|
(uint8_t)(((extconfig->xf_id2 &
|
||||||
|
0x1c0000) >> 16) << 3);
|
||||||
mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1);
|
mcp2515_writeregs(priv, MCP2515_RXM0SIDL + offset, ®val, 1);
|
||||||
|
|
||||||
/* STD3 - STD10 */
|
/* STD3 - STD10 */
|
||||||
|
@ -801,6 +810,7 @@ static int mcp2515_del_extfilter(FAR struct mcp2515_can_s *priv, int ndx)
|
||||||
FAR struct mcp2515_config_s *config;
|
FAR struct mcp2515_config_s *config;
|
||||||
uint8_t regval;
|
uint8_t regval;
|
||||||
uint8_t offset;
|
uint8_t offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
||||||
config = priv->config;
|
config = priv->config;
|
||||||
|
@ -818,7 +828,11 @@ static int mcp2515_del_extfilter(FAR struct mcp2515_can_s *priv, int ndx)
|
||||||
|
|
||||||
/* Get exclusive excess to the MCP2515 hardware */
|
/* Get exclusive excess to the MCP2515 hardware */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if this filter is really assigned */
|
/* Check if this filter is really assigned */
|
||||||
|
|
||||||
|
@ -902,13 +916,18 @@ static int mcp2515_add_stdfilter(FAR struct mcp2515_can_s *priv,
|
||||||
uint8_t offset;
|
uint8_t offset;
|
||||||
uint8_t mode = CAN_FILTER_MASK;
|
uint8_t mode = CAN_FILTER_MASK;
|
||||||
int ndx;
|
int ndx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
||||||
config = priv->config;
|
config = priv->config;
|
||||||
|
|
||||||
/* Get exclusive excess to the MCP2515 hardware */
|
/* Get exclusive excess to the MCP2515 hardware */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find an unused standard filter */
|
/* Find an unused standard filter */
|
||||||
|
|
||||||
|
@ -1074,6 +1093,7 @@ static int mcp2515_del_stdfilter(FAR struct mcp2515_can_s *priv, int ndx)
|
||||||
FAR struct mcp2515_config_s *config;
|
FAR struct mcp2515_config_s *config;
|
||||||
uint8_t regval;
|
uint8_t regval;
|
||||||
uint8_t offset;
|
uint8_t offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
||||||
config = priv->config;
|
config = priv->config;
|
||||||
|
@ -1091,7 +1111,11 @@ static int mcp2515_del_stdfilter(FAR struct mcp2515_can_s *priv, int ndx)
|
||||||
|
|
||||||
/* Get exclusive excess to the MCP2515 hardware */
|
/* Get exclusive excess to the MCP2515 hardware */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if this filter is really assigned */
|
/* Check if this filter is really assigned */
|
||||||
|
|
||||||
|
@ -1166,6 +1190,7 @@ static int mcp2515_del_stdfilter(FAR struct mcp2515_can_s *priv, int ndx)
|
||||||
static void mcp2515_reset_lowlevel(FAR struct mcp2515_can_s *priv)
|
static void mcp2515_reset_lowlevel(FAR struct mcp2515_can_s *priv)
|
||||||
{
|
{
|
||||||
FAR struct mcp2515_config_s *config;
|
FAR struct mcp2515_config_s *config;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
config = priv->config;
|
config = priv->config;
|
||||||
|
@ -1175,7 +1200,11 @@ static void mcp2515_reset_lowlevel(FAR struct mcp2515_can_s *priv)
|
||||||
|
|
||||||
/* Get exclusive access to the MCP2515 peripheral */
|
/* Get exclusive access to the MCP2515 peripheral */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send SPI reset command to MCP2515 */
|
/* Send SPI reset command to MCP2515 */
|
||||||
|
|
||||||
|
@ -1263,7 +1292,11 @@ static int mcp2515_setup(FAR struct can_dev_s *dev)
|
||||||
|
|
||||||
/* Get exclusive access to the MCP2515 peripheral */
|
/* Get exclusive access to the MCP2515 peripheral */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* MCP2515 hardware initialization */
|
/* MCP2515 hardware initialization */
|
||||||
|
|
||||||
|
@ -1521,15 +1554,14 @@ static int mcp2515_ioctl(FAR struct can_dev_s *dev, int cmd,
|
||||||
* PHSEG1 == PHSEG2 (PHSEG2 = TSEG2)
|
* PHSEG1 == PHSEG2 (PHSEG2 = TSEG2)
|
||||||
*
|
*
|
||||||
* See more at:
|
* See more at:
|
||||||
|
* http://www.analog.com/en/analog-dialogue/articles/configure-can-bit-timing.html
|
||||||
*
|
*
|
||||||
* http://www.analog.com/en/analog-dialogue/articles/configure-can-bit-timing.html
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
phseg1 = tseg2;
|
phseg1 = tseg2;
|
||||||
prseg = tseg1 - phseg1;
|
prseg = tseg1 - phseg1;
|
||||||
|
|
||||||
brp = (uint32_t)
|
brp = (uint32_t)(((float) MCP2515_CANCLK_FREQUENCY /
|
||||||
(((float) MCP2515_CANCLK_FREQUENCY /
|
|
||||||
((float)(tseg1 + tseg2 + 1) * (float)(2 * bt->bt_baud))) - 1);
|
((float)(tseg1 + tseg2 + 1) * (float)(2 * bt->bt_baud))) - 1);
|
||||||
|
|
||||||
/* Save the value of the new bit timing register */
|
/* Save the value of the new bit timing register */
|
||||||
|
@ -1716,6 +1748,7 @@ static int mcp2515_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
|
||||||
uint8_t regval;
|
uint8_t regval;
|
||||||
uint8_t txbuf;
|
uint8_t txbuf;
|
||||||
unsigned int nbytes;
|
unsigned int nbytes;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(dev);
|
DEBUGASSERT(dev);
|
||||||
priv = dev->cd_priv;
|
priv = dev->cd_priv;
|
||||||
|
@ -1729,11 +1762,21 @@ static int mcp2515_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
|
||||||
|
|
||||||
/* Get exclusive access to the MCP2515 peripheral */
|
/* Get exclusive access to the MCP2515 peripheral */
|
||||||
|
|
||||||
mcp2515_dev_lock(priv);
|
ret = mcp2515_dev_lock(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Acquire buffer */
|
/* Acquire buffer */
|
||||||
|
|
||||||
nxsem_wait(&priv->txfsem);
|
ret = nxsem_wait(&priv->txfsem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
mcp2515_dev_unlock(priv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUGASSERT(priv->txbuffers != 0);
|
DEBUGASSERT(priv->txbuffers != 0);
|
||||||
|
|
||||||
txbuf = ffs(priv->txbuffers) - 1;
|
txbuf = ffs(priv->txbuffers) - 1;
|
||||||
|
@ -2485,7 +2528,8 @@ FAR struct mcp2515_can_s *
|
||||||
|
|
||||||
caninfo("Starting mcp2515_instantiate()!\n");
|
caninfo("Starting mcp2515_instantiate()!\n");
|
||||||
|
|
||||||
priv = (FAR struct mcp2515_can_s *)kmm_malloc(sizeof(struct mcp2515_can_s));
|
priv = (FAR struct mcp2515_can_s *)
|
||||||
|
kmm_malloc(sizeof(struct mcp2515_can_s));
|
||||||
if (priv == NULL)
|
if (priv == NULL)
|
||||||
{
|
{
|
||||||
canerr("ERROR: Failed to allocate instance of mcp2515_can_s!\n");
|
canerr("ERROR: Failed to allocate instance of mcp2515_can_s!\n");
|
||||||
|
@ -2553,7 +2597,8 @@ FAR struct mcp2515_can_s *
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct can_dev_s *mcp2515_initialize(FAR struct mcp2515_can_s *mcp2515can)
|
FAR struct can_dev_s *mcp2515_initialize(
|
||||||
|
FAR struct mcp2515_can_s *mcp2515can)
|
||||||
{
|
{
|
||||||
FAR struct can_dev_s *dev;
|
FAR struct can_dev_s *dev;
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ struct mmcsd_state_s
|
||||||
|
|
||||||
/* Misc Helpers *************************************************************/
|
/* Misc Helpers *************************************************************/
|
||||||
|
|
||||||
static void mmcsd_takesem(FAR struct mmcsd_state_s *priv);
|
static int mmcsd_takesem(FAR struct mmcsd_state_s *priv);
|
||||||
|
|
||||||
#ifndef CONFIG_SDIO_MUXBUS
|
#ifndef CONFIG_SDIO_MUXBUS
|
||||||
# define mmcsd_givesem(p) nxsem_post(&priv->sem);
|
# define mmcsd_givesem(p) nxsem_post(&priv->sem);
|
||||||
|
@ -256,13 +256,19 @@ static const struct block_operations g_bops =
|
||||||
* Misc Helpers
|
* Misc Helpers
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void mmcsd_takesem(FAR struct mmcsd_state_s *priv)
|
static int mmcsd_takesem(FAR struct mmcsd_state_s *priv)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Take the semaphore, giving exclusive access to the driver (perhaps
|
/* Take the semaphore, giving exclusive access to the driver (perhaps
|
||||||
* waiting)
|
* waiting)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nxsem_wait_uninterruptible(&priv->sem);
|
ret = nxsem_wait_uninterruptible(&priv->sem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Lock the bus if mutually exclusive access to the SDIO bus is required
|
/* Lock the bus if mutually exclusive access to the SDIO bus is required
|
||||||
* on this platform.
|
* on this platform.
|
||||||
|
@ -271,6 +277,8 @@ static void mmcsd_takesem(FAR struct mmcsd_state_s *priv)
|
||||||
#ifdef CONFIG_SDIO_MUXBUS
|
#ifdef CONFIG_SDIO_MUXBUS
|
||||||
SDIO_LOCK(priv->dev, TRUE);
|
SDIO_LOCK(priv->dev, TRUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SDIO_MUXBUS
|
#ifdef CONFIG_SDIO_MUXBUS
|
||||||
|
@ -2144,6 +2152,7 @@ static ssize_t mmcsd_flush(FAR void *dev, FAR const uint8_t *buffer,
|
||||||
static int mmcsd_open(FAR struct inode *inode)
|
static int mmcsd_open(FAR struct inode *inode)
|
||||||
{
|
{
|
||||||
FAR struct mmcsd_state_s *priv;
|
FAR struct mmcsd_state_s *priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
finfo("Entry\n");
|
finfo("Entry\n");
|
||||||
DEBUGASSERT(inode && inode->i_private);
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
|
@ -2152,7 +2161,13 @@ static int mmcsd_open(FAR struct inode *inode)
|
||||||
/* Just increment the reference count on the driver */
|
/* Just increment the reference count on the driver */
|
||||||
|
|
||||||
DEBUGASSERT(priv->crefs < MAX_CREFS);
|
DEBUGASSERT(priv->crefs < MAX_CREFS);
|
||||||
mmcsd_takesem(priv);
|
|
||||||
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
priv->crefs++;
|
priv->crefs++;
|
||||||
mmcsd_givesem(priv);
|
mmcsd_givesem(priv);
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -2168,6 +2183,7 @@ static int mmcsd_open(FAR struct inode *inode)
|
||||||
static int mmcsd_close(FAR struct inode *inode)
|
static int mmcsd_close(FAR struct inode *inode)
|
||||||
{
|
{
|
||||||
FAR struct mmcsd_state_s *priv;
|
FAR struct mmcsd_state_s *priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
finfo("Entry\n");
|
finfo("Entry\n");
|
||||||
DEBUGASSERT(inode && inode->i_private);
|
DEBUGASSERT(inode && inode->i_private);
|
||||||
|
@ -2176,7 +2192,12 @@ static int mmcsd_close(FAR struct inode *inode)
|
||||||
/* Decrement the reference count on the block driver */
|
/* Decrement the reference count on the block driver */
|
||||||
|
|
||||||
DEBUGASSERT(priv->crefs > 0);
|
DEBUGASSERT(priv->crefs > 0);
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
priv->crefs--;
|
priv->crefs--;
|
||||||
mmcsd_givesem(priv);
|
mmcsd_givesem(priv);
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -2208,7 +2229,11 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
|
||||||
|
|
||||||
if (nsectors > 0)
|
if (nsectors > 0)
|
||||||
{
|
{
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ssize_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_DRVR_READAHEAD)
|
#if defined(CONFIG_DRVR_READAHEAD)
|
||||||
/* Get the data from the read-ahead buffer */
|
/* Get the data from the read-ahead buffer */
|
||||||
|
@ -2282,7 +2307,11 @@ static ssize_t mmcsd_write(FAR struct inode *inode,
|
||||||
finfo("sector: %lu nsectors: %u sectorsize: %u\n",
|
finfo("sector: %lu nsectors: %u sectorsize: %u\n",
|
||||||
(unsigned long)startsector, nsectors, priv->blocksize);
|
(unsigned long)startsector, nsectors, priv->blocksize);
|
||||||
|
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ssize_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_DRVR_WRITEBUFFER)
|
#if defined(CONFIG_DRVR_WRITEBUFFER)
|
||||||
/* Write the data to the write buffer */
|
/* Write the data to the write buffer */
|
||||||
|
@ -2349,7 +2378,12 @@ static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry)
|
||||||
/* Is there a (supported) card inserted in the slot? */
|
/* Is there a (supported) card inserted in the slot? */
|
||||||
|
|
||||||
priv = (FAR struct mmcsd_state_s *)inode->i_private;
|
priv = (FAR struct mmcsd_state_s *)inode->i_private;
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_EMPTY(priv))
|
if (IS_EMPTY(priv))
|
||||||
{
|
{
|
||||||
/* No.. return ENODEV */
|
/* No.. return ENODEV */
|
||||||
|
@ -2402,7 +2436,12 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||||
|
|
||||||
/* Process the IOCTL by command */
|
/* Process the IOCTL by command */
|
||||||
|
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case BIOC_PROBE: /* Check for media in the slot */
|
case BIOC_PROBE: /* Check for media in the slot */
|
||||||
|
@ -2467,13 +2506,19 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||||
static void mmcsd_mediachange(FAR void *arg)
|
static void mmcsd_mediachange(FAR void *arg)
|
||||||
{
|
{
|
||||||
FAR struct mmcsd_state_s *priv = (FAR struct mmcsd_state_s *)arg;
|
FAR struct mmcsd_state_s *priv = (FAR struct mmcsd_state_s *)arg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
finfo("arg: %p\n", arg);
|
finfo("arg: %p\n", arg);
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
|
|
||||||
/* Is there a card present in the slot? */
|
/* Is there a card present in the slot? */
|
||||||
|
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (SDIO_PRESENT(priv->dev))
|
if (SDIO_PRESENT(priv->dev))
|
||||||
{
|
{
|
||||||
/* No... process the card insertion. This could cause chaos if we
|
/* No... process the card insertion. This could cause chaos if we
|
||||||
|
@ -3518,7 +3563,11 @@ static int mmcsd_hwinitialize(FAR struct mmcsd_state_s *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mmcsd_takesem(priv);
|
ret = mmcsd_takesem(priv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the capabilities of the SDIO driver */
|
/* Get the capabilities of the SDIO driver */
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ struct mmcsd_cmdinfo_s
|
||||||
|
|
||||||
/* Misc *********************************************************************/
|
/* Misc *********************************************************************/
|
||||||
|
|
||||||
static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot);
|
static int mmcsd_semtake(FAR struct mmcsd_slot_s *slot);
|
||||||
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot);
|
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot);
|
||||||
|
|
||||||
/* Card SPI interface *******************************************************/
|
/* Card SPI interface *******************************************************/
|
||||||
|
@ -386,8 +386,20 @@ static const struct mmcsd_cmdinfo_s g_acmd41 =
|
||||||
* Name: mmcsd_semtake
|
* Name: mmcsd_semtake
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
|
static int mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Get exclusive access to the MMC/SD device (possibly unnecessary if
|
||||||
|
* SPI_LOCK is also implemented as a semaphore).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = nxsem_wait_uninterruptible(&slot->sem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get exclusive access to the SPI bus (if necessary) */
|
/* Get exclusive access to the SPI bus (if necessary) */
|
||||||
|
|
||||||
SPI_LOCK(slot->spi, true);
|
SPI_LOCK(slot->spi, true);
|
||||||
|
@ -401,11 +413,7 @@ static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
|
||||||
SPI_HWFEATURES(slot->spi, 0);
|
SPI_HWFEATURES(slot->spi, 0);
|
||||||
SPI_SETFREQUENCY(slot->spi, slot->spispeed);
|
SPI_SETFREQUENCY(slot->spi, slot->spispeed);
|
||||||
|
|
||||||
/* Get exclusive access to the MMC/SD device (possibly unnecessary if
|
return ret;
|
||||||
* SPI_LOCK is also implemented as a semaphore).
|
|
||||||
*/
|
|
||||||
|
|
||||||
nxsem_wait_uninterruptible(&slot->sem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -414,10 +422,6 @@ static void mmcsd_semtake(FAR struct mmcsd_slot_s *slot)
|
||||||
|
|
||||||
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot)
|
static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot)
|
||||||
{
|
{
|
||||||
/* Relinquish the lock on the MMC/SD device */
|
|
||||||
|
|
||||||
nxsem_post(&slot->sem);
|
|
||||||
|
|
||||||
/* Relinquish the lock on the SPI bus */
|
/* Relinquish the lock on the SPI bus */
|
||||||
|
|
||||||
/* The card may need up to 8 SCLK cycles to sample the CS status
|
/* The card may need up to 8 SCLK cycles to sample the CS status
|
||||||
|
@ -429,6 +433,10 @@ static void mmcsd_semgive(FAR struct mmcsd_slot_s *slot)
|
||||||
/* Relinquish exclusive access to the SPI bus */
|
/* Relinquish exclusive access to the SPI bus */
|
||||||
|
|
||||||
SPI_LOCK(slot->spi, false);
|
SPI_LOCK(slot->spi, false);
|
||||||
|
|
||||||
|
/* Relinquish the lock on the MMC/SD device */
|
||||||
|
|
||||||
|
nxsem_post(&slot->sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -1105,10 +1113,16 @@ static int mmcsd_open(FAR struct inode *inode)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ret = mmcsd_semtake(slot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Verify that an MMC/SD card has been inserted */
|
/* Verify that an MMC/SD card has been inserted */
|
||||||
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
mmcsd_semtake(slot);
|
|
||||||
if ((SPI_STATUS(spi, SPIDEV_MMCSD(0)) & SPI_STATUS_PRESENT) != 0)
|
if ((SPI_STATUS(spi, SPIDEV_MMCSD(0)) & SPI_STATUS_PRESENT) != 0)
|
||||||
{
|
{
|
||||||
/* Yes.. a card is present. Has it been initialized? */
|
/* Yes.. a card is present. Has it been initialized? */
|
||||||
|
@ -1164,8 +1178,9 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
|
||||||
FAR struct spi_dev_s *spi;
|
FAR struct spi_dev_s *spi;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
uint8_t response;
|
uint8_t response;
|
||||||
int i;
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
finfo("start_sector=%d nsectors=%d\n", start_sector, nsectors);
|
finfo("start_sector=%d nsectors=%d\n", start_sector, nsectors);
|
||||||
|
|
||||||
|
@ -1229,7 +1244,12 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
|
||||||
|
|
||||||
/* Select the slave */
|
/* Select the slave */
|
||||||
|
|
||||||
mmcsd_semtake(slot);
|
ret = mmcsd_semtake(slot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ssize_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
SPI_SELECT(spi, SPIDEV_MMCSD(0), true);
|
SPI_SELECT(spi, SPIDEV_MMCSD(0), true);
|
||||||
|
|
||||||
/* Single or multiple block read? */
|
/* Single or multiple block read? */
|
||||||
|
@ -1321,6 +1341,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode,
|
||||||
off_t offset;
|
off_t offset;
|
||||||
uint8_t response;
|
uint8_t response;
|
||||||
int i;
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
finfo("start_sector=%d nsectors=%d\n", start_sector, nsectors);
|
finfo("start_sector=%d nsectors=%d\n", start_sector, nsectors);
|
||||||
|
|
||||||
|
@ -1394,7 +1415,12 @@ static ssize_t mmcsd_write(FAR struct inode *inode,
|
||||||
|
|
||||||
/* Select the slave */
|
/* Select the slave */
|
||||||
|
|
||||||
mmcsd_semtake(slot);
|
ret = mmcsd_semtake(slot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ssize_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
SPI_SELECT(spi, SPIDEV_MMCSD(0), true);
|
SPI_SELECT(spi, SPIDEV_MMCSD(0), true);
|
||||||
|
|
||||||
/* Single or multiple block transfer? */
|
/* Single or multiple block transfer? */
|
||||||
|
@ -1536,7 +1562,12 @@ static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry)
|
||||||
|
|
||||||
/* Re-sample the CSD */
|
/* Re-sample the CSD */
|
||||||
|
|
||||||
mmcsd_semtake(slot);
|
ret = mmcsd_semtake(slot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
SPI_SELECT(spi, SPIDEV_MMCSD(0), true);
|
SPI_SELECT(spi, SPIDEV_MMCSD(0), true);
|
||||||
ret = mmcsd_getcsd(slot, csd);
|
ret = mmcsd_getcsd(slot, csd);
|
||||||
SPI_SELECT(spi, SPIDEV_MMCSD(0), false);
|
SPI_SELECT(spi, SPIDEV_MMCSD(0), false);
|
||||||
|
@ -1901,7 +1932,12 @@ static void mmcsd_mediachanged(void *arg)
|
||||||
|
|
||||||
/* Save the current slot state and reassess the new state */
|
/* Save the current slot state and reassess the new state */
|
||||||
|
|
||||||
mmcsd_semtake(slot);
|
ret = mmcsd_semtake(slot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
oldstate = slot->state;
|
oldstate = slot->state;
|
||||||
|
|
||||||
/* Check if media was removed or inserted */
|
/* Check if media was removed or inserted */
|
||||||
|
@ -2004,7 +2040,11 @@ int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi)
|
||||||
* configured for the MMC/SD card
|
* configured for the MMC/SD card
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mmcsd_semtake(slot);
|
ret = mmcsd_semtake(slot);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize for the media in the slot (if any) */
|
/* Initialize for the media in the slot (if any) */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue