← index #9563Issue #5619
Related · high · value 2.707
QUERY · ISSUE

dac.write_timed() does not work with NUCLEO_G474RE

openby anchung-chenopened 2022-10-10updated 2023-07-01
bugport-stm32

The example code from micropython document does not work with NUCLEO_G474RE.

import math
from array import array
from pyb import DAC

# create a buffer containing a sine-wave, using half-word samples
buf = array('H', 2048 + int(2047 * math.sin(2 * math.pi * i / 128)) for i in range(128))

# output the sine-wave at 400Hz
dac = DAC(1, bits=12)
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)

The DAC1 output of PA4 pin (A2 pin on arduino connector) shows no waveform.

After a little research, I found the root cause is that DMA_PDATAALIGN_WORD should be used for the "DMA + DAC" operation of STM32G4 cpu.

Here is my modification of dac.c to make dac.write_timed() work with NUCLEO_G474RE.

STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, uint32_t dma_mode, uint32_t bit_size, uint32_t dac_align, size_t len, void *buf) {
    uint32_t dma_align;
    if (bit_size == 8) {
        dma_align = DMA_MDATAALIGN_BYTE | DMA_PDATAALIGN_BYTE;
    } else {
#if defined(STM32G4)
        dma_align = DMA_MDATAALIGN_HALFWORD | DMA_PDATAALIGN_WORD;
#else
        dma_align = DMA_MDATAALIGN_HALFWORD | DMA_PDATAALIGN_HALFWORD;
#endif
    }
CANDIDATE · ISSUE

STM32H7 DAC write_timed is not working.

closedby iabdalkaderopened 2020-02-07updated 2021-07-02
port-stm32

Hi, the DAC timed writes (triggered by timer6) is not working on the H7. I can't figured out the exact issue, but it seems to be related to dma_nohal_xxx functions. If the DMA is initialized with dma_init instead of dma_nohal_init it works, here's my test script:

import math
from pyb import DAC

# create a buffer containing a sine-wave
buf = bytearray(100)
for i in range(len(buf)):
    buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf)))

# output the sine-wave at 400Hz
dac = DAC(2)
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)

The following patches make it work on the H7:

diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c
index 9835abb..95dfe5d 100644
--- a/ports/stm32/dac.c
+++ b/ports/stm32/dac.c
@@ -160,6 +160,7 @@ STATIC void dac_start(uint32_t dac_channel) {
     DAC->CR |= DAC_CR_EN1 << dac_channel;
 }
 
+#if 0
 STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, uint32_t dma_mode, uint32_t bit_size, uint32_t dac_align, size_t len, void *buf) {
     uint32_t dma_align;
     if (bit_size == 8) {
@@ -183,7 +184,22 @@ STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, ui
 
     DAC->CR |= DAC_CR_EN1 << dac_channel;
 }
+#else
+static DAC_HandleTypeDef hdac;
+static DMA_HandleTypeDef hdma;
 
+STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, uint32_t dma_mode, uint32_t bit_size, uint32_t dac_align, size_t len, void *buf) {
+    hdac.Instance = DAC1;
+    HAL_DAC_Init(&hdac);
+
+    dma_deinit(dma_descr);
+    dma_init(&hdma, dma_descr, DMA_MEMORY_TO_PERIPH, &hdac);
+    hdac.DMA_Handle2 = &hdma;
+
+    MP_HAL_CLEAN_DCACHE(buf, len);
+    HAL_DAC_Start_DMA(&hdac, dac_channel, (uint32_t *)buf, len, DAC_ALIGN_8B_R);
+}
+#endif
 /******************************************************************************/
 // MicroPython bindings

And:

diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c
index f6017c1..932d60d 100644
--- a/ports/stm32/dma.c
+++ b/ports/stm32/dma.c
@@ -156,7 +156,7 @@ static const DMA_InitTypeDef dma_init_struct_dac = {
     .MemInc              = DMA_MINC_ENABLE,
     .PeriphDataAlignment = DMA_PDATAALIGN_BYTE,
     .MemDataAlignment    = DMA_MDATAALIGN_BYTE,
-    .Mode                = DMA_NORMAL,
+    .Mode                = DMA_CIRCULAR,
     .Priority            = DMA_PRIORITY_HIGH,
     #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
     .FIFOMode            = DMA_FIFOMODE_DISABLE,

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied