Fix dma pin <io> list (#13233)
[betaflight.git] / src / main / drivers / at32 / dma_reqmap_mcu.c
blobb6323f9e1da6612c4277e9d28c8e3767e65e5249
1 /*
2 * This file is part of Betaflight.
4 * Betaflight is free software. You can redistribute this software
5 * and/or modify this software under the terms of the GNU General
6 * Public License as published by the Free Software Foundation,
7 * either version 3 of the License, or (at your option) any later
8 * version.
10 * Betaflight is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this software.
19 * If not, see <http://www.gnu.org/licenses/>.
22 #include <stdint.h>
24 #include "platform.h"
26 #ifdef USE_DMA_SPEC
28 #include "timer_def.h"
29 #include "drivers/adc.h"
30 #include "drivers/bus_spi.h"
31 #include "drivers/dma_reqmap.h"
32 #include "drivers/serial.h"
33 #include "drivers/serial_uart.h"
35 #include "pg/timerio.h"
37 typedef struct dmaPeripheralMapping_s {
38 dmaPeripheral_e device;
39 uint8_t index;
40 uint8_t dmaRequest;
41 } dmaPeripheralMapping_t;
43 typedef struct dmaTimerMapping_s {
44 TIM_TypeDef *tim;
45 uint8_t channel;
46 uint8_t dmaRequest;
47 } dmaTimerMapping_t;
49 #define REQMAP_SGL(periph) { DMA_PERIPH_ ## periph, 0, DMA_REQUEST_ ## periph }
50 #define REQMAP(periph, device) { DMA_PERIPH_ ## periph, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device }
51 #define REQMAP_DIR(periph, device, dir) { DMA_PERIPH_ ## periph ## _ ## dir, periph ## DEV_ ## device, DMA_REQUEST_ ## periph ## device ## _ ## dir }
52 #define REQMAP_TIMUP(periph, timno) { DMA_PERIPH_TIMUP, timno - 1, DMAMUX_DMAREQ_ID_ ## TMR ## timno ## _OVERFLOW }
54 #define DMA_REQUEST_UART1_RX DMAMUX_DMAREQ_ID_USART1_RX
55 #define DMA_REQUEST_UART1_TX DMAMUX_DMAREQ_ID_USART1_TX
56 #define DMA_REQUEST_UART2_RX DMAMUX_DMAREQ_ID_USART2_RX
57 #define DMA_REQUEST_UART2_TX DMAMUX_DMAREQ_ID_USART2_TX
58 #define DMA_REQUEST_UART3_RX DMAMUX_DMAREQ_ID_USART3_RX
59 #define DMA_REQUEST_UART3_TX DMAMUX_DMAREQ_ID_USART3_TX
60 #define DMA_REQUEST_UART4_RX DMAMUX_DMAREQ_ID_UART4_RX
61 #define DMA_REQUEST_UART4_TX DMAMUX_DMAREQ_ID_UART4_TX
62 #define DMA_REQUEST_UART5_RX DMAMUX_DMAREQ_ID_UART5_RX
63 #define DMA_REQUEST_UART5_TX DMAMUX_DMAREQ_ID_UART5_TX
65 #define DMA_REQUEST_UART6_RX DMAMUX_DMAREQ_ID_USART6_RX
66 #define DMA_REQUEST_UART6_TX DMAMUX_DMAREQ_ID_USART6_TX
68 // Resolve our preference for SDO/SDI rather than TX/RX
69 #define DMA_REQUEST_SPI1_SDO DMAMUX_DMAREQ_ID_SPI1_TX
70 #define DMA_REQUEST_SPI1_SDI DMAMUX_DMAREQ_ID_SPI1_RX
71 #define DMA_REQUEST_SPI2_SDO DMAMUX_DMAREQ_ID_SPI2_TX
72 #define DMA_REQUEST_SPI2_SDI DMAMUX_DMAREQ_ID_SPI2_RX
73 #define DMA_REQUEST_SPI3_SDO DMAMUX_DMAREQ_ID_SPI3_TX
74 #define DMA_REQUEST_SPI3_SDI DMAMUX_DMAREQ_ID_SPI3_RX
75 #define DMA_REQUEST_SPI4_SDO DMAMUX_DMAREQ_ID_SPI4_TX
76 #define DMA_REQUEST_SPI4_SDI DMAMUX_DMAREQ_ID_SPI4_RX
78 #define DMA_REQUEST_ADC1 DMAMUX_DMAREQ_ID_ADC1
79 #define DMA_REQUEST_ADC2 DMAMUX_DMAREQ_ID_ADC2
80 #define DMA_REQUEST_ADC3 DMAMUX_DMAREQ_ID_ADC3
82 static const dmaPeripheralMapping_t dmaPeripheralMapping[] = {
83 #ifdef USE_SPI
84 REQMAP_DIR(SPI, 1, SDO),
85 REQMAP_DIR(SPI, 1, SDI),
86 REQMAP_DIR(SPI, 2, SDO),
87 REQMAP_DIR(SPI, 2, SDI),
88 REQMAP_DIR(SPI, 3, SDO),
89 REQMAP_DIR(SPI, 3, SDI),
90 REQMAP_DIR(SPI, 4, SDO),
91 REQMAP_DIR(SPI, 4, SDI),
92 #endif // USE_SPI
94 #ifdef USE_ADC
95 REQMAP(ADC, 1),
96 REQMAP(ADC, 2),
97 REQMAP(ADC, 3),
98 #endif
100 #ifdef USE_UART
101 REQMAP_DIR(UART, 1, TX),
102 REQMAP_DIR(UART, 1, RX),
103 REQMAP_DIR(UART, 2, TX),
104 REQMAP_DIR(UART, 2, RX),
105 REQMAP_DIR(UART, 3, TX),
106 REQMAP_DIR(UART, 3, RX),
107 REQMAP_DIR(UART, 4, TX),
108 REQMAP_DIR(UART, 4, RX),
109 REQMAP_DIR(UART, 5, TX),
110 REQMAP_DIR(UART, 5, RX),
111 REQMAP_DIR(UART, 6, TX),
112 REQMAP_DIR(UART, 6, RX),
113 #endif
115 #ifdef USE_TIMER
116 REQMAP_TIMUP(TIMUP, 1),
117 REQMAP_TIMUP(TIMUP, 2),
118 REQMAP_TIMUP(TIMUP, 3),
119 REQMAP_TIMUP(TIMUP, 4),
120 REQMAP_TIMUP(TIMUP, 5),
121 REQMAP_TIMUP(TIMUP, 6),
122 REQMAP_TIMUP(TIMUP, 7),
123 REQMAP_TIMUP(TIMUP, 8),
124 REQMAP_TIMUP(TIMUP, 20),
125 #endif
128 #undef REQMAP_TIMUP
129 #undef REQMAP
130 #undef REQMAP_SGL
131 #undef REQMAP_DIR
133 #define TC(chan) DEF_TIM_CHANNEL(CH_ ## chan)
135 #define REQMAP_TIM(tim, chan) { tim, TC(chan), DMAMUX_DMAREQ_ID_ ## tim ## _ ## chan }
137 static const dmaTimerMapping_t dmaTimerMapping[] = {
138 REQMAP_TIM(TMR1, CH1),
139 REQMAP_TIM(TMR1, CH2),
140 REQMAP_TIM(TMR1, CH3),
141 REQMAP_TIM(TMR1, CH4),
142 REQMAP_TIM(TMR2, CH1),
143 REQMAP_TIM(TMR2, CH2),
144 REQMAP_TIM(TMR2, CH3),
145 REQMAP_TIM(TMR2, CH4),
146 REQMAP_TIM(TMR3, CH1),
147 REQMAP_TIM(TMR3, CH2),
148 REQMAP_TIM(TMR3, CH3),
149 REQMAP_TIM(TMR3, CH4),
150 REQMAP_TIM(TMR4, CH1),
151 REQMAP_TIM(TMR4, CH2),
152 REQMAP_TIM(TMR4, CH3),
153 REQMAP_TIM(TMR4, CH4),
154 REQMAP_TIM(TMR5, CH1),
155 REQMAP_TIM(TMR5, CH2),
156 REQMAP_TIM(TMR5, CH3),
157 REQMAP_TIM(TMR5, CH4),
158 REQMAP_TIM(TMR8, CH1),
159 REQMAP_TIM(TMR8, CH2),
160 REQMAP_TIM(TMR8, CH3),
161 REQMAP_TIM(TMR8, CH4),
162 REQMAP_TIM(TMR20, CH1),
163 REQMAP_TIM(TMR20, CH2),
164 REQMAP_TIM(TMR20, CH3),
165 REQMAP_TIM(TMR20, 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(2, 1),
183 DMA(2, 2),
184 DMA(2, 3),
185 DMA(2, 4),
186 DMA(2, 5),
187 DMA(2, 6),
188 DMA(2, 7),
191 #undef DMA
193 static void dmaSetupRequest(dmaChannelSpec_t *dmaSpec, uint8_t request)
195 dmaSpec->dmaMuxId = request;
196 dmaCode_t code = dmaSpec->code;
197 dmaSpec->code = DMA_CODE(DMA_CODE_CONTROLLER(code), DMA_CODE_STREAM(code), dmaSpec->dmaMuxId);
200 const dmaChannelSpec_t *dmaGetChannelSpecByPeripheral(dmaPeripheral_e device, uint8_t index, int8_t opt)
202 if (opt < 0 || opt >= MAX_PERIPHERAL_DMA_OPTIONS) {
203 return NULL;
206 for (unsigned i = 0 ; i < ARRAYLEN(dmaPeripheralMapping) ; i++) {
207 const dmaPeripheralMapping_t *periph = &dmaPeripheralMapping[i];
208 if (periph->device == device && periph->index == index) {
209 dmaChannelSpec_t *dmaSpec = &dmaChannelSpec[opt];
210 dmaSetupRequest(dmaSpec, periph->dmaRequest);
211 return dmaSpec;
215 return NULL;
218 dmaoptValue_t dmaoptByTag(ioTag_t ioTag)
220 #ifdef USE_TIMER_MGMT
221 for (unsigned i = 0; i < MAX_TIMER_PINMAP_COUNT; i++) {
222 if (timerIOConfig(i)->ioTag == ioTag) {
223 return timerIOConfig(i)->dmaopt;
226 #else
227 UNUSED(ioTag);
228 #endif
230 return DMA_OPT_UNUSED;
233 const dmaChannelSpec_t *dmaGetChannelSpecByTimerValue(TIM_TypeDef *tim, uint8_t channel, dmaoptValue_t dmaopt)
235 if (dmaopt < 0 || dmaopt >= MAX_PERIPHERAL_DMA_OPTIONS) {
236 return NULL;
239 for (unsigned i = 0 ; i < ARRAYLEN(dmaTimerMapping) ; i++) {
240 const dmaTimerMapping_t *timerMapping = &dmaTimerMapping[i];
241 if (timerMapping->tim == tim && timerMapping->channel == channel) {
242 dmaChannelSpec_t *dmaSpec = &dmaChannelSpec[dmaopt];
243 dmaSetupRequest(dmaSpec, timerMapping->dmaRequest);
244 return dmaSpec;
248 return NULL;
251 const dmaChannelSpec_t *dmaGetChannelSpecByTimer(const timerHardware_t *timer)
253 if (!timer) {
254 return NULL;
257 dmaoptValue_t dmaopt = dmaoptByTag(timer->tag);
258 return dmaGetChannelSpecByTimerValue(timer->tim, timer->channel, dmaopt);
261 // dmaGetOptionByTimer is called by pgResetFn_timerIOConfig to find out dmaopt for pre-configured timer.
263 dmaoptValue_t dmaGetOptionByTimer(const timerHardware_t *timer)
265 for (unsigned opt = 0; opt < ARRAYLEN(dmaChannelSpec); opt++) {
266 if (timer->dmaRefConfigured == dmaChannelSpec[opt].ref) {
267 return (dmaoptValue_t)opt;
271 return DMA_OPT_UNUSED;
274 // A variant of dmaGetOptionByTimer that looks for matching dmaTimUPRef
275 dmaoptValue_t dmaGetUpOptionByTimer(const timerHardware_t *timer)
277 for (unsigned opt = 0; opt < ARRAYLEN(dmaChannelSpec); opt++) {
278 if (timer->dmaTimUPRef == dmaChannelSpec[opt].ref) {
279 return (dmaoptValue_t)opt;
283 return DMA_OPT_UNUSED;
286 #endif // USE_DMA_SPEC