2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
23 #include "drivers/time.h"
24 #include "drivers/io.h"
26 #include "drivers/nvic.h"
29 #include "serial_uart.h"
30 #include "serial_uart_impl.h"
32 #define UART_RX_BUFFER_SIZE UART1_RX_BUFFER_SIZE
33 #define UART_TX_BUFFER_SIZE UART1_RX_BUFFER_SIZE
35 typedef struct uartDevice_s
{
42 volatile uint8_t rxBuffer
[UART_RX_BUFFER_SIZE
];
43 volatile uint8_t txBuffer
[UART_TX_BUFFER_SIZE
];
45 rccPeriphTag_t rcc_apb2
;
46 rccPeriphTag_t rcc_apb1
;
53 static uartDevice_t uart1
= {
55 .rx
= IO_TAG(UART1_RX_PIN
),
56 .tx
= IO_TAG(UART1_TX_PIN
),
57 #if defined(UART1_RX_AF)
58 .rx_af
= CONCAT(GPIO_MUX_
, UART1_RX_AF
),
59 #elif defined(UART1_AF)
60 .rx_af
= CONCAT(GPIO_MUX_
, UART1_AF
),
64 #if defined(UART1_TX_AF)
65 .tx_af
= CONCAT(GPIO_MUX_
, UART1_TX_AF
),
66 #elif defined(UART1_AF)
67 .tx_af
= CONCAT(GPIO_MUX_
, UART1_AF
),
71 #ifdef UART1_AHB1_PERIPHERALS
72 .rcc_ahb1
= UART1_AHB1_PERIPHERALS
,
74 .rcc_apb2
= RCC_APB2(USART1
),
76 .irqPriority
= NVIC_PRIO_SERIALUART
,
77 #ifdef USE_UART1_PIN_SWAP
86 static uartDevice_t uart2
=
89 .rx
= IO_TAG(UART2_RX_PIN
),
90 .tx
= IO_TAG(UART2_TX_PIN
),
91 #if defined(UART2_RX_AF)
92 .rx_af
= CONCAT(GPIO_MUX_
, UART2_RX_AF
),
93 #elif defined(UART2_AF)
94 .rx_af
= CONCAT(GPIO_MUX_
, UART2_AF
),
98 #if defined(UART2_TX_AF)
99 .tx_af
= CONCAT(GPIO_MUX_
, UART2_TX_AF
),
100 #elif defined(UART2_AF)
101 .tx_af
= CONCAT(GPIO_MUX_
, UART2_AF
),
105 #ifdef UART2_AHB1_PERIPHERALS
106 .rcc_ahb1
= UART2_AHB1_PERIPHERALS
,
108 .rcc_apb1
= RCC_APB1(USART2
),
110 .irqPriority
= NVIC_PRIO_SERIALUART
,
111 #ifdef USE_UART2_PIN_SWAP
120 static uartDevice_t uart3
=
123 .rx
= IO_TAG(UART3_RX_PIN
),
124 .tx
= IO_TAG(UART3_TX_PIN
),
125 #if defined(UART3_RX_AF)
126 .rx_af
= CONCAT(GPIO_MUX_
, UART3_RX_AF
),
127 #elif defined(UART3_AF)
128 .rx_af
= CONCAT(GPIO_MUX_
, UART3_AF
),
132 #if defined(UART3_TX_AF)
133 .tx_af
= CONCAT(GPIO_MUX_
, UART3_TX_AF
),
134 #elif defined(UART3_AF)
135 .tx_af
= CONCAT(GPIO_MUX_
, UART3_AF
),
139 #ifdef UART3_AHB1_PERIPHERALS
140 .rcc_ahb1
= UART3_AHB1_PERIPHERALS
,
142 .rcc_apb1
= RCC_APB1(USART3
),
144 .irqPriority
= NVIC_PRIO_SERIALUART
,
145 #ifdef USE_UART3_PIN_SWAP
154 static uartDevice_t uart4
=
157 .rx
= IO_TAG(UART4_RX_PIN
),
158 .tx
= IO_TAG(UART4_TX_PIN
),
159 #if defined(UART4_RX_AF)
160 .rx_af
= CONCAT(GPIO_MUX_
, UART4_RX_AF
),
161 #elif defined(UART4_AF)
162 .rx_af
= CONCAT(GPIO_MUX_
, UART4_AF
),
166 #if defined(UART4_TX_AF)
167 .tx_af
= CONCAT(GPIO_MUX_
, UART4_TX_AF
),
168 #elif defined(UART4_AF)
169 .tx_af
= CONCAT(GPIO_MUX_
, UART4_AF
),
173 #ifdef UART4_AHB1_PERIPHERALS
174 .rcc_ahb1
= UART4_AHB1_PERIPHERALS
,
176 .rcc_apb1
= RCC_APB1(UART4
),
178 .irqPriority
= NVIC_PRIO_SERIALUART
,
179 #ifdef USE_UART4_PIN_SWAP
188 static uartDevice_t uart5
=
191 .rx
= IO_TAG(UART5_RX_PIN
),
192 .tx
= IO_TAG(UART5_TX_PIN
),
193 #if defined(UART5_RX_AF)
194 .rx_af
= CONCAT(GPIO_MUX_
, UART5_RX_AF
),
195 #elif defined(UART5_AF)
196 .rx_af
= CONCAT(GPIO_MUX_
, UART5_AF
),
200 #if defined(UART5_TX_AF)
201 .tx_af
= CONCAT(GPIO_MUX_
, UART5_TX_AF
),
202 #elif defined(UART5_AF)
203 .tx_af
= CONCAT(GPIO_MUX_
, UART5_AF
),
207 #ifdef UART5_AHB1_PERIPHERALS
208 .rcc_ahb1
= UART5_AHB1_PERIPHERALS
,
210 .rcc_apb1
= RCC_APB1(UART5
),
212 .irqPriority
= NVIC_PRIO_SERIALUART
,
213 #ifdef USE_UART5_PIN_SWAP
222 static uartDevice_t uart6
=
225 .rx
= IO_TAG(UART6_RX_PIN
),
226 .tx
= IO_TAG(UART6_TX_PIN
),
227 #if defined(UART6_RX_AF)
228 .rx_af
= CONCAT(GPIO_MUX_
, UART6_RX_AF
),
229 #elif defined(UART6_AF)
230 .rx_af
= CONCAT(GPIO_MUX_
, UART6_AF
),
234 #if defined(UART6_TX_AF)
235 .tx_af
= CONCAT(GPIO_MUX_
, UART6_TX_AF
),
236 #elif defined(UART6_AF)
237 .tx_af
= CONCAT(GPIO_MUX_
, UART6_AF
),
241 #ifdef UART6_AHB1_PERIPHERALS
242 .rcc_ahb1
= UART6_AHB1_PERIPHERALS
,
244 .rcc_apb2
= RCC_APB2(USART6
),
246 .irqPriority
= NVIC_PRIO_SERIALUART
,
247 #ifdef USE_UART6_PIN_SWAP
256 static uartDevice_t uart7
=
259 .rx
= IO_TAG(UART7_RX_PIN
),
260 .tx
= IO_TAG(UART7_TX_PIN
),
261 #if defined(UART7_RX_AF)
262 .rx_af
= CONCAT(GPIO_MUX_
, UART7_RX_AF
),
263 #elif defined(UART7_AF)
264 .rx_af
= CONCAT(GPIO_MUX_
, UART7_AF
),
268 #if defined(UART7_TX_AF)
269 .tx_af
= CONCAT(GPIO_MUX_
, UART7_TX_AF
),
270 #elif defined(UART7_AF)
271 .tx_af
= CONCAT(GPIO_MUX_
, UART7_AF
),
275 .rcc_apb1
= RCC_APB1(UART7
),
277 .irqPriority
= NVIC_PRIO_SERIALUART
,
278 #ifdef USE_UART7_PIN_SWAP
287 static uartDevice_t uart8
=
290 .rx
= IO_TAG(UART8_RX_PIN
),
291 .tx
= IO_TAG(UART8_TX_PIN
),
292 #if defined(UART8_RX_AF)
293 .rx_af
= CONCAT(GPIO_MUX_
, UART8_RX_AF
),
294 #elif defined(UART8_AF)
295 .rx_af
= CONCAT(GPIO_MUX_
, UART8_AF
),
299 #if defined(UART8_TX_AF)
300 .tx_af
= CONCAT(GPIO_MUX_
, UART8_TX_AF
),
301 #elif defined(UART8_AF)
302 .tx_af
= CONCAT(GPIO_MUX_
, UART8_AF
),
306 .rcc_apb1
= RCC_APB1(UART8
),
308 .irqPriority
= NVIC_PRIO_SERIALUART
,
309 #ifdef USE_UART8_PIN_SWAP
317 static uartDevice_t
* uartHardwareMap
[] = {
360 void uartIrqHandler(uartPort_t
*s
)
362 if (usart_flag_get(s
->USARTx
, USART_RDBF_FLAG
) == SET
) {
363 if (s
->port
.rxCallback
) {
364 s
->port
.rxCallback(s
->USARTx
->dt
, s
->port
.rxCallbackData
);
366 s
->port
.rxBuffer
[s
->port
.rxBufferHead
] = s
->USARTx
->dt
;
367 s
->port
.rxBufferHead
= (s
->port
.rxBufferHead
+ 1) % s
->port
.rxBufferSize
;
371 if (usart_flag_get(s
->USARTx
, USART_TDBE_FLAG
) == SET
) {
372 if (s
->port
.txBufferTail
!= s
->port
.txBufferHead
) {
373 usart_data_transmit(s
->USARTx
, s
->port
.txBuffer
[s
->port
.txBufferTail
]);
374 s
->port
.txBufferTail
= (s
->port
.txBufferTail
+ 1) % s
->port
.txBufferSize
;
376 usart_interrupt_enable (s
->USARTx
, USART_TDBE_INT
, FALSE
);
380 if (usart_flag_get(s
->USARTx
, USART_ROERR_FLAG
) == SET
)
382 usart_flag_clear(s
->USARTx
, USART_ROERR_FLAG
);
386 void uartGetPortPins(UARTDevice_e device
, serialPortPins_t
* pins
)
388 uartDevice_t
*uart
= uartHardwareMap
[device
];
391 pins
->txPin
= uart
->tx
;
392 pins
->rxPin
= uart
->rx
;
395 pins
->txPin
= IO_TAG(NONE
);
396 pins
->rxPin
= IO_TAG(NONE
);
400 void uartClearIdleFlag(uartPort_t
*s
)
402 (void) s
->USARTx
->sts
;
403 (void) s
->USARTx
->dt
;
406 static uartDevice_t
*uartFindDevice(uartPort_t
*uartPort
)
408 for (uint32_t i
= 0; i
< UARTDEV_MAX
; i
++) {
409 uartDevice_t
*pDevice
= uartHardwareMap
[i
];
411 if (pDevice
->dev
== uartPort
->USARTx
) {
418 void uartConfigurePinSwap(uartPort_t
*uartPort
)
420 uartDevice_t
*uartDevice
= uartFindDevice(uartPort
);
425 if (uartDevice
->pinSwap
) {
426 usart_transmit_receive_pin_swap(uartPort
->USARTx
, TRUE
);
430 uartPort_t
*serialUART(UARTDevice_e device
, uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
434 uartDevice_t
*uart
= uartHardwareMap
[device
];
435 if (!uart
) return NULL
;
438 s
->port
.vTable
= uartVTable
;
440 s
->port
.baudRate
= baudRate
;
442 s
->port
.rxBuffer
= uart
->rxBuffer
;
443 s
->port
.txBuffer
= uart
->txBuffer
;
444 s
->port
.rxBufferSize
= sizeof(uart
->rxBuffer
);
445 s
->port
.txBufferSize
= sizeof(uart
->txBuffer
);
447 s
->USARTx
= uart
->dev
;
449 IO_t tx
= IOGetByTag(uart
->tx
);
450 IO_t rx
= IOGetByTag(uart
->rx
);
453 RCC_ClockCmd(uart
->rcc_apb2
, ENABLE
);
456 RCC_ClockCmd(uart
->rcc_apb1
, ENABLE
);
459 RCC_ClockCmd(uart
->rcc_apb1
, ENABLE
);
461 if (options
& SERIAL_BIDIR
) {
462 IOInit(tx
, OWNER_SERIAL
, RESOURCE_UART_TXRX
, RESOURCE_INDEX(device
));
463 if (options
& SERIAL_BIDIR_PP
) {
464 IOConfigGPIOAF(tx
, IOCFG_AF_PP
, uart
->tx_af
);
467 (options
& SERIAL_BIDIR_NOPULL
) ? IOCFG_AF_OD
: IOCFG_AF_OD_UP
,
472 if (mode
& MODE_TX
) {
473 IOInit(tx
, OWNER_SERIAL
, RESOURCE_UART_TX
, RESOURCE_INDEX(device
));
474 IOConfigGPIOAF(tx
, IOCFG_AF_PP
, uart
->rx_af
);
477 if (mode
& MODE_RX
) {
478 IOInit(rx
, OWNER_SERIAL
, RESOURCE_UART_RX
, RESOURCE_INDEX(device
));
479 IOConfigGPIOAF(rx
, IOCFG_AF_PP
, uart
->rx_af
);
483 nvic_irq_enable(uart
->irq
, uart
->irqPriority
, 0);
490 uartPort_t
*serialUART1(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
492 return serialUART(UARTDEV_1
, baudRate
, mode
, options
);
495 // USART1 Rx/Tx IRQ Handler
496 void USART1_IRQHandler(void)
498 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_1
]->port
);
505 // USART2 (RX + TX by IRQ)
506 uartPort_t
*serialUART2(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
508 return serialUART(UARTDEV_2
, baudRate
, mode
, options
);
511 void USART2_IRQHandler(void)
513 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_2
]->port
);
520 uartPort_t
*serialUART3(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
522 return serialUART(UARTDEV_3
, baudRate
, mode
, options
);
525 void USART3_IRQHandler(void)
527 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_3
]->port
);
534 uartPort_t
*serialUART4(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
536 return serialUART(UARTDEV_4
, baudRate
, mode
, options
);
539 void UART4_IRQHandler(void)
541 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_4
]->port
);
548 uartPort_t
*serialUART5(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
550 return serialUART(UARTDEV_5
, baudRate
, mode
, options
);
553 void UART5_IRQHandler(void)
555 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_5
]->port
);
562 uartPort_t
*serialUART6(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
564 return serialUART(UARTDEV_6
, baudRate
, mode
, options
);
567 void USART6_IRQHandler(void)
569 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_6
]->port
);
575 uartPort_t
*serialUART7(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
577 return serialUART(UARTDEV_7
, baudRate
, mode
, options
);
580 // UART7 Rx/Tx IRQ Handler
581 void UART7_IRQHandler(void)
583 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_7
]->port
);
589 uartPort_t
*serialUART8(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
591 return serialUART(UARTDEV_8
, baudRate
, mode
, options
);
594 // UART8 Rx/Tx IRQ Handler
595 void UART8_IRQHandler(void)
597 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_8
]->port
);