Merged in raiden00/nuttx (pull request #476)

Master

* stm32_dac.c: fix compilation when DMA disabled for channel

* smps.h: update some comments

* smps.c: more sanity checks

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Mateusz Szafoni
2017-09-02 19:52:21 +00:00
committed by Gregory Nutt
parent 8ffb103adb
commit daac3bd7f8
3 changed files with 164 additions and 14 deletions
+3 -3
View File
@@ -493,13 +493,13 @@
/* DMA buffers default size */
#ifndef CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE
#if !defined(CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE) && defined(CONFIG_STM32_DAC1CH1_DMA)
# error "DAC1CH1 buffer size must be provided"
#endif
#ifndef CONFIG_STM32_DAC1CH2_DMA_BUFFER_SIZE
#if !defined(CONFIG_STM32_DAC1CH2_DMA_BUFFER_SIZE) && defined(CONFIG_STM32_DAC1CH2_DMA)
# error "DAC1CH2 buffer size must be provided"
#endif
#ifndef CONFIG_STM32_DAC2CH1_DMA_BUFFER_SIZE
#if !defined(CONFIG_STM32_DAC2CH1_DMA_BUFFER_SIZE) && defined(CONFIG_STM32_DAC2CH1_DMA)
# error "DAC2CH1 buffer size must be provided"
#endif
+145 -7
View File
@@ -229,18 +229,74 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct inode *inode = filep->f_inode;
FAR struct smps_dev_s *dev = inode->i_private;
FAR struct smps_s *smps = (FAR struct smps_s *)dev->priv;
int ret;
switch (cmd)
{
case PWRIOC_START:
{
/* TODO: sanity checking:
* - absolute limits
* - SMPS parameters
* - SMPS mode
/* Allow SMPS start only when some limits available
* and strucutre is locked.
* REVISIT: not sure if it is needed here
*/
if ((smps->limits.lock == false) ||
(smps->limits.v_in <= 0 && smps->limits.v_out <= 0 &&
smps->limits.i_in <= 0 && smps->limits.i_out <= 0 &&
smps->limits.p_in <= 0 && smps->limits.p_out <= 0 ))
{
pwrerr("ERROR: SMPS limits data must be set"
" and locked before SMPS start\n", ret);
ret = -EPERM;
goto errout;
}
/* Check SMPS mode */
if (smps->opmode == SMPS_OPMODE_INIT)
{
pwrerr("ERROR: SMPS operation mode not specified\n");
ret = -EPERM;
goto errout;
}
/* When constan current mode, then output current must be provided */
if (smps->opmode == SMPS_OPMODE_CC && smps->param.i_out <= 0)
{
pwrerr("ERROR: CC selected but i_out not specified!\n");
ret = -EPERM;
goto errout;
}
/* When constan voltage mode, then output voltage must be provided */
if (smps->opmode == SMPS_OPMODE_CV && smps->param.v_out <= 0)
{
pwrerr("ERROR: CV selected but v_out not specified!\n");
ret = -EPERM;
goto errout;
}
/* When constan power mode, then output power must be provided */
if (smps->opmode == SMPS_OPMODE_CP && smps->param.p_out <= 0)
{
pwrerr("ERROR: CP selected but p_out not specified!\n");
ret = -EPERM;
goto errout;
}
/* REVISIT: something else ?? */
/* Finally, call start from lower-half driver */
ret = dev->ops->start(dev);
if (ret != OK)
{
@@ -276,7 +332,15 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
FAR struct smps_limits_s *limits =
(FAR struct smps_limits_s *)((uintptr_t)arg);
/* TODO: lock mechanism */
if (smps->limits.lock == true)
{
pwrerr("ERROR: SMPS limits locked!\n");
ret = -EPERM;
goto errout;
}
/* NOTE: this call must set the smps_limits_s structure */
ret = dev->ops->limits_set(dev, limits);
if (ret != OK)
@@ -340,7 +404,58 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
FAR struct smps_params_s *params =
(FAR struct smps_params_s *)((uintptr_t)arg);
/* TODO: lock mechanism */
if (smps->param.lock == true)
{
pwrerr("ERROR: SMPS params locked!\n");
ret = -EPERM;
goto errout;
}
if ((smps->limits.lock == false) ||
(smps->limits.v_in <= 0 && smps->limits.v_out <= 0 &&
smps->limits.i_in <= 0 && smps->limits.i_out <= 0 &&
smps->limits.p_in <= 0 && smps->limits.p_out <= 0 ))
{
pwrerr("ERROR: limits must be set prior to params!\n");
ret = -EPERM;
goto errout;
}
/* Check output voltage configuration */
if (smps->limits.v_out > 0 && params->v_out > smps->limits.v_out)
{
pwrerr("ERROR: params->v_out > limits.v_out: %d > %d\n",
params->v_out, smps->limits.v_out);
ret = -EPERM;
goto errout;
}
/* Check output current configuration */
if (smps->limits.i_out > 0 && params->i_out > smps->limits.i_out)
{
pwrerr("ERROR: params->i_out > limits.i_out: %d > %d\n",
params->i_out, smps->limits.i_out);
ret = -EPERM;
goto errout;
}
/* Check output power configuration */
if (smps->limits.p_out > 0 && params->p_out > smps->limits.p_out)
{
pwrerr("ERROR: params->p_out > limits.p_out: %d > %d\n",
params->p_out, smps->limits.p_out);
ret = -EPERM;
goto errout;
}
/* TODO: limits */
ret = dev->ops->params_set(dev, params);
@@ -359,6 +474,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
}
errout:
return ret;
}
@@ -374,6 +490,28 @@ int smps_register(FAR const char *path, FAR struct smps_dev_s *dev, FAR void *lo
{
int ret;
DEBUGASSERT(path != NULL && dev != NULL && lower != NULL);
DEBUGASSERT(dev->ops != NULL);
/* For safety reason, when some necessary low-level logic is not provided,
* system should fail before low-level hardware initialization, so:
* - all ops are checked here, before character driver registration
* - all ops must be provided, even if not used
*/
DEBUGASSERT(dev->ops->setup != NULL);
DEBUGASSERT(dev->ops->shutdown != NULL);
DEBUGASSERT(dev->ops->stop != NULL);
DEBUGASSERT(dev->ops->start != NULL);
DEBUGASSERT(dev->ops->params_set != NULL);
DEBUGASSERT(dev->ops->mode_set != NULL);
DEBUGASSERT(dev->ops->limits_set != NULL);
DEBUGASSERT(dev->ops->fault_set != NULL);
DEBUGASSERT(dev->ops->state_get != NULL);
DEBUGASSERT(dev->ops->fault_get != NULL);
DEBUGASSERT(dev->ops->fault_clean != NULL);
DEBUGASSERT(dev->ops->ioctl != NULL);
/* Initialize the HRTIM device structure */
dev->ocount = 0;
@@ -388,7 +526,7 @@ int smps_register(FAR const char *path, FAR struct smps_dev_s *dev, FAR void *lo
/* Register the SMPS character driver */
ret = register_driver(path, &smps_fops, 0444, dev);
ret = register_driver(path, &smps_fops, 0444, dev);
if (ret < 0)
{
sem_destroy(&dev->closesem);
+16 -4
View File
@@ -47,6 +47,10 @@
* - analog peripherals configuration such as ADC, DAC and comparators,
* - control algorithm for SMPS action (eg. PID loop)
*
* NOTE: This driver can also be used as "upper half" driver for programmable
* digital PWM controllers (eg. ADP1046), but it is not the main goal of
* current development.
*
*/
/****************************************************************************
@@ -146,11 +150,16 @@ struct smps_state_s
struct smps_feedback_s fb; /* Feedback from SMPS */
};
/* SMPS absolute limits. Exceeding this limits should cause critical error */
/* SMPS absolute limits. Exceeding this limits should cause critical error.
* This structure must be configured before SMPS params_set call.
* When limit is set to 0 then it is ignored.
*/
struct smps_limits_s
{
bool lock; /* */
bool lock; /* This bit must be set after
* limits configuration.
*/
float v_in; /* Maximum input voltage */
float v_out; /* Maximum output voltage */
float i_in; /* Maximum input current */
@@ -163,7 +172,10 @@ struct smps_limits_s
struct smps_params_s
{
bool lock;
bool lock; /* Lock this structure. Set this bit
* if there is no need to change SMPS
* parameter during run-time.
*/
float v_out; /* */
float i_out; /* */
float p_out; /* */
@@ -175,7 +187,7 @@ struct smps_s
{
uint8_t opmode; /* SMPS operation mode */
uint8_t opflags; /* SMPS operation flags */
const struct smps_limits_s limits; /* SMPS absolute limits */
struct smps_limits_s limits; /* SMPS absolute limits */
struct smps_params_s param; /* SMPS settings */
struct smps_state_s state; /* SMPS state */
};