Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / drivers / serial_uart_stm32f7xx.c
blobef3c81daad58f1e5c648f2f1a134440dadbc0c7c
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/>.
22 * jflyper - Refactoring, cleanup and made pin-configurable
25 #include <stdbool.h>
26 #include <stdint.h>
28 #include "platform.h"
30 #ifdef USE_UART
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] = {
45 #ifdef USE_UART1
47 .device = UARTDEV_1,
48 .reg = USART1,
49 .rxDMAChannel = DMA_CHANNEL_4,
50 .txDMAChannel = DMA_CHANNEL_4,
51 #ifdef USE_UART1_RX_DMA
52 .rxDMAResource = (dmaResource_t *)DMA2_Stream5,
53 #endif
54 #ifdef USE_UART1_TX_DMA
55 .txDMAResource = (dmaResource_t *)DMA2_Stream7,
56 #endif
57 .rxPins = {
58 { DEFIO_TAG_E(PA10), GPIO_AF7_USART1 },
59 { DEFIO_TAG_E(PB7), GPIO_AF7_USART1 },
60 #ifdef STM32F765xx
61 { DEFIO_TAG_E(PB15), GPIO_AF4_USART1 }
62 #endif
64 .txPins = {
65 { DEFIO_TAG_E(PA9), GPIO_AF7_USART1 },
66 { DEFIO_TAG_E(PB6), GPIO_AF7_USART1 },
67 #ifdef STM32F765xx
68 { DEFIO_TAG_E(PB14), GPIO_AF4_USART1 }
69 #endif
71 .rcc = RCC_APB2(USART1),
72 .rxIrq = USART1_IRQn,
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),
80 #endif
82 #ifdef USE_UART2
84 .device = UARTDEV_2,
85 .reg = USART2,
86 .rxDMAChannel = DMA_CHANNEL_4,
87 .txDMAChannel = DMA_CHANNEL_4,
88 #ifdef USE_UART2_RX_DMA
89 .rxDMAResource = (dmaResource_t *)DMA1_Stream5,
90 #endif
91 #ifdef USE_UART2_TX_DMA
92 .txDMAResource = (dmaResource_t *)DMA1_Stream6,
93 #endif
94 .rxPins = {
95 { DEFIO_TAG_E(PA3), GPIO_AF7_USART2 },
96 { DEFIO_TAG_E(PD6), GPIO_AF7_USART2 }
98 .txPins = {
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),
111 #endif
113 #ifdef USE_UART3
115 .device = UARTDEV_3,
116 .reg = USART3,
117 .rxDMAChannel = DMA_CHANNEL_4,
118 .txDMAChannel = DMA_CHANNEL_4,
119 #ifdef USE_UART3_RX_DMA
120 .rxDMAResource = (dmaResource_t *)DMA1_Stream1,
121 #endif
122 #ifdef USE_UART3_TX_DMA
123 .txDMAResource = (dmaResource_t *)DMA1_Stream3,
124 #endif
125 .rxPins = {
126 { DEFIO_TAG_E(PB11), GPIO_AF7_USART3 },
127 { DEFIO_TAG_E(PC11), GPIO_AF7_USART3 },
128 { DEFIO_TAG_E(PD9), GPIO_AF7_USART3 }
130 .txPins = {
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),
144 #endif
146 #ifdef USE_UART4
148 .device = UARTDEV_4,
149 .reg = UART4,
150 .rxDMAChannel = DMA_CHANNEL_4,
151 .txDMAChannel = DMA_CHANNEL_4,
152 #ifdef USE_UART4_RX_DMA
153 .rxDMAResource = (dmaResource_t *)DMA1_Stream2,
154 #endif
155 #ifdef USE_UART4_TX_DMA
156 .txDMAResource = (dmaResource_t *)DMA1_Stream4,
157 #endif
158 .rxPins = {
159 { DEFIO_TAG_E(PA1), GPIO_AF8_UART4 },
160 { DEFIO_TAG_E(PC11), GPIO_AF8_UART4 },
161 #ifdef STM32F765xx
162 { DEFIO_TAG_E(PA11), GPIO_AF6_UART4 },
163 { DEFIO_TAG_E(PD0), GPIO_AF8_UART4 }
164 #endif
166 .txPins = {
167 { DEFIO_TAG_E(PA0), GPIO_AF8_UART4 },
168 { DEFIO_TAG_E(PC10), GPIO_AF8_UART4 },
169 #ifdef STM32F765xx
170 { DEFIO_TAG_E(PA12), GPIO_AF6_UART4 },
171 { DEFIO_TAG_E(PD1), GPIO_AF8_UART4 }
172 #endif
174 .rcc = RCC_APB1(UART4),
175 .rxIrq = UART4_IRQn,
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),
183 #endif
185 #ifdef USE_UART5
187 .device = UARTDEV_5,
188 .reg = UART5,
189 .rxDMAChannel = DMA_CHANNEL_4,
190 .txDMAChannel = DMA_CHANNEL_4,
191 #ifdef USE_UART5_RX_DMA
192 .rxDMAResource = (dmaResource_t *)DMA1_Stream0,
193 #endif
194 #ifdef USE_UART5_TX_DMA
195 .txDMAResource = (dmaResource_t *)DMA1_Stream7,
196 #endif
197 .rxPins = {
198 { DEFIO_TAG_E(PD2), GPIO_AF8_UART5 },
199 #ifdef STM32F765xx
200 { DEFIO_TAG_E(PB5), GPIO_AF1_UART5 },
201 { DEFIO_TAG_E(PB8), GPIO_AF7_UART5 },
202 { DEFIO_TAG_E(PB12), GPIO_AF8_UART5 }
203 #endif
205 .txPins = {
206 { DEFIO_TAG_E(PC12), GPIO_AF8_UART5 },
207 #ifdef STM32F765xx
208 { DEFIO_TAG_E(PB6), GPIO_AF1_UART5 },
209 { DEFIO_TAG_E(PB9), GPIO_AF7_UART5 },
210 { DEFIO_TAG_E(PB13), GPIO_AF8_UART5 }
211 #endif
213 .rcc = RCC_APB1(UART5),
214 .rxIrq = UART5_IRQn,
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),
222 #endif
224 #ifdef USE_UART6
226 .device = UARTDEV_6,
227 .reg = USART6,
228 .rxDMAChannel = DMA_CHANNEL_5,
229 .txDMAChannel = DMA_CHANNEL_5,
230 #ifdef USE_UART6_RX_DMA
231 .rxDMAResource = (dmaResource_t *)DMA2_Stream1,
232 #endif
233 #ifdef USE_UART6_TX_DMA
234 .txDMAResource = (dmaResource_t *)DMA2_Stream6,
235 #endif
236 .rxPins = {
237 { DEFIO_TAG_E(PC7), GPIO_AF8_USART6 },
238 { DEFIO_TAG_E(PG9), GPIO_AF8_USART6 }
240 .txPins = {
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),
253 #endif
255 #ifdef USE_UART7
257 .device = UARTDEV_7,
258 .reg = UART7,
259 .rxDMAChannel = DMA_CHANNEL_5,
260 .txDMAChannel = DMA_CHANNEL_5,
261 #ifdef USE_UART7_RX_DMA
262 .rxDMAResource = (dmaResource_t *)DMA1_Stream3,
263 #endif
264 #ifdef USE_UART7_TX_DMA
265 .txDMAResource = (dmaResource_t *)DMA1_Stream1,
266 #endif
267 .rxPins = {
268 { DEFIO_TAG_E(PE7), GPIO_AF8_UART7 },
269 { DEFIO_TAG_E(PF6), GPIO_AF8_UART7 },
270 #ifdef STM32F765xx
271 { DEFIO_TAG_E(PA8), GPIO_AF12_UART7 },
272 { DEFIO_TAG_E(PB3), GPIO_AF12_UART7 }
273 #endif
275 .txPins = {
276 { DEFIO_TAG_E(PE8), GPIO_AF8_UART7 },
277 { DEFIO_TAG_E(PF7), GPIO_AF8_UART7 },
278 #ifdef STM32F765xx
279 { DEFIO_TAG_E(PA15), GPIO_AF12_UART7 },
280 { DEFIO_TAG_E(PB4), GPIO_AF12_UART7 }
281 #endif
283 .rcc = RCC_APB1(UART7),
284 .rxIrq = UART7_IRQn,
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),
292 #endif
294 #ifdef USE_UART8
296 .device = UARTDEV_8,
297 .reg = UART8,
298 .rxDMAChannel = DMA_CHANNEL_5,
299 .txDMAChannel = DMA_CHANNEL_5,
300 #ifdef USE_UART8_RX_DMA
301 .rxDMAResource = (dmaResource_t *)DMA1_Stream6,
302 #endif
303 #ifdef USE_UART8_TX_DMA
304 .txDMAResource = (dmaResource_t *)DMA1_Stream0,
305 #endif
306 .rxPins = {
307 { DEFIO_TAG_E(PE0), GPIO_AF8_UART8 }
309 .txPins = {
310 { DEFIO_TAG_E(PE1), GPIO_AF8_UART8 }
312 .rcc = RCC_APB1(UART8),
313 .rxIrq = UART8_IRQn,
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),
321 #endif
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];
329 if (!uartdev) {
330 return NULL;
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 #ifdef USE_DMA
349 uartConfigureDma(uartdev);
350 #endif
352 s->Handle.Instance = hardware->reg;
354 if (hardware->rcc) {
355 RCC_ClockCmd(hardware->rcc, ENABLE);
358 IO_t txIO = IOGetByTag(uartdev->tx.pin);
359 IO_t rxIO = IOGetByTag(uartdev->rx.pin);
361 if ((options & SERIAL_BIDIR) && txIO) {
362 ioConfig_t ioCfg = IO_CONFIG(
363 ((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_MODE_AF_PP : GPIO_MODE_AF_OD,
364 GPIO_SPEED_FREQ_HIGH,
365 ((options & SERIAL_INVERTED) || (options & SERIAL_BIDIR_PP_PD)) ? GPIO_PULLDOWN : GPIO_PULLUP
368 IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
369 IOConfigGPIOAF(txIO, ioCfg, uartdev->tx.af);
371 else {
372 if ((mode & MODE_TX) && txIO) {
373 IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
374 IOConfigGPIOAF(txIO, IOCFG_AF_PP, uartdev->tx.af);
377 if ((mode & MODE_RX) && rxIO) {
378 IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(device));
379 IOConfigGPIOAF(rxIO, IOCFG_AF_PP, uartdev->rx.af);
383 #ifdef USE_DMA
384 if (!s->rxDMAResource) {
385 HAL_NVIC_SetPriority(hardware->rxIrq, NVIC_PRIORITY_BASE(hardware->rxPriority), NVIC_PRIORITY_SUB(hardware->rxPriority));
386 HAL_NVIC_EnableIRQ(hardware->rxIrq);
388 #endif
390 return s;
392 #endif // USE_UART