Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / drivers / dma_reqmap.c
blob0f3da3b7e76780c0c19ab76345d57890823abaac
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 // 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[] = {
85 #ifdef USE_SPI
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),
94 #endif // USE_SPI
96 #ifdef USE_ADC
97 REQMAP(ADC, 1),
98 REQMAP(ADC, 2),
99 REQMAP(ADC, 3),
100 REQMAP(ADC, 4),
101 REQMAP(ADC, 5),
102 #endif
104 #ifdef USE_UART
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),
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
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[] = {
235 #ifdef USE_SPI
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
248 #endif // USE_SPI
250 #ifdef USE_ADC
251 REQMAP(ADC, 1),
252 REQMAP(ADC, 2),
253 #if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H725xx) || defined(STM32H730xx)
254 REQMAP(ADC, 3),
255 #endif
256 #endif
258 #ifdef USE_UART
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),
275 #endif
277 #ifdef USE_TIMER
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),
290 #endif
293 #undef REQMAP_TIMUP
294 #undef REQMAP
295 #undef REQMAP_SGL
296 #undef REQMAP_DIR
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),
331 #undef TC
332 #undef REQMAP_TIM
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] = {
337 DMA(1, 0),
338 DMA(1, 1),
339 DMA(1, 2),
340 DMA(1, 3),
341 DMA(1, 4),
342 DMA(1, 5),
343 DMA(1, 6),
344 DMA(1, 7),
345 DMA(2, 0),
346 DMA(2, 1),
347 DMA(2, 2),
348 DMA(2, 3),
349 DMA(2, 4),
350 DMA(2, 5),
351 DMA(2, 6),
352 DMA(2, 7),
355 #undef DMA
357 #elif defined(STM32F4) || defined(STM32F7)
359 #if defined(STM32F4)
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 }
363 #endif
365 static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
366 #ifdef USE_SPI
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) } },
386 #endif
387 #endif // USE_EXTENDED_SPI_DEVICE
388 #endif
389 #endif // USE_SPI
391 #ifdef USE_ADC
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) } },
395 #endif
397 #ifdef USE_SDCARD_SDIO
398 { DMA_PERIPH_SDIO, 0, { DMA(2, 3, 4), DMA(2, 6, 4) } },
399 #endif
401 #ifdef USE_UART
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) } },
414 #endif
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) } },
450 #undef TC
451 #undef DMA
453 #else // STM32F3
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] = {
458 #ifdef USE_SPI
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) } },
465 #endif
467 #ifdef USE_ADC
468 { DMA_PERIPH_ADC, ADCDEV_1, { DMA(1, 1) } },
469 #ifdef ADC24_DMA_REMAP
470 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 3) } },
471 #else
472 { DMA_PERIPH_ADC, ADCDEV_2, { DMA(2, 1) } },
473 #endif
474 { DMA_PERIPH_ADC, ADCDEV_3, { DMA(2, 5) } },
475 #ifdef ADC24_DMA_REMAP
476 { DMA_PERIPH_ADC, ADCDEV_4, { DMA(2, 4) } },
477 #else
478 { DMA_PERIPH_ADC, ADCDEV_4, { DMA(2, 2) } },
479 #endif
480 #endif
482 #ifdef USE_UART
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) } },
493 #endif
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) } },
526 #else
527 { TIM16, TC(CH1), { DMA(1, 3) } },
528 #endif
530 #ifdef REMAP_TIM17_DMA
531 { TIM17, TC(CH1), { DMA(1, 7) } },
532 #else
533 { TIM17, TC(CH1), { DMA(1, 1) } },
534 #endif
537 #undef TC
538 #undef DMA
539 #endif
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);
551 #endif
553 const dmaChannelSpec_t *dmaGetChannelSpecByPeripheral(dmaPeripheral_e device, uint8_t index, int8_t opt)
555 if (opt < 0 || opt >= MAX_PERIPHERAL_DMA_OPTIONS) {
556 return NULL;
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);
565 return dmaSpec;
567 #else
568 if (periph->device == device && periph->index == index && periph->channelSpec[opt].ref) {
569 return &periph->channelSpec[opt];
571 #endif
574 return NULL;
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;
585 #else
586 UNUSED(ioTag);
587 #endif
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) {
595 return NULL;
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);
604 return dmaSpec;
606 #else
607 if (timerMapping->tim == tim && timerMapping->channel == channel && timerMapping->channelSpec[dmaopt].ref) {
608 return &timerMapping->channelSpec[dmaopt];
610 #endif
613 return NULL;
616 const dmaChannelSpec_t *dmaGetChannelSpecByTimer(const timerHardware_t *timer)
618 if (!timer) {
619 return NULL;
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;
636 #else
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
645 #endif
647 return j;
652 #endif
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;
669 #endif
671 #endif // USE_DMA_SPEC