Improved DAC driver, updated STM32 DACv1.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16315 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
f77d00b0c9
commit
665b0d48b4
|
@ -40,11 +40,14 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @brief Enables synchronous APIs.
|
* @brief Support for thread synchronization API.
|
||||||
* @note Disabling this option saves both code and data space.
|
|
||||||
*/
|
*/
|
||||||
|
#if !defined(DAC_USE_SYNCHRONIZATION) || defined(__DOXYGEN__)
|
||||||
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
||||||
#define DAC_USE_WAIT TRUE
|
#define DAC_USE_SYNCHRONIZATION FALSE
|
||||||
|
#else
|
||||||
|
#define DAC_USE_SYNCHRONIZATION DAC_USE_WAIT
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,12 +166,12 @@ struct hal_dac_driver {
|
||||||
* @brief Current configuration data.
|
* @brief Current configuration data.
|
||||||
*/
|
*/
|
||||||
const DACConfig *config;
|
const DACConfig *config;
|
||||||
#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
#if (DAC_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Waiting thread.
|
* @brief Waiting thread.
|
||||||
*/
|
*/
|
||||||
thread_reference_t thread;
|
thread_reference_t thread;
|
||||||
#endif /* DAC_USE_WAIT */
|
#endif /* DAC_USE_SYNCHRONIZATION */
|
||||||
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Mutex protecting the bus.
|
* @brief Mutex protecting the bus.
|
||||||
|
@ -205,7 +208,7 @@ struct hal_dac_driver {
|
||||||
*/
|
*/
|
||||||
#define dacIsBufferComplete(dacp) ((bool)((dacp)->state == DAC_COMPLETE))
|
#define dacIsBufferComplete(dacp) ((bool)((dacp)->state == DAC_COMPLETE))
|
||||||
|
|
||||||
#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
#if (DAC_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Waits for operation completion.
|
* @brief Waits for operation completion.
|
||||||
* @details This function waits for the driver to complete the current
|
* @details This function waits for the driver to complete the current
|
||||||
|
@ -264,13 +267,13 @@ struct hal_dac_driver {
|
||||||
osalSysUnlockFromISR(); \
|
osalSysUnlockFromISR(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !DAC_USE_WAIT */
|
#else /* !DAC_USE_SYNCHRONIZATION */
|
||||||
#define _dac_wait_s(dacp)
|
#define _dac_wait_s(dacp)
|
||||||
#define _dac_reset_i(dacp)
|
#define _dac_reset_i(dacp)
|
||||||
#define _dac_reset_s(dacp)
|
#define _dac_reset_s(dacp)
|
||||||
#define _dac_wakeup_isr(dacp)
|
#define _dac_wakeup_isr(dacp)
|
||||||
#define _dac_timeout_isr(dacp)
|
#define _dac_timeout_isr(dacp)
|
||||||
#endif /* !DAC_USE_WAIT */
|
#endif /* !DAC_USE_SYNCHRONIZATION */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Common ISR code, half buffer event.
|
* @brief Common ISR code, half buffer event.
|
||||||
|
@ -310,13 +313,14 @@ struct hal_dac_driver {
|
||||||
if ((dacp)->state == DAC_COMPLETE) \
|
if ((dacp)->state == DAC_COMPLETE) \
|
||||||
(dacp)->state = DAC_ACTIVE; \
|
(dacp)->state = DAC_ACTIVE; \
|
||||||
} \
|
} \
|
||||||
|
_dac_wakeup_isr(dacp); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Common ISR code, error event.
|
* @brief Common ISR code, error event.
|
||||||
* @details This code handles the portable part of the ISR code:
|
* @details This code handles the portable part of the ISR code:
|
||||||
* - Callback invocation.
|
* - Callback invocation.
|
||||||
* - Waiting thread timeout signaling, if any.
|
* - Waiting thread timeout signalling, if any.
|
||||||
* - Driver state transitions.
|
* - Driver state transitions.
|
||||||
* .
|
* .
|
||||||
* @note This macro is meant to be used in the low level drivers
|
* @note This macro is meant to be used in the low level drivers
|
||||||
|
@ -360,10 +364,12 @@ extern "C" {
|
||||||
dacsample_t *samples, size_t depth);
|
dacsample_t *samples, size_t depth);
|
||||||
void dacStopConversion(DACDriver *dacp);
|
void dacStopConversion(DACDriver *dacp);
|
||||||
void dacStopConversionI(DACDriver *dacp);
|
void dacStopConversionI(DACDriver *dacp);
|
||||||
#if DAC_USE_WAIT
|
#if DAC_USE_SYNCHRONIZATION
|
||||||
msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp,
|
msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||||
dacsample_t *samples, size_t depth);
|
dacsample_t *samples, size_t depth);
|
||||||
#endif
|
msg_t dacSynchronizeS(DACDriver *dacp, sysinterval_t timeout);
|
||||||
|
msg_t dacSynchronize(DACDriver *dacp, sysinterval_t timeout);
|
||||||
|
#endif /* DAC_USE_SYNCHRONIZATION */
|
||||||
#if DAC_USE_MUTUAL_EXCLUSION
|
#if DAC_USE_MUTUAL_EXCLUSION
|
||||||
void dacAcquireBus(DACDriver *dacp);
|
void dacAcquireBus(DACDriver *dacp);
|
||||||
void dacReleaseBus(DACDriver *dacp);
|
void dacReleaseBus(DACDriver *dacp);
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
STM32_DAC4_CH2_DMA_CHN)
|
STM32_DAC4_CH2_DMA_CHN)
|
||||||
|
|
||||||
#define CHANNEL_DATA_OFFSET 3U
|
#define CHANNEL_DATA_OFFSET 3U
|
||||||
|
#define CHANNEL_REGISTER_SHIFT 16U
|
||||||
|
#define CHANNEL_REGISTER_MASK1 0xFFFF0000U
|
||||||
|
#define CHANNEL_REGISTER_MASK2 0x0000FFFFU
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver exported variables. */
|
/* Driver exported variables. */
|
||||||
|
@ -122,7 +125,7 @@ static const dacparams_t dac1_ch1_params = {
|
||||||
.dac = DAC1,
|
.dac = DAC1,
|
||||||
.dataoffset = 0U,
|
.dataoffset = 0U,
|
||||||
.regshift = 0U,
|
.regshift = 0U,
|
||||||
.regmask = 0xFFFF0000U,
|
.regmask = CHANNEL_REGISTER_MASK1,
|
||||||
.dmastream = STM32_DAC_DAC1_CH1_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC1_CH1_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC1_CH1,
|
.peripheral = STM32_DMAMUX1_DAC1_CH1,
|
||||||
|
@ -140,8 +143,8 @@ static const dacparams_t dac1_ch1_params = {
|
||||||
static const dacparams_t dac1_ch2_params = {
|
static const dacparams_t dac1_ch2_params = {
|
||||||
.dac = DAC1,
|
.dac = DAC1,
|
||||||
.dataoffset = CHANNEL_DATA_OFFSET,
|
.dataoffset = CHANNEL_DATA_OFFSET,
|
||||||
.regshift = 16U,
|
.regshift = CHANNEL_REGISTER_SHIFT,
|
||||||
.regmask = 0x0000FFFFU,
|
.regmask = CHANNEL_REGISTER_MASK2,
|
||||||
.dmastream = STM32_DAC_DAC1_CH2_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC1_CH2_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC1_CH2,
|
.peripheral = STM32_DMAMUX1_DAC1_CH2,
|
||||||
|
@ -160,7 +163,7 @@ static const dacparams_t dac2_ch1_params = {
|
||||||
.dac = DAC2,
|
.dac = DAC2,
|
||||||
.dataoffset = 0U,
|
.dataoffset = 0U,
|
||||||
.regshift = 0U,
|
.regshift = 0U,
|
||||||
.regmask = 0xFFFF0000U,
|
.regmask = CHANNEL_REGISTER_MASK1,
|
||||||
.dmastream = STM32_DAC_DAC2_CH1_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC2_CH1_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC2_CH1,
|
.peripheral = STM32_DMAMUX1_DAC2_CH1,
|
||||||
|
@ -178,8 +181,8 @@ static const dacparams_t dac2_ch1_params = {
|
||||||
static const dacparams_t dac2_ch2_params = {
|
static const dacparams_t dac2_ch2_params = {
|
||||||
.dac = DAC2,
|
.dac = DAC2,
|
||||||
.dataoffset = CHANNEL_DATA_OFFSET,
|
.dataoffset = CHANNEL_DATA_OFFSET,
|
||||||
.regshift = 16U,
|
.regshift = CHANNEL_REGISTER_SHIFT,
|
||||||
.regmask = 0x0000FFFFU,
|
.regmask = CHANNEL_REGISTER_MASK2,
|
||||||
.dmastream = STM32_DAC_DAC2_CH2_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC2_CH2_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC2_CH2,
|
.peripheral = STM32_DMAMUX1_DAC2_CH2,
|
||||||
|
@ -198,7 +201,7 @@ static const dacparams_t dac3_ch1_params = {
|
||||||
.dac = DAC3,
|
.dac = DAC3,
|
||||||
.dataoffset = 0U,
|
.dataoffset = 0U,
|
||||||
.regshift = 0U,
|
.regshift = 0U,
|
||||||
.regmask = 0xFFFF0000U,
|
.regmask = CHANNEL_REGISTER_MASK1,
|
||||||
.dmastream = STM32_DAC_DAC3_CH1_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC3_CH1_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC3_CH1,
|
.peripheral = STM32_DMAMUX1_DAC3_CH1,
|
||||||
|
@ -216,8 +219,8 @@ static const dacparams_t dac3_ch1_params = {
|
||||||
static const dacparams_t dac3_ch2_params = {
|
static const dacparams_t dac3_ch2_params = {
|
||||||
.dac = DAC3,
|
.dac = DAC3,
|
||||||
.dataoffset = CHANNEL_DATA_OFFSET,
|
.dataoffset = CHANNEL_DATA_OFFSET,
|
||||||
.regshift = 16U,
|
.regshift = CHANNEL_REGISTER_SHIFT,
|
||||||
.regmask = 0x0000FFFFU,
|
.regmask = CHANNEL_REGISTER_MASK2,
|
||||||
.dmastream = STM32_DAC_DAC3_CH2_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC3_CH2_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC3_CH2,
|
.peripheral = STM32_DMAMUX1_DAC3_CH2,
|
||||||
|
@ -236,7 +239,7 @@ static const dacparams_t dac4_ch1_params = {
|
||||||
.dac = DAC4,
|
.dac = DAC4,
|
||||||
.dataoffset = 0U,
|
.dataoffset = 0U,
|
||||||
.regshift = 0U,
|
.regshift = 0U,
|
||||||
.regmask = 0xFFFF0000U,
|
.regmask = CHANNEL_REGISTER_MASK1,
|
||||||
.dmastream = STM32_DAC_DAC4_CH1_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC4_CH1_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC4_CH1,
|
.peripheral = STM32_DMAMUX1_DAC4_CH1,
|
||||||
|
@ -254,8 +257,8 @@ static const dacparams_t dac4_ch1_params = {
|
||||||
static const dacparams_t dac4_ch2_params = {
|
static const dacparams_t dac4_ch2_params = {
|
||||||
.dac = DAC4,
|
.dac = DAC4,
|
||||||
.dataoffset = CHANNEL_DATA_OFFSET,
|
.dataoffset = CHANNEL_DATA_OFFSET,
|
||||||
.regshift = 16U,
|
.regshift = CHANNEL_REGISTER_SHIFT,
|
||||||
.regmask = 0x0000FFFFU,
|
.regmask = CHANNEL_REGISTER_MASK2,
|
||||||
.dmastream = STM32_DAC_DAC4_CH2_DMA_STREAM,
|
.dmastream = STM32_DAC_DAC4_CH2_DMA_STREAM,
|
||||||
#if STM32_DMA_SUPPORTS_DMAMUX
|
#if STM32_DMA_SUPPORTS_DMAMUX
|
||||||
.peripheral = STM32_DMAMUX1_DAC4_CH2,
|
.peripheral = STM32_DMAMUX1_DAC4_CH2,
|
||||||
|
@ -429,30 +432,41 @@ void dac_lld_start(DACDriver *dacp) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Enabling DAC in SW triggering mode initially, initializing data to
|
|
||||||
zero.*/
|
|
||||||
#if STM32_DAC_DUAL_MODE == FALSE
|
#if STM32_DAC_DUAL_MODE == FALSE
|
||||||
|
/* Enabling DAC in SW triggering mode initially, initializing data to
|
||||||
|
configuration default.*/
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t reg;
|
||||||
|
|
||||||
cr = dacp->params->dac->CR;
|
/* Operating in SINGLE mode with one channel to set. Set registers for
|
||||||
cr &= dacp->params->regmask;
|
specified channel from configuration. Lower half word of
|
||||||
cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
|
configuration specifies configuration for any channel.*/
|
||||||
dacp->params->dac->CR = cr;
|
reg = dacp->params->dac->MCR & dacp->params->regmask;
|
||||||
dac_lld_put_channel(dacp, channel, dacp->config->init);
|
dacp->params->dac->MCR = reg |
|
||||||
|
((dacp->config->mcr & ~dacp->params->regmask) << dacp->params->regshift);
|
||||||
|
|
||||||
|
/* Enable and initialise the channel.*/
|
||||||
|
reg = dacp->params->dac->CR;
|
||||||
|
reg &= dacp->params->regmask;
|
||||||
|
reg |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
|
||||||
|
dacp->params->dac->CR = reg;
|
||||||
|
dac_lld_put_channel(dacp, channel, (dacsample_t)dacp->config->init);
|
||||||
}
|
}
|
||||||
#else
|
#else /* STM32_DAC_DUAL_MODE != FALSE */
|
||||||
if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) ||
|
/* Operating in DUAL mode with two channels to setup. Set registers for
|
||||||
(dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) ||
|
both channels from configuration. Lower and upper half words specify
|
||||||
(dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) {
|
configuration for channels CH1 & CH2 respectively.*/
|
||||||
dacp->params->dac->CR = DAC_CR_EN2 | (dacp->config->cr << 16) | DAC_CR_EN1 | dacp->config->cr;
|
(void)channel;
|
||||||
dac_lld_put_channel(dacp, 1U, dacp->config->init);
|
dacp->params->dac->MCR = dacp->config->mcr;
|
||||||
}
|
|
||||||
else {
|
/* Enable and initialise both CH1 and CH2. Mask out DMA and calibrate.*/
|
||||||
dacp->params->dac->CR = DAC_CR_EN1 | dacp->config->cr;
|
reg = dacp->config->cr;
|
||||||
}
|
reg &= ~(DAC_CR_DMAEN1 | DAC_CR_DMAEN2 | DAC_CR_CEN1 | DAC_CR_CEN2);
|
||||||
dac_lld_put_channel(dacp, channel, dacp->config->init);
|
dacp->params->dac->CR = DAC_CR_EN2 | DAC_CR_EN1 | reg;
|
||||||
#endif
|
dac_lld_put_channel(dacp, 0U, (dacsample_t)dacp->config->init);
|
||||||
|
dac_lld_put_channel(dacp, 1U, (dacsample_t)(dacp->config->init >>
|
||||||
|
(sizeof(dacsample_t) * 8)));
|
||||||
|
#endif /* STM32_DAC_DUAL_MODE == FALSE */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,6 +569,8 @@ void dac_lld_stop(DACDriver *dacp) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Outputs a value directly on a DAC channel.
|
* @brief Outputs a value directly on a DAC channel.
|
||||||
|
* @note While a group is active in DUAL mode on CH1 only then CH2
|
||||||
|
* is available for normal output (put) operations.
|
||||||
*
|
*
|
||||||
* @param[in] dacp pointer to the @p DACDriver object
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
* @param[in] channel DAC channel number
|
* @param[in] channel DAC channel number
|
||||||
|
@ -566,6 +582,13 @@ void dac_lld_put_channel(DACDriver *dacp,
|
||||||
dacchannel_t channel,
|
dacchannel_t channel,
|
||||||
dacsample_t sample) {
|
dacsample_t sample) {
|
||||||
|
|
||||||
|
#if STM32_DAC_DUAL_MODE
|
||||||
|
if (dacp->grpp != NULL) {
|
||||||
|
osalDbgAssert(dacp->grpp->num_channels == 1 && channel == 1,
|
||||||
|
"channel busy");
|
||||||
|
}
|
||||||
|
#endif /* STM32_DAC_DUAL_MODE */
|
||||||
|
|
||||||
switch (dacp->config->datamode) {
|
switch (dacp->config->datamode) {
|
||||||
case DAC_DHRM_12BIT_RIGHT:
|
case DAC_DHRM_12BIT_RIGHT:
|
||||||
#if STM32_DAC_DUAL_MODE
|
#if STM32_DAC_DUAL_MODE
|
||||||
|
@ -638,6 +661,11 @@ void dac_lld_put_channel(DACDriver *dacp,
|
||||||
* as a single 16 bits sample and packed into a single dacsample_t
|
* as a single 16 bits sample and packed into a single dacsample_t
|
||||||
* element. The num_channels must be set to one in the group
|
* element. The num_channels must be set to one in the group
|
||||||
* conversion configuration structure.
|
* conversion configuration structure.
|
||||||
|
* @note If using DUAL mode with a single channel conversion then CH2
|
||||||
|
* is enabled for manual (put_channel) for non DMA triggered use. The
|
||||||
|
* the data format for put operations is specified in the upper half
|
||||||
|
* word of the 'datamode' field. The CR setting is in the upper half
|
||||||
|
* word of the 'cr' field of the configuration.
|
||||||
*
|
*
|
||||||
* @param[in] dacp pointer to the @p DACDriver object
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
*
|
*
|
||||||
|
@ -744,15 +772,18 @@ void dac_lld_start_conversion(DACDriver *dacp) {
|
||||||
STM32_DMA_CR_HTIE | STM32_DMA_CR_TCIE);
|
STM32_DMA_CR_HTIE | STM32_DMA_CR_TCIE);
|
||||||
dmaStreamEnable(dacp->dma);
|
dmaStreamEnable(dacp->dma);
|
||||||
|
|
||||||
/* DAC configuration.*/
|
/* DAC configuration. Mask out DMA and calibration.*/
|
||||||
cr = dacp->params->dac->CR;
|
cr = dacp->params->dac->CR;
|
||||||
|
cr &= ~(DAC_CR_CEN1 | DAC_CR_CEN2 | DAC_CR_DMAEN2);
|
||||||
#if STM32_DAC_DUAL_MODE == FALSE
|
#if STM32_DAC_DUAL_MODE == FALSE
|
||||||
|
/* Start the DMA on the single channel.*/
|
||||||
cr &= dacp->params->regmask;
|
cr &= dacp->params->regmask;
|
||||||
cr |= (DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
|
cr |= (DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) |
|
||||||
|
DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
|
||||||
#else
|
#else
|
||||||
cr = DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr
|
/* Enable the DMA operation on CH1.*/
|
||||||
| (dacp->grpp->trigger << DAC_CR_TSEL2_Pos) | DAC_CR_TEN2 | DAC_CR_EN2 | (dacp->config->cr << 16);
|
cr = DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) |
|
||||||
|
DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dacp->params->dac->CR = cr;
|
dacp->params->dac->CR = cr;
|
||||||
|
@ -760,9 +791,9 @@ void dac_lld_start_conversion(DACDriver *dacp) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stops an ongoing conversion.
|
* @brief Stops an ongoing conversion.
|
||||||
* @details This function stops the currently ongoing conversion and returns
|
* @details This function stops the currently ongoing conversion. The
|
||||||
* the driver in the @p DAC_READY state. If there was no conversion
|
* configuration is restored to start condition. The DOR values
|
||||||
* being processed then the function does nothing.
|
* are not updated.
|
||||||
*
|
*
|
||||||
* @param[in] dacp pointer to the @p DACDriver object
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
*
|
*
|
||||||
|
@ -776,21 +807,19 @@ void dac_lld_stop_conversion(DACDriver *dacp) {
|
||||||
dmaStreamFreeI(dacp->dma);
|
dmaStreamFreeI(dacp->dma);
|
||||||
dacp->dma = NULL;
|
dacp->dma = NULL;
|
||||||
|
|
||||||
|
/* Restore start configuration but leave DORx at current values.*/
|
||||||
cr = dacp->params->dac->CR;
|
cr = dacp->params->dac->CR;
|
||||||
|
|
||||||
#if STM32_DAC_DUAL_MODE == FALSE
|
#if STM32_DAC_DUAL_MODE == FALSE
|
||||||
|
uint32_t mcr;
|
||||||
|
mcr = dacp->params->dac->MCR & dacp->params->regmask;
|
||||||
|
dacp->params->dac->MCR = mcr |
|
||||||
|
((dacp->config->mcr & dacp->params->regmask) << dacp->params->regshift);
|
||||||
cr &= dacp->params->regmask;
|
cr &= dacp->params->regmask;
|
||||||
cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
|
cr |= (DAC_CR_EN1 | (dacp->config->cr & ~dacp->params->regmask)) <<
|
||||||
|
dacp->params->regshift;
|
||||||
#else
|
#else
|
||||||
if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) ||
|
dacp->params->dac->MCR = dacp->config->mcr;
|
||||||
(dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) ||
|
cr = dacp->config->cr | DAC_CR_EN1 | DAC_CR_EN2;
|
||||||
(dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) {
|
|
||||||
cr = DAC_CR_EN2 | (dacp->config->cr << 16) |
|
|
||||||
DAC_CR_EN1 | dacp->config->cr;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cr = DAC_CR_EN1 | dacp->config->cr;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dacp->params->dac->CR = cr;
|
dacp->params->dac->CR = cr;
|
||||||
|
|
|
@ -31,14 +31,6 @@
|
||||||
/* Driver constants. */
|
/* Driver constants. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @name DAC trigger modes
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
#define DAC_TRG_MASK 7U
|
|
||||||
#define DAC_TRG(n) (n)
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver pre-compile time settings. */
|
/* Driver pre-compile time settings. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -487,7 +479,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief Max DAC channels.
|
* @brief Max DAC channels.
|
||||||
*/
|
*/
|
||||||
#if STM32_DAC_DUAL_MODE == FALSE
|
#if STM32_DAC_DUAL_MODE == TRUE
|
||||||
#define DAC_MAX_CHANNELS 2
|
#define DAC_MAX_CHANNELS 2
|
||||||
#else
|
#else
|
||||||
#define DAC_MAX_CHANNELS 1
|
#define DAC_MAX_CHANNELS 1
|
||||||
|
@ -571,10 +563,6 @@ typedef enum {
|
||||||
#endif
|
#endif
|
||||||
} dacdhrmode_t;
|
} dacdhrmode_t;
|
||||||
|
|
||||||
/*===========================================================================*/
|
|
||||||
/* Driver macros. */
|
|
||||||
/*===========================================================================*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Low level fields of the DAC driver structure.
|
* @brief Low level fields of the DAC driver structure.
|
||||||
*/
|
*/
|
||||||
|
@ -586,14 +574,18 @@ typedef enum {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Low level fields of the DAC configuration structure.
|
* @brief Low level fields of the DAC configuration structure.
|
||||||
|
* @note In DUAL mode init, cr and mcr fields hold CH1 settings in their
|
||||||
|
* lower 16 bits and CH2 settings in the upper 16 bits.
|
||||||
*/
|
*/
|
||||||
#define dac_lld_config_fields \
|
#define dac_lld_config_fields \
|
||||||
/* Initial output on DAC channels.*/ \
|
/* Initial output on DAC channel.*/ \
|
||||||
dacsample_t init; \
|
uint32_t init; \
|
||||||
/* DAC data holding register mode.*/ \
|
/* DAC data holding register mode.*/ \
|
||||||
dacdhrmode_t datamode; \
|
dacdhrmode_t datamode; \
|
||||||
/* DAC control register lower 16 bits.*/ \
|
/* DAC control register.*/ \
|
||||||
uint32_t cr
|
uint32_t cr; \
|
||||||
|
/* DAC mode control register.*/ \
|
||||||
|
uint32_t mcr
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Low level fields of the DAC group configuration structure.
|
* @brief Low level fields of the DAC group configuration structure.
|
||||||
|
@ -604,6 +596,23 @@ typedef enum {
|
||||||
initialization. All other fields are handled internally.*/ \
|
initialization. All other fields are handled internally.*/ \
|
||||||
uint32_t trigger
|
uint32_t trigger
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver macros. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name DAC trigger modes
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define DAC_TRG_MASK 7U
|
||||||
|
#define DAC_TRG(n) (n)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shift of initialisation value for channel 2 in dual mode.
|
||||||
|
*/
|
||||||
|
#define DAC_VALUE_DUAL(n) ((n) << (sizeof(dacsample_t) * 8))
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
|
@ -158,7 +158,8 @@ void dacStop(DACDriver *dacp) {
|
||||||
void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) {
|
void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) {
|
||||||
|
|
||||||
osalDbgCheck(channel < (dacchannel_t)DAC_MAX_CHANNELS);
|
osalDbgCheck(channel < (dacchannel_t)DAC_MAX_CHANNELS);
|
||||||
osalDbgAssert(dacp->state == DAC_READY, "invalid state");
|
osalDbgAssert(dacp->state == DAC_READY || dacp->state == DAC_ACTIVE,
|
||||||
|
"invalid state");
|
||||||
|
|
||||||
dac_lld_put_channel(dacp, channel, sample);
|
dac_lld_put_channel(dacp, channel, sample);
|
||||||
}
|
}
|
||||||
|
@ -193,10 +194,10 @@ void dacStartConversion(DACDriver *dacp,
|
||||||
* @brief Starts a DAC conversion.
|
* @brief Starts a DAC conversion.
|
||||||
* @details Starts an asynchronous conversion operation.
|
* @details Starts an asynchronous conversion operation.
|
||||||
* @post The callbacks associated to the conversion group will be invoked
|
* @post The callbacks associated to the conversion group will be invoked
|
||||||
* on buffer fill and error events.
|
* on buffer complete and error events.
|
||||||
* @note The buffer is organized as a matrix of M*N elements where M is the
|
* @note The buffer is organized as a matrix of M*N elements where M is the
|
||||||
* channels number configured into the conversion group and N is the
|
* channels number configured into the conversion group and N is the
|
||||||
* buffer depth. The samples are sequentially written into the buffer
|
* buffer depth. The samples are sequentially organised in the buffer
|
||||||
* with no gaps.
|
* with no gaps.
|
||||||
*
|
*
|
||||||
* @param[in] dacp pointer to the @p DACDriver object
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
@ -284,25 +285,25 @@ void dacStopConversionI(DACDriver *dacp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
#if (DAC_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Performs a DAC conversion.
|
* @brief Performs a DAC conversion.
|
||||||
* @details Performs a synchronous conversion operation.
|
* @details Performs a synchronous conversion operation.
|
||||||
* @note The buffer is organized as a matrix of M*N elements where M is the
|
* @note The buffer is organized as a matrix of M*N elements where M is the
|
||||||
* channels number configured into the conversion group and N is the
|
* channels number configured into the conversion group and N is the
|
||||||
* buffer depth. The samples are sequentially written into the buffer
|
* buffer depth. The samples are sequentially organised in the buffer
|
||||||
* with no gaps.
|
* with no gaps.
|
||||||
*
|
*
|
||||||
* @param[in] dacp pointer to the @p DACDriver object
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
* @param[in] grpp pointer to a @p DACConversionGroup object
|
* @param[in] grpp pointer to a @p DACConversionGroup object
|
||||||
* @param[out] samples pointer to the samples buffer
|
* @param[in] samples pointer to the samples buffer
|
||||||
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
||||||
* must be one or an even number.
|
* must be one or an even number.
|
||||||
|
*
|
||||||
* @return The operation result.
|
* @return The operation result.
|
||||||
* @retval MSG_OK Conversion finished.
|
* @retval MSG_OK Conversion finished.
|
||||||
* @retval MSG_RESET The conversion has been stopped using
|
* @retval MSG_RESET The conversion has been stopped using
|
||||||
* @p acdStopConversion() or @p acdStopConversionI(),
|
* @p dacStopConversion() or @p dacStopConversionI().
|
||||||
* the result buffer may contain incorrect data.
|
|
||||||
* @retval MSG_TIMEOUT The conversion has been stopped because an hardware
|
* @retval MSG_TIMEOUT The conversion has been stopped because an hardware
|
||||||
* error.
|
* error.
|
||||||
*
|
*
|
||||||
|
@ -322,7 +323,63 @@ msg_t dacConvert(DACDriver *dacp,
|
||||||
osalSysUnlock();
|
osalSysUnlock();
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
#endif /* DAC_USE_WAIT == TRUE */
|
|
||||||
|
/**
|
||||||
|
* @brief Synchronize to a conversion completion.
|
||||||
|
* @note This function can only be called by a single thread at time.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
* @param[in] timeout wait timeout
|
||||||
|
*
|
||||||
|
* @return The wait result.
|
||||||
|
* @retval MSG_OK if operation completed without errors.
|
||||||
|
* @retval MSG_TIMEOUT if synchronization request timed out.
|
||||||
|
* @retval MSG_RESET if the conversion has been stopped.
|
||||||
|
*
|
||||||
|
* @sclass
|
||||||
|
*/
|
||||||
|
msg_t dacSynchronizeS(DACDriver *dacp, sysinterval_t timeout) {
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
osalDbgCheckClassS();
|
||||||
|
osalDbgCheck(dacp != NULL);
|
||||||
|
osalDbgAssert((dacp->state == DAC_ACTIVE) || (dacp->state == DAC_READY),
|
||||||
|
"invalid state");
|
||||||
|
|
||||||
|
if (dacp->state == DAC_ACTIVE) {
|
||||||
|
msg = osalThreadSuspendTimeoutS(&dacp->thread, timeout);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = MSG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Synchronize to a conversion completion.
|
||||||
|
* @note This function can only be called by a single thread at time.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
* @param[in] timeout wait timeout
|
||||||
|
*
|
||||||
|
* @return The wait result.
|
||||||
|
* @retval MSG_OK if operation completed without errors.
|
||||||
|
* @retval MSG_TIMEOUT if synchronization request timed out.
|
||||||
|
* @retval MSG_RESET if the conversion has been stopped.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
msg_t dacSynchronize(DACDriver *dacp, sysinterval_t timeout) {
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
osalSysLock();
|
||||||
|
msg = dacSynchronizeS(dacp, timeout);
|
||||||
|
osalSysUnlock();
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#endif /* DAC_USE_SYNCHRONIZATION == TRUE */
|
||||||
|
|
||||||
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
|
|
||||||
*** Next ***
|
*** Next ***
|
||||||
|
- NEW: Improved DAC driver, updated STM32 DACv1.
|
||||||
- NEW: STM32 RTCv2 and RTCv3 modified to not use shadow registers.
|
- NEW: STM32 RTCv2 and RTCv3 modified to not use shadow registers.
|
||||||
- NEW: Enhanced STM32F7xx MPU configuration in mcuconf.h.
|
- NEW: Enhanced STM32F7xx MPU configuration in mcuconf.h.
|
||||||
- NEW: I2C slave support in HAL high level driver.
|
- NEW: I2C slave support in HAL high level driver.
|
||||||
|
|
Loading…
Reference in New Issue