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
{
40 volatile uint8_t rxBuffer
[UART_RX_BUFFER_SIZE
];
41 volatile uint8_t txBuffer
[UART_TX_BUFFER_SIZE
];
43 rccPeriphTag_t rcc_apb2
;
44 rccPeriphTag_t rcc_apb1
;
51 static uartDevice_t uart1
=
54 .rx
= IO_TAG(UART1_RX_PIN
),
55 .tx
= IO_TAG(UART1_TX_PIN
),
57 #ifdef UART1_AHB1_PERIPHERALS
58 .rcc_ahb1
= UART1_AHB1_PERIPHERALS
,
60 .rcc_apb2
= RCC_APB2(USART1
),
62 .irqPriority
= NVIC_PRIO_SERIALUART
67 static uartDevice_t uart2
=
70 .rx
= IO_TAG(UART2_RX_PIN
),
71 .tx
= IO_TAG(UART2_TX_PIN
),
73 #ifdef UART2_AHB1_PERIPHERALS
74 .rcc_ahb1
= UART2_AHB1_PERIPHERALS
,
76 .rcc_apb1
= RCC_APB1(USART2
),
78 .irqPriority
= NVIC_PRIO_SERIALUART
83 static uartDevice_t uart3
=
86 .rx
= IO_TAG(UART3_RX_PIN
),
87 .tx
= IO_TAG(UART3_TX_PIN
),
89 #ifdef UART3_AHB1_PERIPHERALS
90 .rcc_ahb1
= UART3_AHB1_PERIPHERALS
,
92 .rcc_apb1
= RCC_APB1(USART3
),
94 .irqPriority
= NVIC_PRIO_SERIALUART
99 static uartDevice_t uart4
=
102 .rx
= IO_TAG(UART4_RX_PIN
),
103 .tx
= IO_TAG(UART4_TX_PIN
),
105 #ifdef UART4_AHB1_PERIPHERALS
106 .rcc_ahb1
= UART4_AHB1_PERIPHERALS
,
108 .rcc_apb1
= RCC_APB1(UART4
),
110 .irqPriority
= NVIC_PRIO_SERIALUART
115 static uartDevice_t uart5
=
118 .rx
= IO_TAG(UART5_RX_PIN
),
119 .tx
= IO_TAG(UART5_TX_PIN
),
121 #ifdef UART5_AHB1_PERIPHERALS
122 .rcc_ahb1
= UART5_AHB1_PERIPHERALS
,
124 .rcc_apb1
= RCC_APB1(UART5
),
126 .irqPriority
= NVIC_PRIO_SERIALUART
131 static uartDevice_t uart6
=
134 .rx
= IO_TAG(UART6_RX_PIN
),
135 .tx
= IO_TAG(UART6_TX_PIN
),
137 #ifdef UART6_AHB1_PERIPHERALS
138 .rcc_ahb1
= UART6_AHB1_PERIPHERALS
,
140 .rcc_apb2
= RCC_APB2(USART6
),
142 .irqPriority
= NVIC_PRIO_SERIALUART
147 static uartDevice_t uart7
=
150 .rx
= IO_TAG(UART7_RX_PIN
),
151 .tx
= IO_TAG(UART7_TX_PIN
),
153 .rcc_apb1
= RCC_APB1(UART7
),
155 .irqPriority
= NVIC_PRIO_SERIALUART
160 static uartDevice_t uart8
=
163 .rx
= IO_TAG(UART8_RX_PIN
),
164 .tx
= IO_TAG(UART8_TX_PIN
),
166 .rcc_apb1
= RCC_APB1(UART8
),
168 .irqPriority
= NVIC_PRIO_SERIALUART
172 static uartDevice_t
* uartHardwareMap
[] = {
215 void uartIrqHandler(uartPort_t
*s
)
217 if (usart_flag_get(s
->USARTx
, USART_RDBF_FLAG
) == SET
) {
218 if (s
->port
.rxCallback
) {
219 s
->port
.rxCallback(s
->USARTx
->dt
, s
->port
.rxCallbackData
);
221 s
->port
.rxBuffer
[s
->port
.rxBufferHead
] = s
->USARTx
->dt
;
222 s
->port
.rxBufferHead
= (s
->port
.rxBufferHead
+ 1) % s
->port
.rxBufferSize
;
226 if (usart_flag_get(s
->USARTx
, USART_TDBE_FLAG
) == SET
) {
227 if (s
->port
.txBufferTail
!= s
->port
.txBufferHead
) {
228 usart_data_transmit(s
->USARTx
, s
->port
.txBuffer
[s
->port
.txBufferTail
]);
229 s
->port
.txBufferTail
= (s
->port
.txBufferTail
+ 1) % s
->port
.txBufferSize
;
231 usart_interrupt_enable (s
->USARTx
, USART_TDBE_INT
, FALSE
);
235 if (usart_flag_get(s
->USARTx
, USART_ROERR_FLAG
) == SET
)
237 usart_flag_clear(s
->USARTx
, USART_ROERR_FLAG
);
241 void uartGetPortPins(UARTDevice_e device
, serialPortPins_t
* pins
)
243 uartDevice_t
*uart
= uartHardwareMap
[device
];
246 pins
->txPin
= uart
->tx
;
247 pins
->rxPin
= uart
->rx
;
250 pins
->txPin
= IO_TAG(NONE
);
251 pins
->rxPin
= IO_TAG(NONE
);
255 void uartClearIdleFlag(uartPort_t
*s
)
257 (void) s
->USARTx
->sts
;
258 (void) s
->USARTx
->dt
;
261 uartPort_t
*serialUART(UARTDevice_e device
, uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
265 uartDevice_t
*uart
= uartHardwareMap
[device
];
266 if (!uart
) return NULL
;
269 s
->port
.vTable
= uartVTable
;
271 s
->port
.baudRate
= baudRate
;
273 s
->port
.rxBuffer
= uart
->rxBuffer
;
274 s
->port
.txBuffer
= uart
->txBuffer
;
275 s
->port
.rxBufferSize
= sizeof(uart
->rxBuffer
);
276 s
->port
.txBufferSize
= sizeof(uart
->txBuffer
);
278 s
->USARTx
= uart
->dev
;
280 IO_t tx
= IOGetByTag(uart
->tx
);
281 IO_t rx
= IOGetByTag(uart
->rx
);
284 RCC_ClockCmd(uart
->rcc_apb2
, ENABLE
);
287 RCC_ClockCmd(uart
->rcc_apb1
, ENABLE
);
290 RCC_ClockCmd(uart
->rcc_apb1
, ENABLE
);
292 if (options
& SERIAL_BIDIR
) {
293 IOInit(tx
, OWNER_SERIAL
, RESOURCE_UART_TXRX
, RESOURCE_INDEX(device
));
294 if (options
& SERIAL_BIDIR_PP
) {
295 IOConfigGPIOAF(tx
, IOCFG_AF_PP
, uart
->af
);
298 (options
& SERIAL_BIDIR_NOPULL
) ? IOCFG_AF_OD
: IOCFG_AF_OD_UP
,
303 if (mode
& MODE_TX
) {
304 IOInit(tx
, OWNER_SERIAL
, RESOURCE_UART_TX
, RESOURCE_INDEX(device
));
305 IOConfigGPIOAF(tx
, IOCFG_AF_PP
, uart
->af
);
308 if (mode
& MODE_RX
) {
309 IOInit(rx
, OWNER_SERIAL
, RESOURCE_UART_RX
, RESOURCE_INDEX(device
));
310 IOConfigGPIOAF(rx
, IOCFG_AF_PP
, uart
->af
);
314 nvic_irq_enable(uart
->irq
, uart
->irqPriority
, 0);
321 uartPort_t
*serialUART1(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
323 return serialUART(UARTDEV_1
, baudRate
, mode
, options
);
326 // USART1 Rx/Tx IRQ Handler
327 void USART1_IRQHandler(void)
329 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_1
]->port
);
336 // USART2 (RX + TX by IRQ)
337 uartPort_t
*serialUART2(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
339 return serialUART(UARTDEV_2
, baudRate
, mode
, options
);
342 void USART2_IRQHandler(void)
344 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_2
]->port
);
351 uartPort_t
*serialUART3(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
353 return serialUART(UARTDEV_3
, baudRate
, mode
, options
);
356 void USART3_IRQHandler(void)
358 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_3
]->port
);
365 uartPort_t
*serialUART4(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
367 return serialUART(UARTDEV_4
, baudRate
, mode
, options
);
370 void UART4_IRQHandler(void)
372 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_4
]->port
);
379 uartPort_t
*serialUART5(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
381 return serialUART(UARTDEV_5
, baudRate
, mode
, options
);
384 void UART5_IRQHandler(void)
386 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_5
]->port
);
393 uartPort_t
*serialUART6(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
395 return serialUART(UARTDEV_6
, baudRate
, mode
, options
);
398 void USART6_IRQHandler(void)
400 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_6
]->port
);
406 uartPort_t
*serialUART7(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
408 return serialUART(UARTDEV_7
, baudRate
, mode
, options
);
411 // UART7 Rx/Tx IRQ Handler
412 void UART7_IRQHandler(void)
414 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_7
]->port
);
420 uartPort_t
*serialUART8(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
422 return serialUART(UARTDEV_8
, baudRate
, mode
, options
);
425 // UART8 Rx/Tx IRQ Handler
426 void UART8_IRQHandler(void)
428 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_8
]->port
);