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:
Giovanni Di Sirio 2023-07-09 08:34:39 +00:00
parent f77d00b0c9
commit 665b0d48b4
5 changed files with 2309 additions and 2207 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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. */
/*===========================================================================*/ /*===========================================================================*/

View File

@ -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__)
/** /**

View File

@ -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.