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)
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/>.
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
;
40 #if defined(STM32H7) || defined(STM32G4)
43 dmaChannelSpec_t channelSpec
[MAX_PERIPHERAL_DMA_OPTIONS
];
45 } dmaPeripheralMapping_t
;
47 typedef struct dmaTimerMapping_s
{
50 #if defined(STM32H7) || defined(STM32G4)
53 dmaChannelSpec_t channelSpec
[MAX_TIMER_DMA_OPTIONS
];
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
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
72 // Resolve our preference for MOSI/MISO rather than TX/RX
73 #define DMA_REQUEST_SPI1_MOSI DMA_REQUEST_SPI1_TX
74 #define DMA_REQUEST_SPI1_MISO DMA_REQUEST_SPI1_RX
75 #define DMA_REQUEST_SPI2_MOSI DMA_REQUEST_SPI2_TX
76 #define DMA_REQUEST_SPI2_MISO DMA_REQUEST_SPI2_RX
77 #define DMA_REQUEST_SPI3_MOSI DMA_REQUEST_SPI3_TX
78 #define DMA_REQUEST_SPI3_MISO DMA_REQUEST_SPI3_RX
79 #define DMA_REQUEST_SPI4_MOSI DMA_REQUEST_SPI4_TX
80 #define DMA_REQUEST_SPI4_MISO DMA_REQUEST_SPI4_RX
82 static const dmaPeripheralMapping_t dmaPeripheralMapping
[] = {
84 REQMAP_DIR(SPI
, 1, MOSI
),
85 REQMAP_DIR(SPI
, 1, MISO
),
86 REQMAP_DIR(SPI
, 2, MOSI
),
87 REQMAP_DIR(SPI
, 2, MISO
),
88 REQMAP_DIR(SPI
, 3, MOSI
),
89 REQMAP_DIR(SPI
, 3, MISO
),
90 REQMAP_DIR(SPI
, 4, MOSI
),
91 REQMAP_DIR(SPI
, 4, MISO
),
103 REQMAP_DIR(UART
, 1, TX
),
104 REQMAP_DIR(UART
, 1, RX
),
105 REQMAP_DIR(UART
, 2, TX
),
106 REQMAP_DIR(UART
, 2, RX
),
107 REQMAP_DIR(UART
, 3, TX
),
108 REQMAP_DIR(UART
, 3, RX
),
109 REQMAP_DIR(UART
, 4, TX
),
110 REQMAP_DIR(UART
, 4, RX
),
111 REQMAP_DIR(UART
, 5, TX
),
112 REQMAP_DIR(UART
, 5, RX
),
114 { DMA_PERIPH_UART_TX
, LPUARTDEV_1
, DMA_REQUEST_LPUART1_TX
},
115 { DMA_PERIPH_UART_RX
, LPUARTDEV_1
, DMA_REQUEST_LPUART1_RX
},
120 // Pseudo peripheral for TIMx_UP channel
121 REQMAP_TIMUP(TIMUP
, 1),
122 REQMAP_TIMUP(TIMUP
, 2),
123 REQMAP_TIMUP(TIMUP
, 3),
124 REQMAP_TIMUP(TIMUP
, 4),
125 REQMAP_TIMUP(TIMUP
, 5),
126 REQMAP_TIMUP(TIMUP
, 6),
127 REQMAP_TIMUP(TIMUP
, 7),
128 REQMAP_TIMUP(TIMUP
, 8),
129 REQMAP_TIMUP(TIMUP
, 15),
130 REQMAP_TIMUP(TIMUP
, 16),
131 REQMAP_TIMUP(TIMUP
, 17),
132 REQMAP_TIMUP(TIMUP
, 20),
141 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
143 #define REQMAP_TIM(tim, chan) { tim, TC(chan), DMA_REQUEST_ ## tim ## _ ## chan }
145 static const dmaTimerMapping_t dmaTimerMapping
[] = {
146 REQMAP_TIM(TIM1
, CH1
),
147 REQMAP_TIM(TIM1
, CH2
),
148 REQMAP_TIM(TIM1
, CH3
),
149 REQMAP_TIM(TIM1
, CH4
),
150 REQMAP_TIM(TIM2
, CH1
),
151 REQMAP_TIM(TIM2
, CH2
),
152 REQMAP_TIM(TIM2
, CH3
),
153 REQMAP_TIM(TIM2
, CH4
),
154 REQMAP_TIM(TIM3
, CH1
),
155 REQMAP_TIM(TIM3
, CH2
),
156 REQMAP_TIM(TIM3
, CH3
),
157 REQMAP_TIM(TIM3
, CH4
),
158 REQMAP_TIM(TIM4
, CH1
),
159 REQMAP_TIM(TIM4
, CH2
),
160 REQMAP_TIM(TIM4
, CH3
),
161 REQMAP_TIM(TIM5
, CH1
),
162 REQMAP_TIM(TIM5
, CH2
),
163 REQMAP_TIM(TIM5
, CH3
),
164 REQMAP_TIM(TIM5
, CH4
),
165 REQMAP_TIM(TIM8
, CH1
),
166 REQMAP_TIM(TIM8
, CH2
),
167 REQMAP_TIM(TIM8
, CH3
),
168 REQMAP_TIM(TIM8
, CH4
),
169 REQMAP_TIM(TIM15
, CH1
),
170 REQMAP_TIM(TIM16
, CH1
),
171 REQMAP_TIM(TIM17
, CH1
),
172 REQMAP_TIM(TIM20
, CH1
),
173 REQMAP_TIM(TIM20
, CH2
),
174 REQMAP_TIM(TIM20
, CH3
),
175 REQMAP_TIM(TIM20
, CH4
),
176 // XXX Check non-CH1 for TIM15,16,17 and 20
182 #define DMA(d, c) { DMA_CODE(d, c, 0), (dmaResource_t *)DMA ## d ## _Channel ## c, 0 }
184 static dmaChannelSpec_t dmaChannelSpec
[MAX_PERIPHERAL_DMA_OPTIONS
] = {
205 #elif defined(STM32H7)
207 #define REQMAP_SGL(periph) { DMA_PERIPH_ ## periph, 0, DMA_REQUEST_ ## periph }
208 #define REQMAP(periph, device) { DMA_PERIPH_ ## periph, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device }
209 #define REQMAP_DIR(periph, device, dir) { DMA_PERIPH_ ## periph ## _ ## dir, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device ## _ ## dir }
210 #define REQMAP_TIMUP(periph, timno) { DMA_PERIPH_TIMUP, timno - 1, DMA_REQUEST_ ## TIM ## timno ## _UP }
212 // Resolve UART/USART mess
213 #define DMA_REQUEST_UART1_RX DMA_REQUEST_USART1_RX
214 #define DMA_REQUEST_UART1_TX DMA_REQUEST_USART1_TX
215 #define DMA_REQUEST_UART2_RX DMA_REQUEST_USART2_RX
216 #define DMA_REQUEST_UART2_TX DMA_REQUEST_USART2_TX
217 #define DMA_REQUEST_UART3_RX DMA_REQUEST_USART3_RX
218 #define DMA_REQUEST_UART3_TX DMA_REQUEST_USART3_TX
219 #define DMA_REQUEST_UART6_RX DMA_REQUEST_USART6_RX
220 #define DMA_REQUEST_UART6_TX DMA_REQUEST_USART6_TX
221 #define DMA_REQUEST_UART10_RX DMA_REQUEST_USART10_RX
222 #define DMA_REQUEST_UART10_TX DMA_REQUEST_USART10_TX
224 // Resolve our preference for MOSI/MISO rather than TX/RX
225 #define DMA_REQUEST_SPI1_MOSI DMA_REQUEST_SPI1_TX
226 #define DMA_REQUEST_SPI1_MISO DMA_REQUEST_SPI1_RX
227 #define DMA_REQUEST_SPI2_MOSI DMA_REQUEST_SPI2_TX
228 #define DMA_REQUEST_SPI2_MISO DMA_REQUEST_SPI2_RX
229 #define DMA_REQUEST_SPI3_MOSI DMA_REQUEST_SPI3_TX
230 #define DMA_REQUEST_SPI3_MISO DMA_REQUEST_SPI3_RX
231 #define DMA_REQUEST_SPI4_MOSI DMA_REQUEST_SPI4_TX
232 #define DMA_REQUEST_SPI4_MISO DMA_REQUEST_SPI4_RX
233 #define DMA_REQUEST_SPI5_MOSI DMA_REQUEST_SPI5_TX
234 #define DMA_REQUEST_SPI5_MISO DMA_REQUEST_SPI5_RX
236 static const dmaPeripheralMapping_t dmaPeripheralMapping
[] = {
238 REQMAP_DIR(SPI
, 1, MOSI
),
239 REQMAP_DIR(SPI
, 1, MISO
),
240 REQMAP_DIR(SPI
, 2, MOSI
),
241 REQMAP_DIR(SPI
, 2, MISO
),
242 REQMAP_DIR(SPI
, 3, MOSI
),
243 REQMAP_DIR(SPI
, 3, MISO
),
244 REQMAP_DIR(SPI
, 4, MOSI
),
245 REQMAP_DIR(SPI
, 4, MISO
),
246 REQMAP_DIR(SPI
, 5, MOSI
), // Not available in smaller packages
247 REQMAP_DIR(SPI
, 5, MISO
), // ditto
248 // REQMAP_DIR(SPI, 6, MOSI), // SPI6 is on BDMA (todo)
249 // REQMAP_DIR(SPI, 6, MOSI), // ditto
255 #if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H725xx) || defined(STM32H730xx)
261 REQMAP_DIR(UART
, 1, TX
),
262 REQMAP_DIR(UART
, 1, RX
),
263 REQMAP_DIR(UART
, 2, TX
),
264 REQMAP_DIR(UART
, 2, RX
),
265 REQMAP_DIR(UART
, 3, TX
),
266 REQMAP_DIR(UART
, 3, RX
),
267 REQMAP_DIR(UART
, 4, TX
),
268 REQMAP_DIR(UART
, 4, RX
),
269 REQMAP_DIR(UART
, 5, TX
),
270 REQMAP_DIR(UART
, 5, RX
),
271 REQMAP_DIR(UART
, 6, TX
),
272 REQMAP_DIR(UART
, 6, RX
),
273 REQMAP_DIR(UART
, 7, TX
),
274 REQMAP_DIR(UART
, 7, RX
),
275 REQMAP_DIR(UART
, 8, TX
),
276 REQMAP_DIR(UART
, 8, RX
),
277 #if defined(STM32H7A3xxQ)
278 REQMAP_DIR(UART
, 9, TX
),
279 REQMAP_DIR(UART
, 9, RX
),
280 REQMAP_DIR(UART
, 10, TX
),
281 REQMAP_DIR(UART
, 10, RX
),
284 { DMA_PERIPH_UART_TX
, LPUARTDEV_1
, BDMA_REQUEST_LPUART1_TX
},
285 { DMA_PERIPH_UART_RX
, LPUARTDEV_1
, BDMA_REQUEST_LPUART1_RX
},
290 // Pseudo peripheral for TIMx_UP channel
291 REQMAP_TIMUP(TIMUP
, 1),
292 REQMAP_TIMUP(TIMUP
, 2),
293 REQMAP_TIMUP(TIMUP
, 3),
294 REQMAP_TIMUP(TIMUP
, 4),
295 REQMAP_TIMUP(TIMUP
, 5),
296 REQMAP_TIMUP(TIMUP
, 6),
297 REQMAP_TIMUP(TIMUP
, 7),
298 REQMAP_TIMUP(TIMUP
, 8),
299 REQMAP_TIMUP(TIMUP
, 15),
300 REQMAP_TIMUP(TIMUP
, 16),
301 REQMAP_TIMUP(TIMUP
, 17),
310 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
312 #define REQMAP_TIM(tim, chan) { tim, TC(chan), DMA_REQUEST_ ## tim ## _ ## chan }
314 static const dmaTimerMapping_t dmaTimerMapping
[] = {
315 REQMAP_TIM(TIM1
, CH1
),
316 REQMAP_TIM(TIM1
, CH2
),
317 REQMAP_TIM(TIM1
, CH3
),
318 REQMAP_TIM(TIM1
, CH4
),
319 REQMAP_TIM(TIM2
, CH1
),
320 REQMAP_TIM(TIM2
, CH2
),
321 REQMAP_TIM(TIM2
, CH3
),
322 REQMAP_TIM(TIM2
, CH4
),
323 REQMAP_TIM(TIM3
, CH1
),
324 REQMAP_TIM(TIM3
, CH2
),
325 REQMAP_TIM(TIM3
, CH3
),
326 REQMAP_TIM(TIM3
, CH4
),
327 REQMAP_TIM(TIM4
, CH1
),
328 REQMAP_TIM(TIM4
, CH2
),
329 REQMAP_TIM(TIM4
, CH3
),
330 REQMAP_TIM(TIM5
, CH1
),
331 REQMAP_TIM(TIM5
, CH2
),
332 REQMAP_TIM(TIM5
, CH3
),
333 REQMAP_TIM(TIM5
, CH4
),
334 REQMAP_TIM(TIM8
, CH1
),
335 REQMAP_TIM(TIM8
, CH2
),
336 REQMAP_TIM(TIM8
, CH3
),
337 REQMAP_TIM(TIM8
, CH4
),
338 REQMAP_TIM(TIM15
, CH1
),
339 REQMAP_TIM(TIM16
, CH1
),
340 REQMAP_TIM(TIM17
, CH1
),
346 #define DMA(d, s) { DMA_CODE(d, s, 0), (dmaResource_t *)DMA ## d ## _Stream ## s, 0 }
348 static dmaChannelSpec_t dmaChannelSpec
[MAX_PERIPHERAL_DMA_OPTIONS
] = {
369 #elif defined(STM32F4) || defined(STM32F7)
372 #define DMA(d, s, c) { DMA_CODE(d, s, c), (dmaResource_t *)DMA ## d ## _Stream ## s, DMA_Channel_ ## c }
373 #elif defined(STM32F7)
374 #define DMA(d, s, c) { DMA_CODE(d, s, c), (dmaResource_t *)DMA ## d ## _Stream ## s, DMA_CHANNEL_ ## c }
377 static const dmaPeripheralMapping_t dmaPeripheralMapping
[] = {
379 // Everything including F405 and F446
380 { DMA_PERIPH_SPI_MOSI
, SPIDEV_1
, { DMA(2, 3, 3), DMA(2, 5, 3) } },
381 { DMA_PERIPH_SPI_MISO
, SPIDEV_1
, { DMA(2, 0, 3), DMA(2, 2, 3) } },
382 { DMA_PERIPH_SPI_MOSI
, SPIDEV_2
, { DMA(1, 4, 0) } },
383 { DMA_PERIPH_SPI_MISO
, SPIDEV_2
, { DMA(1, 3, 0) } },
384 { DMA_PERIPH_SPI_MOSI
, SPIDEV_3
, { DMA(1, 5, 0), DMA(1, 7, 0) } },
385 { DMA_PERIPH_SPI_MISO
, SPIDEV_3
, { DMA(1, 0, 0), DMA(1, 2, 0) } },
387 #if defined(STM32F411xE) || defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx) || defined(STM32F722xx)
388 { DMA_PERIPH_SPI_MOSI
, SPIDEV_4
, { DMA(2, 1, 4) } },
389 { DMA_PERIPH_SPI_MISO
, SPIDEV_4
, { DMA(2, 0, 4) } },
391 #ifdef USE_EXTENDED_SPI_DEVICE
392 { DMA_PERIPH_SPI_MOSI
, SPIDEV_5
, { DMA(2, 6, 7) } },
393 { DMA_PERIPH_SPI_MISO
, SPIDEV_5
, { DMA(2, 5, 7) } },
395 #if !defined(STM32F722xx)
396 { DMA_PERIPH_SPI_MOSI
, SPIDEV_6
, { DMA(2, 5, 1) } },
397 { DMA_PERIPH_SPI_MISO
, SPIDEV_6
, { DMA(2, 6, 1) } },
399 #endif // USE_EXTENDED_SPI_DEVICE
404 { DMA_PERIPH_ADC
, ADCDEV_1
, { DMA(2, 0, 0), DMA(2, 4, 0) } },
405 { DMA_PERIPH_ADC
, ADCDEV_2
, { DMA(2, 2, 1), DMA(2, 3, 1) } },
406 { DMA_PERIPH_ADC
, ADCDEV_3
, { DMA(2, 0, 2), DMA(2, 1, 2) } },
409 #ifdef USE_SDCARD_SDIO
410 { DMA_PERIPH_SDIO
, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
414 { DMA_PERIPH_UART_TX
, UARTDEV_1
, { DMA(2, 7, 4) } },
415 { DMA_PERIPH_UART_RX
, UARTDEV_1
, { DMA(2, 5, 4), DMA(2, 2, 4) } },
416 { DMA_PERIPH_UART_TX
, UARTDEV_2
, { DMA(1, 6, 4) } },
417 { DMA_PERIPH_UART_RX
, UARTDEV_2
, { DMA(1, 5, 4) } },
418 { DMA_PERIPH_UART_TX
, UARTDEV_3
, { DMA(1, 3, 4) } },
419 { DMA_PERIPH_UART_RX
, UARTDEV_3
, { DMA(1, 1, 4) } },
420 { DMA_PERIPH_UART_TX
, UARTDEV_4
, { DMA(1, 4, 4) } },
421 { DMA_PERIPH_UART_RX
, UARTDEV_4
, { DMA(1, 2, 4) } },
422 { DMA_PERIPH_UART_TX
, UARTDEV_5
, { DMA(1, 7, 4) } },
423 { DMA_PERIPH_UART_RX
, UARTDEV_5
, { DMA(1, 0, 4) } },
424 { DMA_PERIPH_UART_TX
, UARTDEV_6
, { DMA(2, 6, 5), DMA(2, 7, 5) } },
425 { DMA_PERIPH_UART_RX
, UARTDEV_6
, { DMA(2, 1, 5), DMA(2, 2, 5) } },
429 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
431 static const dmaTimerMapping_t dmaTimerMapping
[] = {
432 // Generated from 'timer_def.h'
433 { TIM1
, TC(CH1
), { DMA(2, 6, 0), DMA(2, 1, 6), DMA(2, 3, 6) } },
434 { TIM1
, TC(CH2
), { DMA(2, 6, 0), DMA(2, 2, 6) } },
435 { TIM1
, TC(CH3
), { DMA(2, 6, 0), DMA(2, 6, 6) } },
436 { TIM1
, TC(CH4
), { DMA(2, 4, 6) } },
438 { TIM2
, TC(CH1
), { DMA(1, 5, 3) } },
439 { TIM2
, TC(CH2
), { DMA(1, 6, 3) } },
440 { TIM2
, TC(CH3
), { DMA(1, 1, 3) } },
441 { TIM2
, TC(CH4
), { DMA(1, 7, 3), DMA(1, 6, 3) } },
443 { TIM3
, TC(CH1
), { DMA(1, 4, 5) } },
444 { TIM3
, TC(CH2
), { DMA(1, 5, 5) } },
445 { TIM3
, TC(CH3
), { DMA(1, 7, 5) } },
446 { TIM3
, TC(CH4
), { DMA(1, 2, 5) } },
448 { TIM4
, TC(CH1
), { DMA(1, 0, 2) } },
449 { TIM4
, TC(CH2
), { DMA(1, 3, 2) } },
450 { TIM4
, TC(CH3
), { DMA(1, 7, 2) } },
452 { TIM5
, TC(CH1
), { DMA(1, 2, 6) } },
453 { TIM5
, TC(CH2
), { DMA(1, 4, 6) } },
454 { TIM5
, TC(CH3
), { DMA(1, 0, 6) } },
455 { TIM5
, TC(CH4
), { DMA(1, 1, 6), DMA(1, 3, 6) } },
457 { TIM8
, TC(CH1
), { DMA(2, 2, 0), DMA(2, 2, 7) } },
458 { TIM8
, TC(CH2
), { DMA(2, 2, 0), DMA(2, 3, 7) } },
459 { TIM8
, TC(CH3
), { DMA(2, 2, 0), DMA(2, 4, 7) } },
460 { TIM8
, TC(CH4
), { DMA(2, 7, 7) } },
466 // The embedded ADC24_DMA_REMAP conditional should be removed
467 // when (and if) F3 is going generic.
468 #define DMA(d, c) { DMA_CODE(d, 0, c), (dmaResource_t *)DMA ## d ## _Channel ## c }
469 static const dmaPeripheralMapping_t dmaPeripheralMapping
[18] = {
471 { DMA_PERIPH_SPI_MOSI
, SPIDEV_1
, { DMA(1, 3) } },
472 { DMA_PERIPH_SPI_MISO
, SPIDEV_1
, { DMA(1, 2) } },
473 { DMA_PERIPH_SPI_MOSI
, SPIDEV_2
, { DMA(1, 5) } },
474 { DMA_PERIPH_SPI_MISO
, SPIDEV_2
, { DMA(1, 4) } },
475 { DMA_PERIPH_SPI_MOSI
, SPIDEV_3
, { DMA(2, 2) } },
476 { DMA_PERIPH_SPI_MISO
, SPIDEV_3
, { DMA(2, 1) } },
480 { DMA_PERIPH_ADC
, ADCDEV_1
, { DMA(1, 1) } },
481 #ifdef ADC24_DMA_REMAP
482 { DMA_PERIPH_ADC
, ADCDEV_2
, { DMA(2, 3) } },
484 { DMA_PERIPH_ADC
, ADCDEV_2
, { DMA(2, 1) } },
486 { DMA_PERIPH_ADC
, ADCDEV_3
, { DMA(2, 5) } },
487 #ifdef ADC24_DMA_REMAP
488 { DMA_PERIPH_ADC
, ADCDEV_4
, { DMA(2, 4) } },
490 { DMA_PERIPH_ADC
, ADCDEV_4
, { DMA(2, 2) } },
495 { DMA_PERIPH_UART_TX
, UARTDEV_1
, { DMA(1, 4) } },
496 { DMA_PERIPH_UART_RX
, UARTDEV_1
, { DMA(1, 5) } },
498 { DMA_PERIPH_UART_TX
, UARTDEV_2
, { DMA(1, 7) } },
499 { DMA_PERIPH_UART_RX
, UARTDEV_2
, { DMA(1, 6) } },
500 { DMA_PERIPH_UART_TX
, UARTDEV_3
, { DMA(1, 2) } },
501 { DMA_PERIPH_UART_RX
, UARTDEV_3
, { DMA(1, 3) } },
502 { DMA_PERIPH_UART_TX
, UARTDEV_4
, { DMA(2, 5) } },
503 { DMA_PERIPH_UART_RX
, UARTDEV_4
, { DMA(2, 3) } },
507 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
509 static const dmaTimerMapping_t dmaTimerMapping
[] = {
510 // Generated from 'timer_def.h'
511 { TIM1
, TC(CH1
), { DMA(1, 2) } },
512 { TIM1
, TC(CH2
), { DMA(1, 3) } },
513 { TIM1
, TC(CH3
), { DMA(1, 6) } },
514 { TIM1
, TC(CH4
), { DMA(1, 4) } },
516 { TIM2
, TC(CH1
), { DMA(1, 5) } },
517 { TIM2
, TC(CH2
), { DMA(1, 7) } },
518 { TIM2
, TC(CH3
), { DMA(1, 1) } },
519 { TIM2
, TC(CH4
), { DMA(1, 7) } },
521 { TIM3
, TC(CH1
), { DMA(1, 6) } },
522 { TIM3
, TC(CH3
), { DMA(1, 2) } },
523 { TIM3
, TC(CH4
), { DMA(1, 3) } },
525 { TIM4
, TC(CH1
), { DMA(1, 1) } },
526 { TIM4
, TC(CH2
), { DMA(1, 4) } },
527 { TIM4
, TC(CH3
), { DMA(1, 5) } },
529 { TIM8
, TC(CH1
), { DMA(2, 3) } },
530 { TIM8
, TC(CH2
), { DMA(2, 5) } },
531 { TIM8
, TC(CH3
), { DMA(2, 1) } },
532 { TIM8
, TC(CH4
), { DMA(2, 2) } },
534 { TIM15
, TC(CH1
), { DMA(1, 5) } },
536 #ifdef REMAP_TIM16_DMA
537 { TIM16
, TC(CH1
), { DMA(1, 6) } },
539 { TIM16
, TC(CH1
), { DMA(1, 3) } },
542 #ifdef REMAP_TIM17_DMA
543 { TIM17
, TC(CH1
), { DMA(1, 7) } },
545 { TIM17
, TC(CH1
), { DMA(1, 1) } },
553 #if defined(STM32H7) || defined(STM32G4)
554 static void dmaSetupRequest(dmaChannelSpec_t
*dmaSpec
, uint8_t request
)
556 // Setup request as channel
557 dmaSpec
->channel
= request
;
559 // Insert DMA request into code
560 dmaCode_t code
= dmaSpec
->code
;
561 dmaSpec
->code
= DMA_CODE(DMA_CODE_CONTROLLER(code
), DMA_CODE_STREAM(code
), dmaSpec
->channel
);
565 const dmaChannelSpec_t
*dmaGetChannelSpecByPeripheral(dmaPeripheral_e device
, uint8_t index
, int8_t opt
)
567 if (opt
< 0 || opt
>= MAX_PERIPHERAL_DMA_OPTIONS
) {
571 for (unsigned i
= 0 ; i
< ARRAYLEN(dmaPeripheralMapping
) ; i
++) {
572 const dmaPeripheralMapping_t
*periph
= &dmaPeripheralMapping
[i
];
573 #if defined(STM32H7) || defined(STM32G4)
574 if (periph
->device
== device
&& periph
->index
== index
) {
575 dmaChannelSpec_t
*dmaSpec
= &dmaChannelSpec
[opt
];
576 dmaSetupRequest(dmaSpec
, periph
->dmaRequest
);
580 if (periph
->device
== device
&& periph
->index
== index
&& periph
->channelSpec
[opt
].ref
) {
581 return &periph
->channelSpec
[opt
];
589 dmaoptValue_t
dmaoptByTag(ioTag_t ioTag
)
591 #ifdef USE_TIMER_MGMT
592 for (unsigned i
= 0; i
< MAX_TIMER_PINMAP_COUNT
; i
++) {
593 if (timerIOConfig(i
)->ioTag
== ioTag
) {
594 return timerIOConfig(i
)->dmaopt
;
601 return DMA_OPT_UNUSED
;
604 const dmaChannelSpec_t
*dmaGetChannelSpecByTimerValue(TIM_TypeDef
*tim
, uint8_t channel
, dmaoptValue_t dmaopt
)
606 if (dmaopt
< 0 || dmaopt
>= MAX_TIMER_DMA_OPTIONS
) {
610 for (unsigned i
= 0 ; i
< ARRAYLEN(dmaTimerMapping
) ; i
++) {
611 const dmaTimerMapping_t
*timerMapping
= &dmaTimerMapping
[i
];
612 #if defined(STM32H7) || defined(STM32G4)
613 if (timerMapping
->tim
== tim
&& timerMapping
->channel
== channel
) {
614 dmaChannelSpec_t
*dmaSpec
= &dmaChannelSpec
[dmaopt
];
615 dmaSetupRequest(dmaSpec
, timerMapping
->dmaRequest
);
619 if (timerMapping
->tim
== tim
&& timerMapping
->channel
== channel
&& timerMapping
->channelSpec
[dmaopt
].ref
) {
620 return &timerMapping
->channelSpec
[dmaopt
];
628 const dmaChannelSpec_t
*dmaGetChannelSpecByTimer(const timerHardware_t
*timer
)
634 dmaoptValue_t dmaopt
= dmaoptByTag(timer
->tag
);
635 return dmaGetChannelSpecByTimerValue(timer
->tim
, timer
->channel
, dmaopt
);
638 // dmaGetOptionByTimer is called by pgResetFn_timerIOConfig to find out dmaopt for pre-configured timer.
640 dmaoptValue_t
dmaGetOptionByTimer(const timerHardware_t
*timer
)
642 #if defined(STM32H7) || defined(STM32G4)
643 for (unsigned opt
= 0; opt
< ARRAYLEN(dmaChannelSpec
); opt
++) {
644 if (timer
->dmaRefConfigured
== dmaChannelSpec
[opt
].ref
) {
645 return (dmaoptValue_t
)opt
;
649 for (unsigned i
= 0 ; i
< ARRAYLEN(dmaTimerMapping
); i
++) {
650 const dmaTimerMapping_t
*timerMapping
= &dmaTimerMapping
[i
];
651 if (timerMapping
->tim
== timer
->tim
&& timerMapping
->channel
== timer
->channel
) {
652 for (unsigned j
= 0; j
< MAX_TIMER_DMA_OPTIONS
; j
++) {
653 const dmaChannelSpec_t
*dma
= &timerMapping
->channelSpec
[j
];
654 if (dma
->ref
== timer
->dmaRefConfigured
655 #if defined(STM32F4) || defined(STM32F7)
656 && dma
->channel
== timer
->dmaChannelConfigured
666 return DMA_OPT_UNUSED
;
669 #if defined(STM32H7) || defined(STM32G4)
670 // A variant of dmaGetOptionByTimer that looks for matching dmaTimUPRef
671 dmaoptValue_t
dmaGetUpOptionByTimer(const timerHardware_t
*timer
)
673 for (unsigned opt
= 0; opt
< ARRAYLEN(dmaChannelSpec
); opt
++) {
674 if (timer
->dmaTimUPRef
== dmaChannelSpec
[opt
].ref
) {
675 return (dmaoptValue_t
)opt
;
679 return DMA_OPT_UNUSED
;
683 #endif // USE_DMA_SPEC