@@ -29,6 +29,7 @@ struct dac_descr_t {
29
29
TIM_HandleTypeDef tim;
30
30
uint32_t tim_trig;
31
31
uint32_t resolution;
32
+ uint32_t dmaudr_flag;
32
33
DMABufferPool<Sample> *pool;
33
34
DMABuffer<Sample> *dmabuf[2 ];
34
35
};
@@ -37,10 +38,10 @@ struct dac_descr_t {
37
38
static DAC_HandleTypeDef dac = {0 };
38
39
39
40
static 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 }},
44
45
};
45
46
46
47
static uint32_t DAC_RES_LUT[] = {
@@ -73,10 +74,12 @@ static dac_descr_t *dac_descr_get(uint32_t channel) {
73
74
}
74
75
75
76
static void dac_descr_deinit (dac_descr_t *descr, bool dealloc_pool) {
76
- if (descr) {
77
+ if (descr != nullptr ) {
77
78
HAL_TIM_Base_Stop (&descr->tim );
78
79
HAL_DAC_Stop_DMA (descr->dac , descr->channel );
79
80
81
+ __HAL_DAC_CLEAR_FLAG (descr->dac , descr->dmaudr_flag );
82
+
80
83
for (size_t i=0 ; i<AN_ARRAY_SIZE (descr->dmabuf ); i++) {
81
84
if (descr->dmabuf [i]) {
82
85
descr->dmabuf [i]->release ();
@@ -89,13 +92,17 @@ static void dac_descr_deinit(dac_descr_t *descr, bool dealloc_pool) {
89
92
delete descr->pool ;
90
93
}
91
94
descr->pool = nullptr ;
95
+ } else {
96
+ descr->pool ->flush ();
92
97
}
93
-
94
98
}
95
99
}
96
100
97
101
bool AdvancedDAC::available () {
98
102
if (descr != nullptr ) {
103
+ if (__HAL_DAC_GET_FLAG (descr->dac , descr->dmaudr_flag )) {
104
+ dac_descr_deinit (descr, false );
105
+ }
99
106
return descr->pool ->writable ();
100
107
}
101
108
return false ;
@@ -113,11 +120,17 @@ DMABuffer<Sample> &AdvancedDAC::dequeue() {
113
120
}
114
121
115
122
void AdvancedDAC::write (DMABuffer<Sample> &dmabuf) {
123
+ static uint32_t buf_count = 0 ;
124
+
125
+ if (descr == nullptr ) {
126
+ return ;
127
+ }
128
+
116
129
// Make sure any cached data is flushed.
117
130
dmabuf.flush ();
118
131
descr->pool ->enqueue (&dmabuf);
119
132
120
- if (descr->dmabuf [0 ] == nullptr && descr-> pool -> readable () > 2 ) {
133
+ if (descr->dmabuf [0 ] == nullptr && (++buf_count % 3 ) == 0 ) {
121
134
descr->dmabuf [0 ] = descr->pool ->dequeue ();
122
135
descr->dmabuf [1 ] = descr->pool ->dequeue ();
123
136
@@ -126,7 +139,9 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
126
139
(uint32_t *) descr->dmabuf [0 ]->data (), descr->dmabuf [0 ]->size (), descr->resolution );
127
140
128
141
// Re/enable DMA double buffer mode.
142
+ HAL_NVIC_DisableIRQ (descr->dma_irqn );
129
143
hal_dma_enable_dbm (&descr->dma , descr->dmabuf [0 ]->data (), descr->dmabuf [1 ]->data ());
144
+ HAL_NVIC_EnableIRQ (descr->dma_irqn );
130
145
131
146
// Start trigger timer.
132
147
HAL_TIM_Base_Start (&descr->tim );
@@ -135,7 +150,7 @@ void AdvancedDAC::write(DMABuffer<Sample> &dmabuf) {
135
150
136
151
int AdvancedDAC::begin (uint32_t resolution, uint32_t frequency, size_t n_samples, size_t n_buffers) {
137
152
// 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 ) {
139
154
return 0 ;
140
155
}
141
156
@@ -147,13 +162,14 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
147
162
148
163
uint32_t function = pinmap_function (dac_pins[0 ], PinMap_DAC);
149
164
descr = dac_descr_get (DAC_CHAN_LUT[STM_PIN_CHANNEL (function) - 1 ]);
150
- if (descr == nullptr || descr-> pool ) {
165
+ if (descr == nullptr ) {
151
166
return 0 ;
152
167
}
153
168
154
169
// Allocate DMA buffer pool.
155
170
descr->pool = new DMABufferPool<Sample>(n_samples, n_channels, n_buffers);
156
171
if (descr->pool == nullptr ) {
172
+ descr = nullptr ;
157
173
return 0 ;
158
174
}
159
175
descr->resolution = DAC_RES_LUT[resolution];
@@ -178,13 +194,16 @@ int AdvancedDAC::begin(uint32_t resolution, uint32_t frequency, size_t n_samples
178
194
179
195
int AdvancedDAC::stop ()
180
196
{
181
- dac_descr_deinit (descr, true );
197
+ if (descr != nullptr ) {
198
+ dac_descr_deinit (descr, true );
199
+ descr = nullptr ;
200
+ }
182
201
return 1 ;
183
202
}
184
203
185
204
int AdvancedDAC::frequency (uint32_t const frequency)
186
205
{
187
- if (descr && descr-> pool ) {
206
+ if (descr != nullptr ) {
188
207
// Reconfigure the trigger timer.
189
208
dac_descr_deinit (descr, false );
190
209
hal_tim_config (&descr->tim , frequency);
@@ -200,9 +219,10 @@ extern "C" {
200
219
201
220
void DAC_DMAConvCplt (DMA_HandleTypeDef *dma, uint32_t channel) {
202
221
dac_descr_t *descr = dac_descr_get (channel);
222
+
203
223
// Release the DMA buffer that was just done, allocate a new one,
204
224
// and update the next DMA memory address target.
205
- if (descr->pool ->readable ()) {
225
+ if (descr && descr ->pool ->readable ()) {
206
226
// NOTE: CT bit is inverted, to get the DMA buffer that's Not currently in use.
207
227
size_t ct = ! hal_dma_get_ct (dma);
208
228
descr->dmabuf [ct]->release ();
0 commit comments