STM32H7 - Fix SPI5 DMA RX mapping.
[betaflight.git] / src / main / drivers / dma_reqmap.c
blob0445edabd628c2f6a63a6c2b38642a958c832efa
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdint.h>
23 #include "platform.h"
25 #ifdef USE_DMA_SPEC
27 #include "drivers/adc.h"
28 #include "drivers/bus_spi.h"
29 #include "drivers/serial.h"
30 #include "drivers/serial_uart.h"
31 #include "drivers/timer_def.h"
33 #include "pg/timerio.h"
35 #include "dma_reqmap.h"
37 typedef struct dmaPeripheralMapping_s {
38 dmaPeripheral_e device;
39 uint8_t index;
40 #if defined(STM32H7) || defined(STM32G4)
41 uint8_t dmaRequest;
42 #else
43 dmaChannelSpec_t channelSpec[MAX_PERIPHERAL_DMA_OPTIONS];
44 #endif
45 } dmaPeripheralMapping_t;
47 typedef struct dmaTimerMapping_s {
48 TIM_TypeDef *tim;
49 uint8_t channel;
50 #if defined(STM32H7) || defined(STM32G4)
51 uint8_t dmaRequest;
52 #else
53 dmaChannelSpec_t channelSpec[MAX_TIMER_DMA_OPTIONS];
54 #endif
55 } dmaTimerMapping_t;
57 #if defined(STM32G4)
59 #define REQMAP_SGL(periph) { DMA_PERIPH_ ## periph, 0, DMA_REQUEST_ ## periph }
60 #define REQMAP(periph, device) { DMA_PERIPH_ ## periph, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device }
61 #define REQMAP_DIR(periph, device, dir) { DMA_PERIPH_ ## periph ## _ ## dir, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device ## _ ## dir }
62 #define REQMAP_TIMUP(periph, timno) { DMA_PERIPH_TIMUP, timno - 1, DMA_REQUEST_ ## TIM ## timno ## _UP }
64 // Resolve UART/USART mess, also map UART6 requests to LPUART1 requests
65 #define DMA_REQUEST_UART1_RX DMA_REQUEST_USART1_RX
66 #define DMA_REQUEST_UART1_TX DMA_REQUEST_USART1_TX
67 #define DMA_REQUEST_UART2_RX DMA_REQUEST_USART2_RX
68 #define DMA_REQUEST_UART2_TX DMA_REQUEST_USART2_TX
69 #define DMA_REQUEST_UART3_RX DMA_REQUEST_USART3_RX
70 #define DMA_REQUEST_UART3_TX DMA_REQUEST_USART3_TX
71 #define DMA_REQUEST_UART9_RX DMA_REQUEST_LPUART1_RX
72 #define DMA_REQUEST_UART9_TX DMA_REQUEST_LPUART1_TX
74 static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
75 #ifdef USE_SPI
76 REQMAP_DIR(SPI, 1, TX),
77 REQMAP_DIR(SPI, 1, RX),
78 REQMAP_DIR(SPI, 2, TX),
79 REQMAP_DIR(SPI, 2, RX),
80 REQMAP_DIR(SPI, 3, TX),
81 REQMAP_DIR(SPI, 3, RX),
82 REQMAP_DIR(SPI, 4, TX),
83 REQMAP_DIR(SPI, 4, RX),
84 #endif // USE_SPI
86 #ifdef USE_ADC
87 REQMAP(ADC, 1),
88 REQMAP(ADC, 2),
89 REQMAP(ADC, 3),
90 REQMAP(ADC, 4),
91 REQMAP(ADC, 5),
92 #endif
94 #ifdef USE_UART
95 REQMAP_DIR(UART, 1, TX),
96 REQMAP_DIR(UART, 1, RX),
97 REQMAP_DIR(UART, 2, TX),
98 REQMAP_DIR(UART, 2, RX),
99 REQMAP_DIR(UART, 3, TX),
100 REQMAP_DIR(UART, 3, RX),
101 REQMAP_DIR(UART, 4, TX),
102 REQMAP_DIR(UART, 4, RX),
103 REQMAP_DIR(UART, 5, TX),
104 REQMAP_DIR(UART, 5, RX),
105 REQMAP_DIR(UART, 9, TX),
106 REQMAP_DIR(UART, 9, RX),
107 #endif
109 #ifdef USE_TIMER
110 // Pseudo peripheral for TIMx_UP channel
111 REQMAP_TIMUP(TIMUP, 1),
112 REQMAP_TIMUP(TIMUP, 2),
113 REQMAP_TIMUP(TIMUP, 3),
114 REQMAP_TIMUP(TIMUP, 4),
115 REQMAP_TIMUP(TIMUP, 5),
116 REQMAP_TIMUP(TIMUP, 6),
117 REQMAP_TIMUP(TIMUP, 7),
118 REQMAP_TIMUP(TIMUP, 8),
119 REQMAP_TIMUP(TIMUP, 15),
120 REQMAP_TIMUP(TIMUP, 16),
121 REQMAP_TIMUP(TIMUP, 17),
122 REQMAP_TIMUP(TIMUP, 20),
123 #endif
126 #undef REQMAP_TIMUP
127 #undef REQMAP
128 #undef REQMAP_SGL
129 #undef REQMAP_DIR
131 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
133 #define REQMAP_TIM(tim, chan) { tim, TC(chan), DMA_REQUEST_ ## tim ## _ ## chan }
135 static const dmaTimerMapping_t dmaTimerMapping[] = {
136 REQMAP_TIM(TIM1, CH1),
137 REQMAP_TIM(TIM1, CH2),
138 REQMAP_TIM(TIM1, CH3),
139 REQMAP_TIM(TIM1, CH4),
140 REQMAP_TIM(TIM2, CH1),
141 REQMAP_TIM(TIM2, CH2),
142 REQMAP_TIM(TIM2, CH3),
143 REQMAP_TIM(TIM2, CH4),
144 REQMAP_TIM(TIM3, CH1),
145 REQMAP_TIM(TIM3, CH2),
146 REQMAP_TIM(TIM3, CH3),
147 REQMAP_TIM(TIM3, CH4),
148 REQMAP_TIM(TIM4, CH1),
149 REQMAP_TIM(TIM4, CH2),
150 REQMAP_TIM(TIM4, CH3),
151 REQMAP_TIM(TIM5, CH1),
152 REQMAP_TIM(TIM5, CH2),
153 REQMAP_TIM(TIM5, CH3),
154 REQMAP_TIM(TIM5, CH4),
155 REQMAP_TIM(TIM8, CH1),
156 REQMAP_TIM(TIM8, CH2),
157 REQMAP_TIM(TIM8, CH3),
158 REQMAP_TIM(TIM8, CH4),
159 REQMAP_TIM(TIM15, CH1),
160 REQMAP_TIM(TIM16, CH1),
161 REQMAP_TIM(TIM17, CH1),
162 REQMAP_TIM(TIM20, CH1),
163 REQMAP_TIM(TIM20, CH2),
164 REQMAP_TIM(TIM20, CH3),
165 REQMAP_TIM(TIM20, CH4),
166 // XXX Check non-CH1 for TIM15,16,17 and 20
169 #undef TC
170 #undef REQMAP_TIM
172 #define DMA(d, c) { DMA_CODE(d, c, 0), (dmaResource_t *)DMA ## d ## _Channel ## c, 0 }
174 static dmaChannelSpec_t dmaChannelSpec[MAX_PERIPHERAL_DMA_OPTIONS] = {
175 DMA(1, 1),
176 DMA(1, 2),
177 DMA(1, 3),
178 DMA(1, 4),
179 DMA(1, 5),
180 DMA(1, 6),
181 DMA(1, 7),
182 DMA(1, 8),
183 DMA(2, 1),
184 DMA(2, 2),
185 DMA(2, 3),
186 DMA(2, 4),
187 DMA(2, 5),
188 DMA(2, 6),
189 DMA(2, 7),
190 DMA(2, 8),
193 #undef DMA
195 #elif defined(STM32H7)
197 #define REQMAP_SGL(periph) { DMA_PERIPH_ ## periph, 0, DMA_REQUEST_ ## periph }
198 #define REQMAP(periph, device) { DMA_PERIPH_ ## periph, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device }
199 #define REQMAP_DIR(periph, device, dir) { DMA_PERIPH_ ## periph ## _ ## dir, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device ## _ ## dir }
200 #define REQMAP_TIMUP(periph, timno) { DMA_PERIPH_TIMUP, timno - 1, DMA_REQUEST_ ## TIM ## timno ## _UP }
202 // Resolve UART/USART mess
203 #define DMA_REQUEST_UART1_RX DMA_REQUEST_USART1_RX
204 #define DMA_REQUEST_UART1_TX DMA_REQUEST_USART1_TX
205 #define DMA_REQUEST_UART2_RX DMA_REQUEST_USART2_RX
206 #define DMA_REQUEST_UART2_TX DMA_REQUEST_USART2_TX
207 #define DMA_REQUEST_UART3_RX DMA_REQUEST_USART3_RX
208 #define DMA_REQUEST_UART3_TX DMA_REQUEST_USART3_TX
209 #define DMA_REQUEST_UART6_RX DMA_REQUEST_USART6_RX
210 #define DMA_REQUEST_UART6_TX DMA_REQUEST_USART6_TX
212 static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
213 #ifdef USE_SPI
214 REQMAP_DIR(SPI, 1, TX),
215 REQMAP_DIR(SPI, 1, RX),
216 REQMAP_DIR(SPI, 2, TX),
217 REQMAP_DIR(SPI, 2, RX),
218 REQMAP_DIR(SPI, 3, TX),
219 REQMAP_DIR(SPI, 3, RX),
220 REQMAP_DIR(SPI, 4, TX),
221 REQMAP_DIR(SPI, 4, RX),
222 REQMAP_DIR(SPI, 5, TX), // Not available in smaller packages
223 REQMAP_DIR(SPI, 5, RX), // ditto
224 // REQMAP_DIR(SPI, 6, TX), // SPI6 is on BDMA (todo)
225 // REQMAP_DIR(SPI, 6, TX), // ditto
226 #endif // USE_SPI
228 #ifdef USE_ADC
229 REQMAP(ADC, 1),
230 REQMAP(ADC, 2),
231 #if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H725xx)
232 REQMAP(ADC, 3),
233 #endif
234 #endif
236 #ifdef USE_UART
237 REQMAP_DIR(UART, 1, TX),
238 REQMAP_DIR(UART, 1, RX),
239 REQMAP_DIR(UART, 2, TX),
240 REQMAP_DIR(UART, 2, RX),
241 REQMAP_DIR(UART, 3, TX),
242 REQMAP_DIR(UART, 3, RX),
243 REQMAP_DIR(UART, 4, TX),
244 REQMAP_DIR(UART, 4, RX),
245 REQMAP_DIR(UART, 5, TX),
246 REQMAP_DIR(UART, 5, RX),
247 REQMAP_DIR(UART, 6, TX),
248 REQMAP_DIR(UART, 6, RX),
249 REQMAP_DIR(UART, 7, TX),
250 REQMAP_DIR(UART, 7, RX),
251 REQMAP_DIR(UART, 8, TX),
252 REQMAP_DIR(UART, 8, RX),
253 #endif
255 #ifdef USE_TIMER
256 // Pseudo peripheral for TIMx_UP channel
257 REQMAP_TIMUP(TIMUP, 1),
258 REQMAP_TIMUP(TIMUP, 2),
259 REQMAP_TIMUP(TIMUP, 3),
260 REQMAP_TIMUP(TIMUP, 4),
261 REQMAP_TIMUP(TIMUP, 5),
262 REQMAP_TIMUP(TIMUP, 6),
263 REQMAP_TIMUP(TIMUP, 7),
264 REQMAP_TIMUP(TIMUP, 8),
265 REQMAP_TIMUP(TIMUP, 15),
266 REQMAP_TIMUP(TIMUP, 16),
267 REQMAP_TIMUP(TIMUP, 17),
268 #endif
271 #undef REQMAP_TIMUP
272 #undef REQMAP
273 #undef REQMAP_SGL
274 #undef REQMAP_DIR
276 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
278 #define REQMAP_TIM(tim, chan) { tim, TC(chan), DMA_REQUEST_ ## tim ## _ ## chan }
280 static const dmaTimerMapping_t dmaTimerMapping[] = {
281 REQMAP_TIM(TIM1, CH1),
282 REQMAP_TIM(TIM1, CH2),
283 REQMAP_TIM(TIM1, CH3),
284 REQMAP_TIM(TIM1, CH4),
285 REQMAP_TIM(TIM2, CH1),
286 REQMAP_TIM(TIM2, CH2),
287 REQMAP_TIM(TIM2, CH3),
288 REQMAP_TIM(TIM2, CH4),
289 REQMAP_TIM(TIM3, CH1),
290 REQMAP_TIM(TIM3, CH2),
291 REQMAP_TIM(TIM3, CH3),
292 REQMAP_TIM(TIM3, CH4),
293 REQMAP_TIM(TIM4, CH1),
294 REQMAP_TIM(TIM4, CH2),
295 REQMAP_TIM(TIM4, CH3),
296 REQMAP_TIM(TIM5, CH1),
297 REQMAP_TIM(TIM5, CH2),
298 REQMAP_TIM(TIM5, CH3),
299 REQMAP_TIM(TIM5, CH4),
300 REQMAP_TIM(TIM8, CH1),
301 REQMAP_TIM(TIM8, CH2),
302 REQMAP_TIM(TIM8, CH3),
303 REQMAP_TIM(TIM8, CH4),
304 REQMAP_TIM(TIM15, CH1),
305 REQMAP_TIM(TIM16, CH1),
306 REQMAP_TIM(TIM17, CH1),
309 #undef TC
310 #undef REQMAP_TIM
312 #define DMA(d, s) { DMA_CODE(d, s, 0), (dmaResource_t *)DMA ## d ## _Stream ## s, 0 }
314 static dmaChannelSpec_t dmaChannelSpec[MAX_PERIPHERAL_DMA_OPTIONS] = {
315 DMA(1, 0),
316 DMA(1, 1),
317 DMA(1, 2),
318 DMA(1, 3),
319 DMA(1, 4),
320 DMA(1, 5),
321 DMA(1, 6),
322 DMA(1, 7),
323 DMA(2, 0),
324 DMA(2, 1),
325 DMA(2, 2),
326 DMA(2, 3),
327 DMA(2, 4),
328 DMA(2, 5),
329 DMA(2, 6),
330 DMA(2, 7),
333 #undef DMA
335 #elif defined(STM32F4) || defined(STM32F7)
337 #if defined(STM32F4)
338 #define DMA(d, s, c) { DMA_CODE(d, s, c), (dmaResource_t *)DMA ## d ## _Stream ## s, DMA_Channel_ ## c }
339 #elif defined(STM32F7)
340 #define DMA(d, s, c) { DMA_CODE(d, s, c), (dmaResource_t *)DMA ## d ## _Stream ## s, DMA_CHANNEL_ ## c }
341 #endif
343 static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
344 #ifdef USE_SPI
345 // Everything including F405 and F446
346 { DMA_PERIPH_SPI_TX, SPIDEV_1, { DMA(2, 3, 3), DMA(2, 5, 3) } },
347 { DMA_PERIPH_SPI_RX, SPIDEV_1, { DMA(2, 0, 3), DMA(2, 2, 3) } },
348 { DMA_PERIPH_SPI_TX, SPIDEV_2, { DMA(1, 4, 0) } },
349 { DMA_PERIPH_SPI_RX, SPIDEV_2, { DMA(1, 3, 0) } },
350 { DMA_PERIPH_SPI_TX, SPIDEV_3, { DMA(1, 5, 0), DMA(1, 7, 0) } },
351 { DMA_PERIPH_SPI_RX, SPIDEV_3, { DMA(1, 0, 0), DMA(1, 2, 0) } },
353 #if defined(STM32F411xE) || defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx) || defined(STM32F722xx)
354 { DMA_PERIPH_SPI_TX, SPIDEV_4, { DMA(2, 1, 4) } },
355 { DMA_PERIPH_SPI_RX, SPIDEV_4, { DMA(2, 0, 4) } },
357 #ifdef USE_EXTENDED_SPI_DEVICE
358 { DMA_PERIPH_SPI_TX, SPIDEV_5, { DMA(2, 6, 7) } },
359 { DMA_PERIPH_SPI_RX, SPIDEV_5, { DMA(2, 5, 7) } },
361 #if !defined(STM32F722xx)
362 { DMA_PERIPH_SPI_TX, SPIDEV_6, { DMA(2, 5, 1) } },
363 { DMA_PERIPH_SPI_RX, SPIDEV_6, { DMA(2, 6, 1) } },
364 #endif
365 #endif // USE_EXTENDED_SPI_DEVICE
366 #endif
367 #endif // USE_SPI
369 #ifdef USE_ADC
370 { DMA_PERIPH_ADC, ADCDEV_1, { DMA(2, 0, 0), DMA(2, 4, 0) } },
371 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 2, 1), DMA(2, 3, 1) } },
372 { DMA_PERIPH_ADC, ADCDEV_3, { DMA(2, 0, 2), DMA(2, 1, 2) } },
373 #endif
375 #ifdef USE_SDCARD_SDIO
376 { DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
377 #endif
379 #ifdef USE_UART
380 { DMA_PERIPH_UART_TX, UARTDEV_1, { DMA(2, 7, 4) } },
381 { DMA_PERIPH_UART_RX, UARTDEV_1, { DMA(2, 5, 4), DMA(2, 2, 4) } },
382 { DMA_PERIPH_UART_TX, UARTDEV_2, { DMA(1, 6, 4) } },
383 { DMA_PERIPH_UART_RX, UARTDEV_2, { DMA(1, 5, 4) } },
384 { DMA_PERIPH_UART_TX, UARTDEV_3, { DMA(1, 3, 4) } },
385 { DMA_PERIPH_UART_RX, UARTDEV_3, { DMA(1, 1, 4) } },
386 { DMA_PERIPH_UART_TX, UARTDEV_4, { DMA(1, 4, 4) } },
387 { DMA_PERIPH_UART_RX, UARTDEV_4, { DMA(1, 2, 4) } },
388 { DMA_PERIPH_UART_TX, UARTDEV_5, { DMA(1, 7, 4) } },
389 { DMA_PERIPH_UART_RX, UARTDEV_5, { DMA(1, 0, 4) } },
390 { DMA_PERIPH_UART_TX, UARTDEV_6, { DMA(2, 6, 5), DMA(2, 7, 5) } },
391 { DMA_PERIPH_UART_RX, UARTDEV_6, { DMA(2, 1, 5), DMA(2, 2, 5) } },
392 #endif
395 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
397 static const dmaTimerMapping_t dmaTimerMapping[] = {
398 // Generated from 'timer_def.h'
399 { TIM1, TC(CH1), { DMA(2, 6, 0), DMA(2, 1, 6), DMA(2, 3, 6) } },
400 { TIM1, TC(CH2), { DMA(2, 6, 0), DMA(2, 2, 6) } },
401 { TIM1, TC(CH3), { DMA(2, 6, 0), DMA(2, 6, 6) } },
402 { TIM1, TC(CH4), { DMA(2, 4, 6) } },
404 { TIM2, TC(CH1), { DMA(1, 5, 3) } },
405 { TIM2, TC(CH2), { DMA(1, 6, 3) } },
406 { TIM2, TC(CH3), { DMA(1, 1, 3) } },
407 { TIM2, TC(CH4), { DMA(1, 7, 3), DMA(1, 6, 3) } },
409 { TIM3, TC(CH1), { DMA(1, 4, 5) } },
410 { TIM3, TC(CH2), { DMA(1, 5, 5) } },
411 { TIM3, TC(CH3), { DMA(1, 7, 5) } },
412 { TIM3, TC(CH4), { DMA(1, 2, 5) } },
414 { TIM4, TC(CH1), { DMA(1, 0, 2) } },
415 { TIM4, TC(CH2), { DMA(1, 3, 2) } },
416 { TIM4, TC(CH3), { DMA(1, 7, 2) } },
418 { TIM5, TC(CH1), { DMA(1, 2, 6) } },
419 { TIM5, TC(CH2), { DMA(1, 4, 6) } },
420 { TIM5, TC(CH3), { DMA(1, 0, 6) } },
421 { TIM5, TC(CH4), { DMA(1, 1, 6), DMA(1, 3, 6) } },
423 { TIM8, TC(CH1), { DMA(2, 2, 0), DMA(2, 2, 7) } },
424 { TIM8, TC(CH2), { DMA(2, 2, 0), DMA(2, 3, 7) } },
425 { TIM8, TC(CH3), { DMA(2, 2, 0), DMA(2, 4, 7) } },
426 { TIM8, TC(CH4), { DMA(2, 7, 7) } },
428 #undef TC
429 #undef DMA
431 #else // STM32F3
432 // The embedded ADC24_DMA_REMAP conditional should be removed
433 // when (and if) F3 is going generic.
434 #define DMA(d, c) { DMA_CODE(d, 0, c), (dmaResource_t *)DMA ## d ## _Channel ## c }
435 static const dmaPeripheralMapping_t dmaPeripheralMapping[18] = {
436 #ifdef USE_SPI
437 { DMA_PERIPH_SPI_TX, SPIDEV_1, { DMA(1, 3) } },
438 { DMA_PERIPH_SPI_RX, SPIDEV_1, { DMA(1, 2) } },
439 { DMA_PERIPH_SPI_TX, SPIDEV_2, { DMA(1, 5) } },
440 { DMA_PERIPH_SPI_RX, SPIDEV_2, { DMA(1, 4) } },
441 { DMA_PERIPH_SPI_TX, SPIDEV_3, { DMA(2, 2) } },
442 { DMA_PERIPH_SPI_RX, SPIDEV_3, { DMA(2, 1) } },
443 #endif
445 #ifdef USE_ADC
446 { DMA_PERIPH_ADC, ADCDEV_1, { DMA(1, 1) } },
447 #ifdef ADC24_DMA_REMAP
448 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 3) } },
449 #else
450 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 1) } },
451 #endif
452 { DMA_PERIPH_ADC, ADCDEV_3, { DMA(2, 5) } },
453 #ifdef ADC24_DMA_REMAP
454 { DMA_PERIPH_ADC, ADCDEV_4, { DMA(2, 4) } },
455 #else
456 { DMA_PERIPH_ADC, ADCDEV_4, { DMA(2, 2) } },
457 #endif
458 #endif
460 #ifdef USE_UART
461 { DMA_PERIPH_UART_TX, UARTDEV_1, { DMA(1, 4) } },
462 { DMA_PERIPH_UART_RX, UARTDEV_1, { DMA(1, 5) } },
464 { DMA_PERIPH_UART_TX, UARTDEV_2, { DMA(1, 7) } },
465 { DMA_PERIPH_UART_RX, UARTDEV_2, { DMA(1, 6) } },
466 { DMA_PERIPH_UART_TX, UARTDEV_3, { DMA(1, 2) } },
467 { DMA_PERIPH_UART_RX, UARTDEV_3, { DMA(1, 3) } },
468 { DMA_PERIPH_UART_TX, UARTDEV_4, { DMA(2, 5) } },
469 { DMA_PERIPH_UART_RX, UARTDEV_4, { DMA(2, 3) } },
471 #endif
473 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
475 static const dmaTimerMapping_t dmaTimerMapping[] = {
476 // Generated from 'timer_def.h'
477 { TIM1, TC(CH1), { DMA(1, 2) } },
478 { TIM1, TC(CH2), { DMA(1, 3) } },
479 { TIM1, TC(CH3), { DMA(1, 6) } },
480 { TIM1, TC(CH4), { DMA(1, 4) } },
482 { TIM2, TC(CH1), { DMA(1, 5) } },
483 { TIM2, TC(CH2), { DMA(1, 7) } },
484 { TIM2, TC(CH3), { DMA(1, 1) } },
485 { TIM2, TC(CH4), { DMA(1, 7) } },
487 { TIM3, TC(CH1), { DMA(1, 6) } },
488 { TIM3, TC(CH3), { DMA(1, 2) } },
489 { TIM3, TC(CH4), { DMA(1, 3) } },
491 { TIM4, TC(CH1), { DMA(1, 1) } },
492 { TIM4, TC(CH2), { DMA(1, 4) } },
493 { TIM4, TC(CH3), { DMA(1, 5) } },
495 { TIM8, TC(CH1), { DMA(2, 3) } },
496 { TIM8, TC(CH2), { DMA(2, 5) } },
497 { TIM8, TC(CH3), { DMA(2, 1) } },
498 { TIM8, TC(CH4), { DMA(2, 2) } },
500 { TIM15, TC(CH1), { DMA(1, 5) } },
502 #ifdef REMAP_TIM16_DMA
503 { TIM16, TC(CH1), { DMA(1, 6) } },
504 #else
505 { TIM16, TC(CH1), { DMA(1, 3) } },
506 #endif
508 #ifdef REMAP_TIM17_DMA
509 { TIM17, TC(CH1), { DMA(1, 7) } },
510 #else
511 { TIM17, TC(CH1), { DMA(1, 1) } },
512 #endif
515 #undef TC
516 #undef DMA
517 #endif
519 #if defined(STM32H7) || defined(STM32G4)
520 static void dmaSetupRequest(dmaChannelSpec_t *dmaSpec, uint8_t request)
522 // Setup request as channel
523 dmaSpec->channel = request;
525 // Insert DMA request into code
526 dmaCode_t code = dmaSpec->code;
527 dmaSpec->code = DMA_CODE(DMA_CODE_CONTROLLER(code), DMA_CODE_STREAM(code), dmaSpec->channel);
529 #endif
531 const dmaChannelSpec_t *dmaGetChannelSpecByPeripheral(dmaPeripheral_e device, uint8_t index, int8_t opt)
533 if (opt < 0 || opt >= MAX_PERIPHERAL_DMA_OPTIONS) {
534 return NULL;
537 for (unsigned i = 0 ; i < ARRAYLEN(dmaPeripheralMapping) ; i++) {
538 const dmaPeripheralMapping_t *periph = &dmaPeripheralMapping[i];
539 #if defined(STM32H7) || defined(STM32G4)
540 if (periph->device == device && periph->index == index) {
541 dmaChannelSpec_t *dmaSpec = &dmaChannelSpec[opt];
542 dmaSetupRequest(dmaSpec, periph->dmaRequest);
543 return dmaSpec;
545 #else
546 if (periph->device == device && periph->index == index && periph->channelSpec[opt].ref) {
547 return &periph->channelSpec[opt];
549 #endif
552 return NULL;
555 dmaoptValue_t dmaoptByTag(ioTag_t ioTag)
557 #ifdef USE_TIMER_MGMT
558 for (unsigned i = 0; i < MAX_TIMER_PINMAP_COUNT; i++) {
559 if (timerIOConfig(i)->ioTag == ioTag) {
560 return timerIOConfig(i)->dmaopt;
563 #else
564 UNUSED(ioTag);
565 #endif
567 return DMA_OPT_UNUSED;
570 const dmaChannelSpec_t *dmaGetChannelSpecByTimerValue(TIM_TypeDef *tim, uint8_t channel, dmaoptValue_t dmaopt)
572 if (dmaopt < 0 || dmaopt >= MAX_TIMER_DMA_OPTIONS) {
573 return NULL;
576 for (unsigned i = 0 ; i < ARRAYLEN(dmaTimerMapping) ; i++) {
577 const dmaTimerMapping_t *timerMapping = &dmaTimerMapping[i];
578 #if defined(STM32H7) || defined(STM32G4)
579 if (timerMapping->tim == tim && timerMapping->channel == channel) {
580 dmaChannelSpec_t *dmaSpec = &dmaChannelSpec[dmaopt];
581 dmaSetupRequest(dmaSpec, timerMapping->dmaRequest);
582 return dmaSpec;
584 #else
585 if (timerMapping->tim == tim && timerMapping->channel == channel && timerMapping->channelSpec[dmaopt].ref) {
586 return &timerMapping->channelSpec[dmaopt];
588 #endif
591 return NULL;
594 const dmaChannelSpec_t *dmaGetChannelSpecByTimer(const timerHardware_t *timer)
596 if (!timer) {
597 return NULL;
600 dmaoptValue_t dmaopt = dmaoptByTag(timer->tag);
601 return dmaGetChannelSpecByTimerValue(timer->tim, timer->channel, dmaopt);
604 // dmaGetOptionByTimer is called by pgResetFn_timerIOConfig to find out dmaopt for pre-configured timer.
606 dmaoptValue_t dmaGetOptionByTimer(const timerHardware_t *timer)
608 #if defined(STM32H7) || defined(STM32G4)
609 for (unsigned opt = 0; opt < ARRAYLEN(dmaChannelSpec); opt++) {
610 if (timer->dmaRefConfigured == dmaChannelSpec[opt].ref) {
611 return (dmaoptValue_t)opt;
614 #else
615 for (unsigned i = 0 ; i < ARRAYLEN(dmaTimerMapping); i++) {
616 const dmaTimerMapping_t *timerMapping = &dmaTimerMapping[i];
617 if (timerMapping->tim == timer->tim && timerMapping->channel == timer->channel) {
618 for (unsigned j = 0; j < MAX_TIMER_DMA_OPTIONS; j++) {
619 const dmaChannelSpec_t *dma = &timerMapping->channelSpec[j];
620 if (dma->ref == timer->dmaRefConfigured
621 #if defined(STM32F4) || defined(STM32F7)
622 && dma->channel == timer->dmaChannelConfigured
623 #endif
625 return j;
630 #endif
632 return DMA_OPT_UNUSED;
635 #if defined(STM32H7) || defined(STM32G4)
636 // A variant of dmaGetOptionByTimer that looks for matching dmaTimUPRef
637 dmaoptValue_t dmaGetUpOptionByTimer(const timerHardware_t *timer)
639 for (unsigned opt = 0; opt < ARRAYLEN(dmaChannelSpec); opt++) {
640 if (timer->dmaTimUPRef == dmaChannelSpec[opt].ref) {
641 return (dmaoptValue_t)opt;
645 return DMA_OPT_UNUSED;
647 #endif
649 #endif // USE_DMA_SPEC