Fix UARTS and LPUART
[betaflight.git] / src / main / drivers / dma_reqmap.c
blob1d79ffcb8b4a8738d2aeb31b6654b24226b5f318
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
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[] = {
83 #ifdef USE_SPI
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),
92 #endif // USE_SPI
94 #ifdef USE_ADC
95 REQMAP(ADC, 1),
96 REQMAP(ADC, 2),
97 REQMAP(ADC, 3),
98 REQMAP(ADC, 4),
99 REQMAP(ADC, 5),
100 #endif
102 #ifdef USE_UART
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),
113 #ifdef USE_LPUART1
114 { DMA_PERIPH_UART_TX, LPUARTDEV_1, DMA_REQUEST_LPUART1_TX },
115 { DMA_PERIPH_UART_RX, LPUARTDEV_1, DMA_REQUEST_LPUART1_RX },
116 #endif
117 #endif
119 #ifdef USE_TIMER
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),
133 #endif
136 #undef REQMAP_TIMUP
137 #undef REQMAP
138 #undef REQMAP_SGL
139 #undef REQMAP_DIR
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
179 #undef TC
180 #undef REQMAP_TIM
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] = {
185 DMA(1, 1),
186 DMA(1, 2),
187 DMA(1, 3),
188 DMA(1, 4),
189 DMA(1, 5),
190 DMA(1, 6),
191 DMA(1, 7),
192 DMA(1, 8),
193 DMA(2, 1),
194 DMA(2, 2),
195 DMA(2, 3),
196 DMA(2, 4),
197 DMA(2, 5),
198 DMA(2, 6),
199 DMA(2, 7),
200 DMA(2, 8),
203 #undef DMA
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[] = {
237 #ifdef USE_SPI
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
250 #endif // USE_SPI
252 #ifdef USE_ADC
253 REQMAP(ADC, 1),
254 REQMAP(ADC, 2),
255 #if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H725xx) || defined(STM32H730xx)
256 REQMAP(ADC, 3),
257 #endif
258 #endif
260 #ifdef USE_UART
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),
282 #endif
283 #ifdef USE_LPUART1
284 { DMA_PERIPH_UART_TX, LPUARTDEV_1, BDMA_REQUEST_LPUART1_TX },
285 { DMA_PERIPH_UART_RX, LPUARTDEV_1, BDMA_REQUEST_LPUART1_RX },
286 #endif
287 #endif
289 #ifdef USE_TIMER
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),
302 #endif
305 #undef REQMAP_TIMUP
306 #undef REQMAP
307 #undef REQMAP_SGL
308 #undef REQMAP_DIR
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),
343 #undef TC
344 #undef REQMAP_TIM
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] = {
349 DMA(1, 0),
350 DMA(1, 1),
351 DMA(1, 2),
352 DMA(1, 3),
353 DMA(1, 4),
354 DMA(1, 5),
355 DMA(1, 6),
356 DMA(1, 7),
357 DMA(2, 0),
358 DMA(2, 1),
359 DMA(2, 2),
360 DMA(2, 3),
361 DMA(2, 4),
362 DMA(2, 5),
363 DMA(2, 6),
364 DMA(2, 7),
367 #undef DMA
369 #elif defined(STM32F4) || defined(STM32F7)
371 #if defined(STM32F4)
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 }
375 #endif
377 static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
378 #ifdef USE_SPI
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) } },
398 #endif
399 #endif // USE_EXTENDED_SPI_DEVICE
400 #endif
401 #endif // USE_SPI
403 #ifdef USE_ADC
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) } },
407 #endif
409 #ifdef USE_SDCARD_SDIO
410 { DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
411 #endif
413 #ifdef USE_UART
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) } },
426 #endif
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) } },
462 #undef TC
463 #undef DMA
465 #else // STM32F3
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] = {
470 #ifdef USE_SPI
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) } },
477 #endif
479 #ifdef USE_ADC
480 { DMA_PERIPH_ADC, ADCDEV_1, { DMA(1, 1) } },
481 #ifdef ADC24_DMA_REMAP
482 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 3) } },
483 #else
484 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 1) } },
485 #endif
486 { DMA_PERIPH_ADC, ADCDEV_3, { DMA(2, 5) } },
487 #ifdef ADC24_DMA_REMAP
488 { DMA_PERIPH_ADC, ADCDEV_4, { DMA(2, 4) } },
489 #else
490 { DMA_PERIPH_ADC, ADCDEV_4, { DMA(2, 2) } },
491 #endif
492 #endif
494 #ifdef USE_UART
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) } },
505 #endif
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) } },
538 #else
539 { TIM16, TC(CH1), { DMA(1, 3) } },
540 #endif
542 #ifdef REMAP_TIM17_DMA
543 { TIM17, TC(CH1), { DMA(1, 7) } },
544 #else
545 { TIM17, TC(CH1), { DMA(1, 1) } },
546 #endif
549 #undef TC
550 #undef DMA
551 #endif
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);
563 #endif
565 const dmaChannelSpec_t *dmaGetChannelSpecByPeripheral(dmaPeripheral_e device, uint8_t index, int8_t opt)
567 if (opt < 0 || opt >= MAX_PERIPHERAL_DMA_OPTIONS) {
568 return NULL;
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);
577 return dmaSpec;
579 #else
580 if (periph->device == device && periph->index == index && periph->channelSpec[opt].ref) {
581 return &periph->channelSpec[opt];
583 #endif
586 return NULL;
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;
597 #else
598 UNUSED(ioTag);
599 #endif
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) {
607 return NULL;
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);
616 return dmaSpec;
618 #else
619 if (timerMapping->tim == tim && timerMapping->channel == channel && timerMapping->channelSpec[dmaopt].ref) {
620 return &timerMapping->channelSpec[dmaopt];
622 #endif
625 return NULL;
628 const dmaChannelSpec_t *dmaGetChannelSpecByTimer(const timerHardware_t *timer)
630 if (!timer) {
631 return NULL;
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;
648 #else
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
657 #endif
659 return j;
664 #endif
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;
681 #endif
683 #endif // USE_DMA_SPEC