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/>.
22 * jflyper - Refactoring, cleanup and made pin-configurable
32 #include "drivers/system.h"
33 #include "drivers/dma.h"
34 #include "drivers/io.h"
35 #include "drivers/nvic.h"
36 #include "drivers/rcc.h"
38 #include "drivers/serial.h"
39 #include "drivers/serial_uart.h"
40 #include "drivers/serial_uart_impl.h"
42 #include "stm32f7xx_ll_usart.h"
44 const uartHardware_t uartHardware
[UARTDEV_COUNT
] = {
49 .rxDMAChannel
= DMA_CHANNEL_4
,
50 .txDMAChannel
= DMA_CHANNEL_4
,
51 #ifdef USE_UART1_RX_DMA
52 .rxDMAResource
= (dmaResource_t
*)DMA2_Stream5
,
54 #ifdef USE_UART1_TX_DMA
55 .txDMAResource
= (dmaResource_t
*)DMA2_Stream7
,
58 { DEFIO_TAG_E(PA10
), GPIO_AF7_USART1
},
59 { DEFIO_TAG_E(PB7
), GPIO_AF7_USART1
},
61 { DEFIO_TAG_E(PB15
), GPIO_AF4_USART1
}
65 { DEFIO_TAG_E(PA9
), GPIO_AF7_USART1
},
66 { DEFIO_TAG_E(PB6
), GPIO_AF7_USART1
},
68 { DEFIO_TAG_E(PB14
), GPIO_AF4_USART1
}
71 .rcc
= RCC_APB2(USART1
),
73 .txPriority
= NVIC_PRIO_SERIALUART1_TXDMA
,
74 .rxPriority
= NVIC_PRIO_SERIALUART1
,
75 .txBuffer
= uart1TxBuffer
,
76 .rxBuffer
= uart1RxBuffer
,
77 .txBufferSize
= sizeof(uart1TxBuffer
),
78 .rxBufferSize
= sizeof(uart1RxBuffer
),
86 .rxDMAChannel
= DMA_CHANNEL_4
,
87 .txDMAChannel
= DMA_CHANNEL_4
,
88 #ifdef USE_UART2_RX_DMA
89 .rxDMAResource
= (dmaResource_t
*)DMA1_Stream5
,
91 #ifdef USE_UART2_TX_DMA
92 .txDMAResource
= (dmaResource_t
*)DMA1_Stream6
,
95 { DEFIO_TAG_E(PA3
), GPIO_AF7_USART2
},
96 { DEFIO_TAG_E(PD6
), GPIO_AF7_USART2
}
99 { DEFIO_TAG_E(PA2
), GPIO_AF7_USART2
},
100 { DEFIO_TAG_E(PD5
), GPIO_AF7_USART2
}
102 .rcc
= RCC_APB1(USART2
),
103 .rxIrq
= USART2_IRQn
,
104 .txPriority
= NVIC_PRIO_SERIALUART2_TXDMA
,
105 .rxPriority
= NVIC_PRIO_SERIALUART2
,
106 .txBuffer
= uart2TxBuffer
,
107 .rxBuffer
= uart2RxBuffer
,
108 .txBufferSize
= sizeof(uart2TxBuffer
),
109 .rxBufferSize
= sizeof(uart2RxBuffer
),
117 .rxDMAChannel
= DMA_CHANNEL_4
,
118 .txDMAChannel
= DMA_CHANNEL_4
,
119 #ifdef USE_UART3_RX_DMA
120 .rxDMAResource
= (dmaResource_t
*)DMA1_Stream1
,
122 #ifdef USE_UART3_TX_DMA
123 .txDMAResource
= (dmaResource_t
*)DMA1_Stream3
,
126 { DEFIO_TAG_E(PB11
), GPIO_AF7_USART3
},
127 { DEFIO_TAG_E(PC11
), GPIO_AF7_USART3
},
128 { DEFIO_TAG_E(PD9
), GPIO_AF7_USART3
}
131 { DEFIO_TAG_E(PB10
), GPIO_AF7_USART3
},
132 { DEFIO_TAG_E(PC10
), GPIO_AF7_USART3
},
133 { DEFIO_TAG_E(PD8
), GPIO_AF7_USART3
}
135 .rcc
= RCC_APB1(USART3
),
136 .rxIrq
= USART3_IRQn
,
137 .txPriority
= NVIC_PRIO_SERIALUART3_TXDMA
,
138 .rxPriority
= NVIC_PRIO_SERIALUART3
,
139 .txBuffer
= uart3TxBuffer
,
140 .rxBuffer
= uart3RxBuffer
,
141 .txBufferSize
= sizeof(uart3TxBuffer
),
142 .rxBufferSize
= sizeof(uart3RxBuffer
),
150 .rxDMAChannel
= DMA_CHANNEL_4
,
151 .txDMAChannel
= DMA_CHANNEL_4
,
152 #ifdef USE_UART4_RX_DMA
153 .rxDMAResource
= (dmaResource_t
*)DMA1_Stream2
,
155 #ifdef USE_UART4_TX_DMA
156 .txDMAResource
= (dmaResource_t
*)DMA1_Stream4
,
159 { DEFIO_TAG_E(PA1
), GPIO_AF8_UART4
},
160 { DEFIO_TAG_E(PC11
), GPIO_AF8_UART4
},
162 { DEFIO_TAG_E(PA11
), GPIO_AF6_UART4
},
163 { DEFIO_TAG_E(PD0
), GPIO_AF8_UART4
}
167 { DEFIO_TAG_E(PA0
), GPIO_AF8_UART4
},
168 { DEFIO_TAG_E(PC10
), GPIO_AF8_UART4
},
170 { DEFIO_TAG_E(PA12
), GPIO_AF6_UART4
},
171 { DEFIO_TAG_E(PD1
), GPIO_AF8_UART4
}
174 .rcc
= RCC_APB1(UART4
),
176 .txPriority
= NVIC_PRIO_SERIALUART4_TXDMA
,
177 .rxPriority
= NVIC_PRIO_SERIALUART4
,
178 .txBuffer
= uart4TxBuffer
,
179 .rxBuffer
= uart4RxBuffer
,
180 .txBufferSize
= sizeof(uart4TxBuffer
),
181 .rxBufferSize
= sizeof(uart4RxBuffer
),
189 .rxDMAChannel
= DMA_CHANNEL_4
,
190 .txDMAChannel
= DMA_CHANNEL_4
,
191 #ifdef USE_UART5_RX_DMA
192 .rxDMAResource
= (dmaResource_t
*)DMA1_Stream0
,
194 #ifdef USE_UART5_TX_DMA
195 .txDMAResource
= (dmaResource_t
*)DMA1_Stream7
,
198 { DEFIO_TAG_E(PD2
), GPIO_AF8_UART5
},
200 { DEFIO_TAG_E(PB5
), GPIO_AF1_UART5
},
201 { DEFIO_TAG_E(PB8
), GPIO_AF7_UART5
},
202 { DEFIO_TAG_E(PB12
), GPIO_AF8_UART5
}
206 { DEFIO_TAG_E(PC12
), GPIO_AF8_UART5
},
208 { DEFIO_TAG_E(PB6
), GPIO_AF1_UART5
},
209 { DEFIO_TAG_E(PB9
), GPIO_AF7_UART5
},
210 { DEFIO_TAG_E(PB13
), GPIO_AF8_UART5
}
213 .rcc
= RCC_APB1(UART5
),
215 .txPriority
= NVIC_PRIO_SERIALUART5_TXDMA
,
216 .rxPriority
= NVIC_PRIO_SERIALUART5
,
217 .txBuffer
= uart5TxBuffer
,
218 .rxBuffer
= uart5RxBuffer
,
219 .txBufferSize
= sizeof(uart5TxBuffer
),
220 .rxBufferSize
= sizeof(uart5RxBuffer
),
228 .rxDMAChannel
= DMA_CHANNEL_5
,
229 .txDMAChannel
= DMA_CHANNEL_5
,
230 #ifdef USE_UART6_RX_DMA
231 .rxDMAResource
= (dmaResource_t
*)DMA2_Stream1
,
233 #ifdef USE_UART6_TX_DMA
234 .txDMAResource
= (dmaResource_t
*)DMA2_Stream6
,
237 { DEFIO_TAG_E(PC7
), GPIO_AF8_USART6
},
238 { DEFIO_TAG_E(PG9
), GPIO_AF8_USART6
}
241 { DEFIO_TAG_E(PC6
), GPIO_AF8_USART6
},
242 { DEFIO_TAG_E(PG14
), GPIO_AF8_USART6
}
244 .rcc
= RCC_APB2(USART6
),
245 .rxIrq
= USART6_IRQn
,
246 .txPriority
= NVIC_PRIO_SERIALUART6_TXDMA
,
247 .rxPriority
= NVIC_PRIO_SERIALUART6
,
248 .txBuffer
= uart6TxBuffer
,
249 .rxBuffer
= uart6RxBuffer
,
250 .txBufferSize
= sizeof(uart6TxBuffer
),
251 .rxBufferSize
= sizeof(uart6RxBuffer
),
259 .rxDMAChannel
= DMA_CHANNEL_5
,
260 .txDMAChannel
= DMA_CHANNEL_5
,
261 #ifdef USE_UART7_RX_DMA
262 .rxDMAResource
= (dmaResource_t
*)DMA1_Stream3
,
264 #ifdef USE_UART7_TX_DMA
265 .txDMAResource
= (dmaResource_t
*)DMA1_Stream1
,
268 { DEFIO_TAG_E(PE7
), GPIO_AF8_UART7
},
269 { DEFIO_TAG_E(PF6
), GPIO_AF8_UART7
},
271 { DEFIO_TAG_E(PA8
), GPIO_AF12_UART7
},
272 { DEFIO_TAG_E(PB3
), GPIO_AF12_UART7
}
276 { DEFIO_TAG_E(PE8
), GPIO_AF8_UART7
},
277 { DEFIO_TAG_E(PF7
), GPIO_AF8_UART7
},
279 { DEFIO_TAG_E(PA15
), GPIO_AF12_UART7
},
280 { DEFIO_TAG_E(PB4
), GPIO_AF12_UART7
}
283 .rcc
= RCC_APB1(UART7
),
285 .txPriority
= NVIC_PRIO_SERIALUART7_TXDMA
,
286 .rxPriority
= NVIC_PRIO_SERIALUART7
,
287 .txBuffer
= uart7TxBuffer
,
288 .rxBuffer
= uart7RxBuffer
,
289 .txBufferSize
= sizeof(uart7TxBuffer
),
290 .rxBufferSize
= sizeof(uart7RxBuffer
),
298 .rxDMAChannel
= DMA_CHANNEL_5
,
299 .txDMAChannel
= DMA_CHANNEL_5
,
300 #ifdef USE_UART8_RX_DMA
301 .rxDMAResource
= (dmaResource_t
*)DMA1_Stream6
,
303 #ifdef USE_UART8_TX_DMA
304 .txDMAResource
= (dmaResource_t
*)DMA1_Stream0
,
307 { DEFIO_TAG_E(PE0
), GPIO_AF8_UART8
}
310 { DEFIO_TAG_E(PE1
), GPIO_AF8_UART8
}
312 .rcc
= RCC_APB1(UART8
),
314 .txPriority
= NVIC_PRIO_SERIALUART8_TXDMA
,
315 .rxPriority
= NVIC_PRIO_SERIALUART8
,
316 .txBuffer
= uart8TxBuffer
,
317 .rxBuffer
= uart8RxBuffer
,
318 .txBufferSize
= sizeof(uart8TxBuffer
),
319 .rxBufferSize
= sizeof(uart8RxBuffer
),
324 // XXX Should serialUART be consolidated?
326 uartPort_t
*serialUART(UARTDevice_e device
, uint32_t baudRate
, portMode_e mode
, portOptions_e options
)
328 uartDevice_t
*uartdev
= uartDevmap
[device
];
333 uartPort_t
*s
= &(uartdev
->port
);
335 s
->port
.vTable
= uartVTable
;
337 s
->port
.baudRate
= baudRate
;
339 const uartHardware_t
*hardware
= uartdev
->hardware
;
341 s
->USARTx
= hardware
->reg
;
343 s
->port
.rxBuffer
= hardware
->rxBuffer
;
344 s
->port
.txBuffer
= hardware
->txBuffer
;
345 s
->port
.rxBufferSize
= hardware
->rxBufferSize
;
346 s
->port
.txBufferSize
= hardware
->txBufferSize
;
348 s
->checkUsartTxOutput
= checkUsartTxOutput
;
351 uartConfigureDma(uartdev
);
354 s
->Handle
.Instance
= hardware
->reg
;
357 RCC_ClockCmd(hardware
->rcc
, ENABLE
);
360 IO_t txIO
= IOGetByTag(uartdev
->tx
.pin
);
361 IO_t rxIO
= IOGetByTag(uartdev
->rx
.pin
);
363 uartdev
->txPinState
= TX_PIN_IGNORE
;
365 if ((options
& SERIAL_BIDIR
) && txIO
) {
366 ioConfig_t ioCfg
= IO_CONFIG(
367 ((options
& SERIAL_INVERTED
) || (options
& SERIAL_BIDIR_PP
) || (options
& SERIAL_BIDIR_PP_PD
)) ? GPIO_MODE_AF_PP
: GPIO_MODE_AF_OD
,
368 GPIO_SPEED_FREQ_HIGH
,
369 ((options
& SERIAL_INVERTED
) || (options
& SERIAL_BIDIR_PP_PD
)) ? GPIO_PULLDOWN
: GPIO_PULLUP
372 IOInit(txIO
, OWNER_SERIAL_TX
, RESOURCE_INDEX(device
));
373 IOConfigGPIOAF(txIO
, ioCfg
, uartdev
->tx
.af
);
376 if ((mode
& MODE_TX
) && txIO
) {
377 IOInit(txIO
, OWNER_SERIAL_TX
, RESOURCE_INDEX(device
));
379 if ((options
& SERIAL_INVERTED
) == SERIAL_NOT_INVERTED
) {
380 uartdev
->txPinState
= TX_PIN_ACTIVE
;
381 // Switch TX to an input with pullup so it's state can be monitored
384 IOConfigGPIOAF(txIO
, IOCFG_AF_PP
, uartdev
->tx
.af
);
388 if ((mode
& MODE_RX
) && rxIO
) {
389 IOInit(rxIO
, OWNER_SERIAL_RX
, RESOURCE_INDEX(device
));
390 IOConfigGPIOAF(rxIO
, IOCFG_AF_PP
, uartdev
->rx
.af
);
395 if (!s
->rxDMAResource
) {
396 HAL_NVIC_SetPriority(hardware
->rxIrq
, NVIC_PRIORITY_BASE(hardware
->rxPriority
), NVIC_PRIORITY_SUB(hardware
->rxPriority
));
397 HAL_NVIC_EnableIRQ(hardware
->rxIrq
);