@@ -29,6 +29,7 @@ struct dac_descr_t {
2929 TIM_HandleTypeDef tim;
3030 uint32_t tim_trig;
3131 uint32_t resolution;
32+ uint32_t dmaudr_flag;
3233 DMABufferPool<Sample> *pool;
3334 DMABuffer<Sample> *dmabuf[2 ];
3435};
@@ -37,10 +38,10 @@ struct dac_descr_t {
3738static DAC_HandleTypeDef dac = {0 };
3839
3940static dac_descr_t dac_descr_all[] = {
40- {&dac, DAC_CHANNEL_1, {DMA1_Stream4, {DMA_REQUEST_DAC1_CH1}}, DMA1_Stream4_IRQn,
41- {TIM4}, DAC_TRIGGER_T4_TRGO, DAC_ALIGN_12B_R, nullptr , {nullptr , nullptr }},
42- {&dac, DAC_CHANNEL_2, {DMA1_Stream5, {DMA_REQUEST_DAC1_CH2}}, DMA1_Stream5_IRQn,
43- {TIM5}, DAC_TRIGGER_T5_TRGO, DAC_ALIGN_12B_R, nullptr , {nullptr , nullptr }},
41+ {&dac, DAC_CHANNEL_1, {DMA1_Stream4, {DMA_REQUEST_DAC1_CH1}}, DMA1_Stream4_IRQn, {TIM4},
42+ DAC_TRIGGER_T4_TRGO, DAC_ALIGN_12B_R, DAC_FLAG_DMAUDR1 , nullptr , {nullptr , nullptr }},
43+ {&dac, DAC_CHANNEL_2, {DMA1_Stream5, {DMA_REQUEST_DAC1_CH2}}, DMA1_Stream5_IRQn, {TIM5},
44+ DAC_TRIGGER_T5_TRGO, DAC_ALIGN_12B_R, DAC_FLAG_DMAUDR2 , nullptr , {nullptr , nullptr }},
4445};
4546
4647static uint32_t DAC_RES_LUT[] = {
@@ -73,10 +74,12 @@ static dac_descr_t *dac_descr_get(uint32_t channel) {
7374}
7475
7576static void dac_descr_deinit (dac_descr_t *descr, bool dealloc_pool) {
76- if (descr) {
77+ if (descr != nullptr ) {
7778 HAL_TIM_Base_Stop (&descr->tim );
7879 HAL_DAC_Stop_DMA (descr->dac , descr->channel );
7980
81+ __HAL_DAC_CLEAR_FLAG (descr->dac , descr->dmaudr_flag );
82+
8083 for (size_t i=0 ; i<AN_ARRAY_SIZE (descr->dmabuf ); i++) {
8184 if (descr->dmabuf [i]) {
8285 descr->dmabuf [i]->release ();
@@ -89,13 +92,17 @@ static void dac_descr_deinit(dac_descr_t *descr, bool dealloc_pool) {
8992 delete descr->pool ;
9093 }
9194 descr->pool = nullptr ;
95+ } else {
96+ descr->pool ->flush ();
9297 }
93-
9498 }
9599}
96100
97101bool AdvancedDAC::available () {
98102 if (descr != nullptr ) {
103+ if (__HAL_DAC_GET_FLAG (descr->dac , descr->dmaudr_flag )) {
104+ dac_descr_deinit (descr, false );
105+ }
99106 return descr->pool ->writable ();
100107 }
101108 return false ;
@@ -113,11 +120,17 @@ DMABuffer<Sample> &AdvancedDAC::dequeue() {
113120}
114121
115122void AdvancedDAC::write (DMABuffer<Sample> &dmabuf) {
123+ static uint32_t buf_count = 0 ;
124+
125+ if (descr == nullptr ) {
126+ return ;
127+ }
128+
116129 // Make sure any cached data is flushed.
117130 dmabuf.flush ();
118131 descr->pool ->enqueue (&dmabuf);
119132
120- if (descr->dmabuf [0 ] == nullptr && descr-> pool -> readable () > 2 ) {
133+ if (descr->dmabuf [0 ] == nullptr && (++buf_count % 3 ) == 0 ) {
121134 descr->dmabuf [0 ] = descr->pool ->dequeue ();
122135 descr->dmabuf [1 ] = descr->pool ->dequeue ();
123136
@@ -126,7 +139,9 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
126139 (uint32_t *) descr->dmabuf [0 ]->data (), descr->dmabuf [0 ]->size (), descr->resolution );
127140
128141 // Re/enable DMA double buffer mode.
142+ HAL_NVIC_DisableIRQ (descr->dma_irqn );
129143 hal_dma_enable_dbm (&descr->dma , descr->dmabuf [0 ]->data (), descr->dmabuf [1 ]->data ());
144+ HAL_NVIC_EnableIRQ (descr->dma_irqn );
130145
131146 // Start trigger timer.
132147 HAL_TIM_Base_Start (&descr->tim );
@@ -135,7 +150,7 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
135150
136151int AdvancedDAC::begin (uint32_t resolution, uint32_t frequency, size_t n_samples, size_t n_buffers) {
137152 // Sanity checks.
138- if (resolution >= AN_ARRAY_SIZE (DAC_RES_LUT) || ( descr && descr-> pool ) ) {
153+ if (resolution >= AN_ARRAY_SIZE (DAC_RES_LUT) || descr != nullptr ) {
139154 return 0 ;
140155 }
141156
@@ -147,13 +162,14 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
147162
148163 uint32_t function = pinmap_function (dac_pins[0 ], PinMap_DAC);
149164 descr = dac_descr_get (DAC_CHAN_LUT[STM_PIN_CHANNEL (function) - 1 ]);
150- if (descr == nullptr || descr-> pool ) {
165+ if (descr == nullptr ) {
151166 return 0 ;
152167 }
153168
154169 // Allocate DMA buffer pool.
155170 descr->pool = new DMABufferPool<Sample>(n_samples, n_channels, n_buffers);
156171 if (descr->pool == nullptr ) {
172+ descr = nullptr ;
157173 return 0 ;
158174 }
159175 descr->resolution = DAC_RES_LUT[resolution];
@@ -178,13 +194,16 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
178194
179195int AdvancedDAC::stop ()
180196{
181- dac_descr_deinit (descr, true );
197+ if (descr != nullptr ) {
198+ dac_descr_deinit (descr, true );
199+ descr = nullptr ;
200+ }
182201 return 1 ;
183202}
184203
185204int AdvancedDAC::frequency (uint32_t const frequency)
186205{
187- if (descr && descr-> pool ) {
206+ if (descr != nullptr ) {
188207 // Reconfigure the trigger timer.
189208 dac_descr_deinit (descr, false );
190209 hal_tim_config (&descr->tim , frequency);
@@ -200,9 +219,10 @@ extern "C" {
200219
201220void DAC_DMAConvCplt (DMA_HandleTypeDef *dma, uint32_t channel) {
202221 dac_descr_t *descr = dac_descr_get (channel);
222+
203223 // Release the DMA buffer that was just done, allocate a new one,
204224 // and update the next DMA memory address target.
205- if (descr->pool ->readable ()) {
225+ if (descr && descr ->pool ->readable ()) {
206226 // NOTE: CT bit is inverted, to get the DMA buffer that's Not currently in use.
207227 size_t ct = ! hal_dma_get_ct (dma);
208228 descr->dmabuf [ct]->release ();
0 commit comments