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, 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 // Resolve our preference for MOSI/MISO rather than TX/RX
75 #define DMA_REQUEST_SPI1_MOSI DMA_REQUEST_SPI1_TX
76 #define DMA_REQUEST_SPI1_MISO DMA_REQUEST_SPI1_RX
77 #define DMA_REQUEST_SPI2_MOSI DMA_REQUEST_SPI2_TX
78 #define DMA_REQUEST_SPI2_MISO DMA_REQUEST_SPI2_RX
79 #define DMA_REQUEST_SPI3_MOSI DMA_REQUEST_SPI3_TX
80 #define DMA_REQUEST_SPI3_MISO DMA_REQUEST_SPI3_RX
81 #define DMA_REQUEST_SPI4_MOSI DMA_REQUEST_SPI4_TX
82 #define DMA_REQUEST_SPI4_MISO DMA_REQUEST_SPI4_RX
84 static const dmaPeripheralMapping_t dmaPeripheralMapping
[] = {
86 REQMAP_DIR(SPI
, 1, MOSI
),
87 REQMAP_DIR(SPI
, 1, MISO
),
88 REQMAP_DIR(SPI
, 2, MOSI
),
89 REQMAP_DIR(SPI
, 2, MISO
),
90 REQMAP_DIR(SPI
, 3, MOSI
),
91 REQMAP_DIR(SPI
, 3, MISO
),
92 REQMAP_DIR(SPI
, 4, MOSI
),
93 REQMAP_DIR(SPI
, 4, MISO
),
105 REQMAP_DIR(UART
, 1, TX
),
106 REQMAP_DIR(UART
, 1, RX
),
107 REQMAP_DIR(UART
, 2, TX
),
108 REQMAP_DIR(UART
, 2, RX
),
109 REQMAP_DIR(UART
, 3, TX
),
110 REQMAP_DIR(UART
, 3, RX
),
111 REQMAP_DIR(UART
, 4, TX
),
112 REQMAP_DIR(UART
, 4, RX
),
113 REQMAP_DIR(UART
, 5, TX
),
114 REQMAP_DIR(UART
, 5, RX
),
115 REQMAP_DIR(UART
, 9, TX
),
116 REQMAP_DIR(UART
, 9, 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
222 // Resolve our preference for MOSI/MISO rather than TX/RX
223 #define DMA_REQUEST_SPI1_MOSI DMA_REQUEST_SPI1_TX
224 #define DMA_REQUEST_SPI1_MISO DMA_REQUEST_SPI1_RX
225 #define DMA_REQUEST_SPI2_MOSI DMA_REQUEST_SPI2_TX
226 #define DMA_REQUEST_SPI2_MISO DMA_REQUEST_SPI2_RX
227 #define DMA_REQUEST_SPI3_MOSI DMA_REQUEST_SPI3_TX
228 #define DMA_REQUEST_SPI3_MISO DMA_REQUEST_SPI3_RX
229 #define DMA_REQUEST_SPI4_MOSI DMA_REQUEST_SPI4_TX
230 #define DMA_REQUEST_SPI4_MISO DMA_REQUEST_SPI4_RX
231 #define DMA_REQUEST_SPI5_MOSI DMA_REQUEST_SPI5_TX
232 #define DMA_REQUEST_SPI5_MISO DMA_REQUEST_SPI5_RX
234 static const dmaPeripheralMapping_t dmaPeripheralMapping
[] = {
236 REQMAP_DIR(SPI
, 1, MOSI
),
237 REQMAP_DIR(SPI
, 1, MISO
),
238 REQMAP_DIR(SPI
, 2, MOSI
),
239 REQMAP_DIR(SPI
, 2, MISO
),
240 REQMAP_DIR(SPI
, 3, MOSI
),
241 REQMAP_DIR(SPI
, 3, MISO
),
242 REQMAP_DIR(SPI
, 4, MOSI
),
243 REQMAP_DIR(SPI
, 4, MISO
),
244 REQMAP_DIR(SPI
, 5, MOSI
), // Not available in smaller packages
245 REQMAP_DIR(SPI
, 5, MISO
), // ditto
246 // REQMAP_DIR(SPI, 6, MOSI), // SPI6 is on BDMA (todo)
247 // REQMAP_DIR(SPI, 6, MOSI), // ditto
253 #if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H725xx) || defined(STM32H730xx)
259 REQMAP_DIR(UART
, 1, TX
),
260 REQMAP_DIR(UART
, 1, RX
),
261 REQMAP_DIR(UART
, 2, TX
),
262 REQMAP_DIR(UART
, 2, RX
),
263 REQMAP_DIR(UART
, 3, TX
),
264 REQMAP_DIR(UART
, 3, RX
),
265 REQMAP_DIR(UART
, 4, TX
),
266 REQMAP_DIR(UART
, 4, RX
),
267 REQMAP_DIR(UART
, 5, TX
),
268 REQMAP_DIR(UART
, 5, RX
),
269 REQMAP_DIR(UART
, 6, TX
),
270 REQMAP_DIR(UART
, 6, RX
),
271 REQMAP_DIR(UART
, 7, TX
),
272 REQMAP_DIR(UART
, 7, RX
),
273 REQMAP_DIR(UART
, 8, TX
),
274 REQMAP_DIR(UART
, 8, RX
),
278 // Pseudo peripheral for TIMx_UP channel
279 REQMAP_TIMUP(TIMUP
, 1),
280 REQMAP_TIMUP(TIMUP
, 2),
281 REQMAP_TIMUP(TIMUP
, 3),
282 REQMAP_TIMUP(TIMUP
, 4),
283 REQMAP_TIMUP(TIMUP
, 5),
284 REQMAP_TIMUP(TIMUP
, 6),
285 REQMAP_TIMUP(TIMUP
, 7),
286 REQMAP_TIMUP(TIMUP
, 8),
287 REQMAP_TIMUP(TIMUP
, 15),
288 REQMAP_TIMUP(TIMUP
, 16),
289 REQMAP_TIMUP(TIMUP
, 17),
298 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
300 #define REQMAP_TIM(tim, chan) { tim, TC(chan), DMA_REQUEST_ ## tim ## _ ## chan }
302 static const dmaTimerMapping_t dmaTimerMapping
[] = {
303 REQMAP_TIM(TIM1
, CH1
),
304 REQMAP_TIM(TIM1
, CH2
),
305 REQMAP_TIM(TIM1
, CH3
),
306 REQMAP_TIM(TIM1
, CH4
),
307 REQMAP_TIM(TIM2
, CH1
),
308 REQMAP_TIM(TIM2
, CH2
),
309 REQMAP_TIM(TIM2
, CH3
),
310 REQMAP_TIM(TIM2
, CH4
),
311 REQMAP_TIM(TIM3
, CH1
),
312 REQMAP_TIM(TIM3
, CH2
),
313 REQMAP_TIM(TIM3
, CH3
),
314 REQMAP_TIM(TIM3
, CH4
),
315 REQMAP_TIM(TIM4
, CH1
),
316 REQMAP_TIM(TIM4
, CH2
),
317 REQMAP_TIM(TIM4
, CH3
),
318 REQMAP_TIM(TIM5
, CH1
),
319 REQMAP_TIM(TIM5
, CH2
),
320 REQMAP_TIM(TIM5
, CH3
),
321 REQMAP_TIM(TIM5
, CH4
),
322 REQMAP_TIM(TIM8
, CH1
),
323 REQMAP_TIM(TIM8
, CH2
),
324 REQMAP_TIM(TIM8
, CH3
),
325 REQMAP_TIM(TIM8
, CH4
),
326 REQMAP_TIM(TIM15
, CH1
),
327 REQMAP_TIM(TIM16
, CH1
),
328 REQMAP_TIM(TIM17
, CH1
),
334 #define DMA(d, s) { DMA_CODE(d, s, 0), (dmaResource_t *)DMA ## d ## _Stream ## s, 0 }
336 static dmaChannelSpec_t dmaChannelSpec
[MAX_PERIPHERAL_DMA_OPTIONS
] = {
357 #elif defined(STM32F4) || defined(STM32F7)
360 #define DMA(d, s, c) { DMA_CODE(d, s, c), (dmaResource_t *)DMA ## d ## _Stream ## s, DMA_Channel_ ## c }
361 #elif defined(STM32F7)
362 #define DMA(d, s, c) { DMA_CODE(d, s, c), (dmaResource_t *)DMA ## d ## _Stream ## s, DMA_CHANNEL_ ## c }
365 static const dmaPeripheralMapping_t dmaPeripheralMapping
[] = {
367 // Everything including F405 and F446
368 { DMA_PERIPH_SPI_MOSI
, SPIDEV_1
, { DMA(2, 3, 3), DMA(2, 5, 3) } },
369 { DMA_PERIPH_SPI_MISO
, SPIDEV_1
, { DMA(2, 0, 3), DMA(2, 2, 3) } },
370 { DMA_PERIPH_SPI_MOSI
, SPIDEV_2
, { DMA(1, 4, 0) } },
371 { DMA_PERIPH_SPI_MISO
, SPIDEV_2
, { DMA(1, 3, 0) } },
372 { DMA_PERIPH_SPI_MOSI
, SPIDEV_3
, { DMA(1, 5, 0), DMA(1, 7, 0) } },
373 { DMA_PERIPH_SPI_MISO
, SPIDEV_3
, { DMA(1, 0, 0), DMA(1, 2, 0) } },
375 #if defined(STM32F411xE) || defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx) || defined(STM32F722xx)
376 { DMA_PERIPH_SPI_MOSI
, SPIDEV_4
, { DMA(2, 1, 4) } },
377 { DMA_PERIPH_SPI_MISO
, SPIDEV_4
, { DMA(2, 0, 4) } },
379 #ifdef USE_EXTENDED_SPI_DEVICE
380 { DMA_PERIPH_SPI_MOSI
, SPIDEV_5
, { DMA(2, 6, 7) } },
381 { DMA_PERIPH_SPI_MISO
, SPIDEV_5
, { DMA(2, 5, 7) } },
383 #if !defined(STM32F722xx)
384 { DMA_PERIPH_SPI_MOSI
, SPIDEV_6
, { DMA(2, 5, 1) } },
385 { DMA_PERIPH_SPI_MISO
, SPIDEV_6
, { DMA(2, 6, 1) } },
387 #endif // USE_EXTENDED_SPI_DEVICE
392 { DMA_PERIPH_ADC
, ADCDEV_1
, { DMA(2, 0, 0), DMA(2, 4, 0) } },
393 { DMA_PERIPH_ADC
, ADCDEV_2
, { DMA(2, 2, 1), DMA(2, 3, 1) } },
394 { DMA_PERIPH_ADC
, ADCDEV_3
, { DMA(2, 0, 2), DMA(2, 1, 2) } },
397 #ifdef USE_SDCARD_SDIO
398 { DMA_PERIPH_SDIO
, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
402 { DMA_PERIPH_UART_TX
, UARTDEV_1
, { DMA(2, 7, 4) } },
403 { DMA_PERIPH_UART_RX
, UARTDEV_1
, { DMA(2, 5, 4), DMA(2, 2, 4) } },
404 { DMA_PERIPH_UART_TX
, UARTDEV_2
, { DMA(1, 6, 4) } },
405 { DMA_PERIPH_UART_RX
, UARTDEV_2
, { DMA(1, 5, 4) } },
406 { DMA_PERIPH_UART_TX
, UARTDEV_3
, { DMA(1, 3, 4) } },
407 { DMA_PERIPH_UART_RX
, UARTDEV_3
, { DMA(1, 1, 4) } },
408 { DMA_PERIPH_UART_TX
, UARTDEV_4
, { DMA(1, 4, 4) } },
409 { DMA_PERIPH_UART_RX
, UARTDEV_4
, { DMA(1, 2, 4) } },
410 { DMA_PERIPH_UART_TX
, UARTDEV_5
, { DMA(1, 7, 4) } },
411 { DMA_PERIPH_UART_RX
, UARTDEV_5
, { DMA(1, 0, 4) } },
412 { DMA_PERIPH_UART_TX
, UARTDEV_6
, { DMA(2, 6, 5), DMA(2, 7, 5) } },
413 { DMA_PERIPH_UART_RX
, UARTDEV_6
, { DMA(2, 1, 5), DMA(2, 2, 5) } },
417 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
419 static const dmaTimerMapping_t dmaTimerMapping
[] = {
420 // Generated from 'timer_def.h'
421 { TIM1
, TC(CH1
), { DMA(2, 6, 0), DMA(2, 1, 6), DMA(2, 3, 6) } },
422 { TIM1
, TC(CH2
), { DMA(2, 6, 0), DMA(2, 2, 6) } },
423 { TIM1
, TC(CH3
), { DMA(2, 6, 0), DMA(2, 6, 6) } },
424 { TIM1
, TC(CH4
), { DMA(2, 4, 6) } },
426 { TIM2
, TC(CH1
), { DMA(1, 5, 3) } },
427 { TIM2
, TC(CH2
), { DMA(1, 6, 3) } },
428 { TIM2
, TC(CH3
), { DMA(1, 1, 3) } },
429 { TIM2
, TC(CH4
), { DMA(1, 7, 3), DMA(1, 6, 3) } },
431 { TIM3
, TC(CH1
), { DMA(1, 4, 5) } },
432 { TIM3
, TC(CH2
), { DMA(1, 5, 5) } },
433 { TIM3
, TC(CH3
), { DMA(1, 7, 5) } },
434 { TIM3
, TC(CH4
), { DMA(1, 2, 5) } },
436 { TIM4
, TC(CH1
), { DMA(1, 0, 2) } },
437 { TIM4
, TC(CH2
), { DMA(1, 3, 2) } },
438 { TIM4
, TC(CH3
), { DMA(1, 7, 2) } },
440 { TIM5
, TC(CH1
), { DMA(1, 2, 6) } },
441 { TIM5
, TC(CH2
), { DMA(1, 4, 6) } },
442 { TIM5
, TC(CH3
), { DMA(1, 0, 6) } },
443 { TIM5
, TC(CH4
), { DMA(1, 1, 6), DMA(1, 3, 6) } },
445 { TIM8
, TC(CH1
), { DMA(2, 2, 0), DMA(2, 2, 7) } },
446 { TIM8
, TC(CH2
), { DMA(2, 2, 0), DMA(2, 3, 7) } },
447 { TIM8
, TC(CH3
), { DMA(2, 2, 0), DMA(2, 4, 7) } },
448 { TIM8
, TC(CH4
), { DMA(2, 7, 7) } },
454 // The embedded ADC24_DMA_REMAP conditional should be removed
455 // when (and if) F3 is going generic.
456 #define DMA(d, c) { DMA_CODE(d, 0, c), (dmaResource_t *)DMA ## d ## _Channel ## c }
457 static const dmaPeripheralMapping_t dmaPeripheralMapping
[18] = {
459 { DMA_PERIPH_SPI_MOSI
, SPIDEV_1
, { DMA(1, 3) } },
460 { DMA_PERIPH_SPI_MISO
, SPIDEV_1
, { DMA(1, 2) } },
461 { DMA_PERIPH_SPI_MOSI
, SPIDEV_2
, { DMA(1, 5) } },
462 { DMA_PERIPH_SPI_MISO
, SPIDEV_2
, { DMA(1, 4) } },
463 { DMA_PERIPH_SPI_MOSI
, SPIDEV_3
, { DMA(2, 2) } },
464 { DMA_PERIPH_SPI_MISO
, SPIDEV_3
, { DMA(2, 1) } },
468 { DMA_PERIPH_ADC
, ADCDEV_1
, { DMA(1, 1) } },
469 #ifdef ADC24_DMA_REMAP
470 { DMA_PERIPH_ADC
, ADCDEV_2
, { DMA(2, 3) } },
472 { DMA_PERIPH_ADC
, ADCDEV_2
, { DMA(2, 1) } },
474 { DMA_PERIPH_ADC
, ADCDEV_3
, { DMA(2, 5) } },
475 #ifdef ADC24_DMA_REMAP
476 { DMA_PERIPH_ADC
, ADCDEV_4
, { DMA(2, 4) } },
478 { DMA_PERIPH_ADC
, ADCDEV_4
, { DMA(2, 2) } },
483 { DMA_PERIPH_UART_TX
, UARTDEV_1
, { DMA(1, 4) } },
484 { DMA_PERIPH_UART_RX
, UARTDEV_1
, { DMA(1, 5) } },
486 { DMA_PERIPH_UART_TX
, UARTDEV_2
, { DMA(1, 7) } },
487 { DMA_PERIPH_UART_RX
, UARTDEV_2
, { DMA(1, 6) } },
488 { DMA_PERIPH_UART_TX
, UARTDEV_3
, { DMA(1, 2) } },
489 { DMA_PERIPH_UART_RX
, UARTDEV_3
, { DMA(1, 3) } },
490 { DMA_PERIPH_UART_TX
, UARTDEV_4
, { DMA(2, 5) } },
491 { DMA_PERIPH_UART_RX
, UARTDEV_4
, { DMA(2, 3) } },
495 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
497 static const dmaTimerMapping_t dmaTimerMapping
[] = {
498 // Generated from 'timer_def.h'
499 { TIM1
, TC(CH1
), { DMA(1, 2) } },
500 { TIM1
, TC(CH2
), { DMA(1, 3) } },
501 { TIM1
, TC(CH3
), { DMA(1, 6) } },
502 { TIM1
, TC(CH4
), { DMA(1, 4) } },
504 { TIM2
, TC(CH1
), { DMA(1, 5) } },
505 { TIM2
, TC(CH2
), { DMA(1, 7) } },
506 { TIM2
, TC(CH3
), { DMA(1, 1) } },
507 { TIM2
, TC(CH4
), { DMA(1, 7) } },
509 { TIM3
, TC(CH1
), { DMA(1, 6) } },
510 { TIM3
, TC(CH3
), { DMA(1, 2) } },
511 { TIM3
, TC(CH4
), { DMA(1, 3) } },
513 { TIM4
, TC(CH1
), { DMA(1, 1) } },
514 { TIM4
, TC(CH2
), { DMA(1, 4) } },
515 { TIM4
, TC(CH3
), { DMA(1, 5) } },
517 { TIM8
, TC(CH1
), { DMA(2, 3) } },
518 { TIM8
, TC(CH2
), { DMA(2, 5) } },
519 { TIM8
, TC(CH3
), { DMA(2, 1) } },
520 { TIM8
, TC(CH4
), { DMA(2, 2) } },
522 { TIM15
, TC(CH1
), { DMA(1, 5) } },
524 #ifdef REMAP_TIM16_DMA
525 { TIM16
, TC(CH1
), { DMA(1, 6) } },
527 { TIM16
, TC(CH1
), { DMA(1, 3) } },
530 #ifdef REMAP_TIM17_DMA
531 { TIM17
, TC(CH1
), { DMA(1, 7) } },
533 { TIM17
, TC(CH1
), { DMA(1, 1) } },
541 #if defined(STM32H7) || defined(STM32G4)
542 static void dmaSetupRequest(dmaChannelSpec_t
*dmaSpec
, uint8_t request
)
544 // Setup request as channel
545 dmaSpec
->channel
= request
;
547 // Insert DMA request into code
548 dmaCode_t code
= dmaSpec
->code
;
549 dmaSpec
->code
= DMA_CODE(DMA_CODE_CONTROLLER(code
), DMA_CODE_STREAM(code
), dmaSpec
->channel
);
553 const dmaChannelSpec_t
*dmaGetChannelSpecByPeripheral(dmaPeripheral_e device
, uint8_t index
, int8_t opt
)
555 if (opt
< 0 || opt
>= MAX_PERIPHERAL_DMA_OPTIONS
) {
559 for (unsigned i
= 0 ; i
< ARRAYLEN(dmaPeripheralMapping
) ; i
++) {
560 const dmaPeripheralMapping_t
*periph
= &dmaPeripheralMapping
[i
];
561 #if defined(STM32H7) || defined(STM32G4)
562 if (periph
->device
== device
&& periph
->index
== index
) {
563 dmaChannelSpec_t
*dmaSpec
= &dmaChannelSpec
[opt
];
564 dmaSetupRequest(dmaSpec
, periph
->dmaRequest
);
568 if (periph
->device
== device
&& periph
->index
== index
&& periph
->channelSpec
[opt
].ref
) {
569 return &periph
->channelSpec
[opt
];
577 dmaoptValue_t
dmaoptByTag(ioTag_t ioTag
)
579 #ifdef USE_TIMER_MGMT
580 for (unsigned i
= 0; i
< MAX_TIMER_PINMAP_COUNT
; i
++) {
581 if (timerIOConfig(i
)->ioTag
== ioTag
) {
582 return timerIOConfig(i
)->dmaopt
;
589 return DMA_OPT_UNUSED
;
592 const dmaChannelSpec_t
*dmaGetChannelSpecByTimerValue(TIM_TypeDef
*tim
, uint8_t channel
, dmaoptValue_t dmaopt
)
594 if (dmaopt
< 0 || dmaopt
>= MAX_TIMER_DMA_OPTIONS
) {
598 for (unsigned i
= 0 ; i
< ARRAYLEN(dmaTimerMapping
) ; i
++) {
599 const dmaTimerMapping_t
*timerMapping
= &dmaTimerMapping
[i
];
600 #if defined(STM32H7) || defined(STM32G4)
601 if (timerMapping
->tim
== tim
&& timerMapping
->channel
== channel
) {
602 dmaChannelSpec_t
*dmaSpec
= &dmaChannelSpec
[dmaopt
];
603 dmaSetupRequest(dmaSpec
, timerMapping
->dmaRequest
);
607 if (timerMapping
->tim
== tim
&& timerMapping
->channel
== channel
&& timerMapping
->channelSpec
[dmaopt
].ref
) {
608 return &timerMapping
->channelSpec
[dmaopt
];
616 const dmaChannelSpec_t
*dmaGetChannelSpecByTimer(const timerHardware_t
*timer
)
622 dmaoptValue_t dmaopt
= dmaoptByTag(timer
->tag
);
623 return dmaGetChannelSpecByTimerValue(timer
->tim
, timer
->channel
, dmaopt
);
626 // dmaGetOptionByTimer is called by pgResetFn_timerIOConfig to find out dmaopt for pre-configured timer.
628 dmaoptValue_t
dmaGetOptionByTimer(const timerHardware_t
*timer
)
630 #if defined(STM32H7) || defined(STM32G4)
631 for (unsigned opt
= 0; opt
< ARRAYLEN(dmaChannelSpec
); opt
++) {
632 if (timer
->dmaRefConfigured
== dmaChannelSpec
[opt
].ref
) {
633 return (dmaoptValue_t
)opt
;
637 for (unsigned i
= 0 ; i
< ARRAYLEN(dmaTimerMapping
); i
++) {
638 const dmaTimerMapping_t
*timerMapping
= &dmaTimerMapping
[i
];
639 if (timerMapping
->tim
== timer
->tim
&& timerMapping
->channel
== timer
->channel
) {
640 for (unsigned j
= 0; j
< MAX_TIMER_DMA_OPTIONS
; j
++) {
641 const dmaChannelSpec_t
*dma
= &timerMapping
->channelSpec
[j
];
642 if (dma
->ref
== timer
->dmaRefConfigured
643 #if defined(STM32F4) || defined(STM32F7)
644 && dma
->channel
== timer
->dmaChannelConfigured
654 return DMA_OPT_UNUSED
;
657 #if defined(STM32H7) || defined(STM32G4)
658 // A variant of dmaGetOptionByTimer that looks for matching dmaTimUPRef
659 dmaoptValue_t
dmaGetUpOptionByTimer(const timerHardware_t
*timer
)
661 for (unsigned opt
= 0; opt
< ARRAYLEN(dmaChannelSpec
); opt
++) {
662 if (timer
->dmaTimUPRef
== dmaChannelSpec
[opt
].ref
) {
663 return (dmaoptValue_t
)opt
;
667 return DMA_OPT_UNUSED
;
671 #endif // USE_DMA_SPEC