diff --git a/os/hal/ports/STM32/LLD/DACv1/dac_lld.c b/os/hal/ports/STM32/LLD/DACv1/dac_lld.c
index 8fc51ae88..f3191e47b 100644
--- a/os/hal/ports/STM32/LLD/DACv1/dac_lld.c
+++ b/os/hal/ports/STM32/LLD/DACv1/dac_lld.c
@@ -253,9 +253,16 @@ void dac_lld_start(DACDriver *dacp) {
dacp->params->dac->CR |= DAC_CR_EN1 << dacp->params->regshift;
dac_lld_put_channel(dacp, 0U, dacp->config->init);
#else
- dacp->params->dac->CR = DAC_CR_EN2 | DAC_CR_EN1;
+ if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) {
+ dacp->params->dac->CR = DAC_CR_EN2 | DAC_CR_EN1;
+ dac_lld_put_channel(dacp, 1U, dacp->config->init);
+ }
+ else {
+ dacp->params->dac->CR = DAC_CR_EN1;
+ }
dac_lld_put_channel(dacp, 0U, dacp->config->init);
- dac_lld_put_channel(dacp, 1U, dacp->config->init);
#endif
}
}
@@ -308,6 +315,7 @@ void dac_lld_put_channel(DACDriver *dacp,
switch (dacp->config->datamode) {
case DAC_DHRM_12BIT_RIGHT:
+ case DAC_DHRM_12BIT_RIGHT_DUAL:
if (channel == 0U) {
dacp->params->dac->DHR12R1 = (uint32_t)sample;
}
@@ -316,6 +324,7 @@ void dac_lld_put_channel(DACDriver *dacp,
}
break;
case DAC_DHRM_12BIT_LEFT:
+ case DAC_DHRM_12BIT_LEFT_DUAL:
if (channel == 0U) {
dacp->params->dac->DHR12L1 = (uint32_t)sample;
}
@@ -324,6 +333,7 @@ void dac_lld_put_channel(DACDriver *dacp,
}
break;
case DAC_DHRM_8BIT_RIGHT:
+ case DAC_DHRM_8BIT_RIGHT_DUAL:
if (channel == 0U) {
dacp->params->dac->DHR8R1 = (uint32_t)sample;
}
@@ -340,13 +350,24 @@ void dac_lld_put_channel(DACDriver *dacp,
/**
* @brief Starts a DAC conversion.
* @details Starts an asynchronous conversion operation.
+ * @note In @p DAC_DHRM_8BIT_RIGHT mode the parameters passed to the
+ * callback are wrong because two samples are packed in a single
+ * dacsample_t element. This will not be corrected, do not rely
+ * on those parameters.
+ * @note In @p DAC_DHRM_8BIT_RIGHT_DUAL mode two samples are treated
+ * 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
+ * conversion configuration structure.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @notapi
*/
void dac_lld_start_conversion(DACDriver *dacp) {
- uint32_t cr, dmamode;
+ uint32_t n, cr, dmamode;
+
+ /* Number of DMA operations per buffer.*/
+ n = dacp->depth * dacp->grpp->num_channels;
/* Allocating the DMA channel.*/
bool b = dmaStreamAllocate(dacp->params->dma, dacp->params->dmairqprio,
@@ -354,53 +375,67 @@ void dac_lld_start_conversion(DACDriver *dacp) {
(void *)dacp);
osalDbgAssert(!b, "stream already allocated");
-#if STM32_DAC_DUAL_MODE == FALSE
+ /* DMA settings depend on the chosed DAC mode.*/
switch (dacp->config->datamode) {
/* Sets the DAC data register */
case DAC_DHRM_12BIT_RIGHT:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
dmaStreamSetPeripheral(dacp->params->dma, &dacp->params->dac->DHR12R1 +
dacp->params->dataoffset);
dmamode = dacp->params->dmamode |
STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
break;
case DAC_DHRM_12BIT_LEFT:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
dmaStreamSetPeripheral(dacp->params->dma, &dacp->params->dac->DHR12L1 +
dacp->params->dataoffset);
dmamode = dacp->params->dmamode |
STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
break;
case DAC_DHRM_8BIT_RIGHT:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
dmaStreamSetPeripheral(dacp->params->dma, &dacp->params->dac->DHR8R1 +
dacp->params->dataoffset);
dmamode = dacp->params->dmamode |
STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+
+ /* In this mode the size of the buffer is halved because two samples
+ packed in a single dacsample_t element.*/
+ n = (n + 1) / 2;
break;
+#if STM32_DAC_DUAL_MODE == TRUE
+ case DAC_DHRM_12BIT_RIGHT_DUAL:
+ osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->params->dma, &dacp->params->dac->DHR12RD);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ break;
+ case DAC_DHRM_12BIT_LEFT_DUAL:
+ osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->params->dma, &dacp->params->dac->DHR12LD);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ break;
+ case DAC_DHRM_8BIT_RIGHT_DUAL:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->params->dma, &dacp->params->dac->DHR8RD);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ break;
+#endif
default:
chDbgAssert(false, "unexpected DAC mode");
break;
}
-#else
-#if defined(STM32_HAS_DAC_CHN2) && STM32_HAS_DAC_CHN2
- case DAC_DHRM_12BIT_RIGHT_DUAL:
- dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR12RD);
- dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
- STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
- break;
- case DAC_DHRM_12BIT_LEFT_DUAL:
- dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR12LD);
- dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
- STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
- break;
- case DAC_DHRM_8BIT_RIGHT_DUAL:
- dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR8RD);
- dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
- STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
- break;
-#endif
-#endif
dmaStreamSetMemory0(dacp->params->dma, dacp->samples);
- dmaStreamSetTransactionSize(dacp->params->dma, dacp->depth);
+ dmaStreamSetTransactionSize(dacp->params->dma, n);
dmaStreamSetMode(dacp->params->dma, dmamode |
STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
STM32_DMA_CR_HTIE | STM32_DMA_CR_TCIE);
@@ -412,11 +447,13 @@ void dac_lld_start_conversion(DACDriver *dacp) {
dacp->params->dac->CR &= dacp->params->regmask;
dacp->params->dac->CR |= cr << dacp->params->regshift;
#else
- /* TODO: Dual.*/
+ dacp->params->dac->CR = 0;
+ cr = DAC_CR_DMAEN1 | (dacp->grpp->trigger << 3) | DAC_CR_TEN1 | DAC_CR_EN1
+ | (dacp->grpp->trigger << 19) | DAC_CR_TEN2 | DAC_CR_EN2;
+ dacp->params->dac->CR = cr;
#endif
}
-
/**
* @brief Stops an ongoing conversion.
* @details This function stops the currently ongoing conversion and returns
@@ -436,10 +473,15 @@ void dac_lld_stop_conversion(DACDriver *dacp) {
#if STM32_DAC_DUAL_MODE == FALSE
dacp->params->dac->CR &= dacp->params->regmask;
dacp->params->dac->CR |= DAC_CR_EN1 << dacp->params->regshift;
- *(&dacp->params->dac->DHR12R1 + dacp->params->dataoffset) = 0U;
#else
- dacp->params->dac->CR = DAC_CR_EN2 | DAC_CR_EN1;
- dacp->params->dac->DAC_DHR12RD = 0U;
+ if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) {
+ dacp->params->dac->CR = DAC_CR_EN2 | DAC_CR_EN1;
+ }
+ else {
+ dacp->params->dac->CR = DAC_CR_EN1;
+ }
#endif
}
diff --git a/testhal/STM32/STM32F4xx/DAC_DUAL/debug/STM32F4xx-DAC_DUAL (OpenOCD, Flash and Run).launch b/testhal/STM32/STM32F4xx/DAC_DUAL/debug/STM32F4xx-DAC_DUAL (OpenOCD, Flash and Run).launch
index a6cdd3e04..cf2bb94e6 100644
--- a/testhal/STM32/STM32F4xx/DAC_DUAL/debug/STM32F4xx-DAC_DUAL (OpenOCD, Flash and Run).launch
+++ b/testhal/STM32/STM32F4xx/DAC_DUAL/debug/STM32F4xx-DAC_DUAL (OpenOCD, Flash and Run).launch
@@ -33,7 +33,7 @@
-
+
diff --git a/testhal/STM32/STM32F4xx/DAC_DUAL/main.c b/testhal/STM32/STM32F4xx/DAC_DUAL/main.c
index e57d8a3f2..b6d46b284 100644
--- a/testhal/STM32/STM32F4xx/DAC_DUAL/main.c
+++ b/testhal/STM32/STM32F4xx/DAC_DUAL/main.c
@@ -89,11 +89,11 @@ static void error_cb1(DACDriver *dacp, dacerror_t err) {
static const DACConfig dac1cfg1 = {
init: 2047U,
- datamode: DAC_DHRM_12BIT_RIGHT
+ datamode: DAC_DHRM_12BIT_RIGHT_DUAL
};
static const DACConversionGroup dacgrpcfg1 = {
- num_channels: 1U,
+ num_channels: 2U,
end_cb: end_cb1,
error_cb: error_cb1,
trigger: DAC_TRG(0)
@@ -125,10 +125,11 @@ int main(void) {
chSysInit();
/*
- * Starting DAC1 driver, setting up the output pin as analog as suggested
+ * Starting DAC1 driver, setting up the output pins as analog as suggested
* by the Reference Manual.
*/
palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG);
+ palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG);
dacStart(&DACD1, &dac1cfg1);
/*
@@ -138,8 +139,10 @@ int main(void) {
/*
* Starting a continuous conversion.
+ * Note, the buffer size is divided by two because two elements are fetched
+ * for each transfer.
*/
- dacStartConversion(&DACD1, &dacgrpcfg1, dac_buffer, DAC_BUFFER_SIZE);
+ dacStartConversion(&DACD1, &dacgrpcfg1, dac_buffer, DAC_BUFFER_SIZE / 2U);
gptStartContinuous(&GPTD6, 2U);
/*
diff --git a/testhal/STM32/STM32F4xx/DAC_DUAL/mcuconf.h b/testhal/STM32/STM32F4xx/DAC_DUAL/mcuconf.h
index a6bc10980..d16ac4194 100644
--- a/testhal/STM32/STM32F4xx/DAC_DUAL/mcuconf.h
+++ b/testhal/STM32/STM32F4xx/DAC_DUAL/mcuconf.h
@@ -93,9 +93,9 @@
/*
* DAC driver system settings.
*/
-#define STM32_DAC_DUAL_MODE FALSE
+#define STM32_DAC_DUAL_MODE TRUE
#define STM32_DAC_USE_DAC1_CH1 TRUE
-#define STM32_DAC_USE_DAC1_CH2 TRUE
+#define STM32_DAC_USE_DAC1_CH2 FALSE
#define STM32_DAC1_CH1_IRQ_PRIORITY 10
#define STM32_DAC1_CH2_IRQ_PRIORITY 10
#define STM32_DAC1_CH1_DMA_PRIORITY 2