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
;
50 //static uartPort_t uartPort[MAX_UARTS];
52 static uartDevice_t uart1
=
55 .rx
= IO_TAG(UART1_RX_PIN
),
56 .tx
= IO_TAG(UART1_TX_PIN
),
58 #ifdef UART1_AHB1_PERIPHERALS
59 .rcc_ahb1
= UART1_AHB1_PERIPHERALS
,
61 .rcc_apb2
= RCC_APB2(USART1
),
63 .irqPriority
= NVIC_PRIO_SERIALUART
68 static uartDevice_t uart2
=
71 .rx
= IO_TAG(UART2_RX_PIN
),
72 .tx
= IO_TAG(UART2_TX_PIN
),
74 #ifdef UART2_AHB1_PERIPHERALS
75 .rcc_ahb1
= UART2_AHB1_PERIPHERALS
,
77 .rcc_apb1
= RCC_APB1(USART2
),
79 .irqPriority
= NVIC_PRIO_SERIALUART
84 static uartDevice_t uart3
=
87 .rx
= IO_TAG(UART3_RX_PIN
),
88 .tx
= IO_TAG(UART3_TX_PIN
),
90 #ifdef UART3_AHB1_PERIPHERALS
91 .rcc_ahb1
= UART3_AHB1_PERIPHERALS
,
93 .rcc_apb1
= RCC_APB1(USART3
),
95 .irqPriority
= NVIC_PRIO_SERIALUART
100 static uartDevice_t uart4
=
103 .rx
= IO_TAG(UART4_RX_PIN
),
104 .tx
= IO_TAG(UART4_TX_PIN
),
106 #ifdef UART4_AHB1_PERIPHERALS
107 .rcc_ahb1
= UART4_AHB1_PERIPHERALS
,
109 .rcc_apb1
= RCC_APB1(UART4
),
111 .irqPriority
= NVIC_PRIO_SERIALUART
116 static uartDevice_t uart5
=
119 .rx
= IO_TAG(UART5_RX_PIN
),
120 .tx
= IO_TAG(UART5_TX_PIN
),
122 #ifdef UART5_AHB1_PERIPHERALS
123 .rcc_ahb1
= UART5_AHB1_PERIPHERALS
,
125 .rcc_apb1
= RCC_APB1(UART5
),
127 .irqPriority
= NVIC_PRIO_SERIALUART
132 static uartDevice_t uart6
=
135 .rx
= IO_TAG(UART6_RX_PIN
),
136 .tx
= IO_TAG(UART6_TX_PIN
),
137 .af
= GPIO_AF_USART6
,
138 #ifdef UART6_AHB1_PERIPHERALS
139 .rcc_ahb1
= UART6_AHB1_PERIPHERALS
,
141 .rcc_apb2
= RCC_APB2(USART6
),
143 .irqPriority
= NVIC_PRIO_SERIALUART
148 static uartDevice_t uart7
=
151 .rx
= IO_TAG(UART7_RX_PIN
),
152 .tx
= IO_TAG(UART7_TX_PIN
),
154 .rcc_apb1
= RCC_APB1(UART7
),
156 .irqPriority
= NVIC_PRIO_SERIALUART
161 static uartDevice_t uart8
=
164 .rx
= IO_TAG(UART8_RX_PIN
),
165 .tx
= IO_TAG(UART8_TX_PIN
),
167 .rcc_apb1
= RCC_APB1(UART8
),
169 .irqPriority
= NVIC_PRIO_SERIALUART
173 static uartDevice_t
* uartHardwareMap
[] = {
216 void uartIrqHandler(uartPort_t
*s
)
218 if (USART_GetITStatus(s
->USARTx
, USART_IT_RXNE
) == SET
) {
219 if (s
->port
.rxCallback
) {
220 s
->port
.rxCallback(s
->USARTx
->DR
, s
->port
.rxCallbackData
);
222 s
->port
.rxBuffer
[s
->port
.rxBufferHead
] = s
->USARTx
->DR
;
223 s
->port
.rxBufferHead
= (s
->port
.rxBufferHead
+ 1) % s
->port
.rxBufferSize
;
227 if (USART_GetITStatus(s
->USARTx
, USART_IT_TXE
) == SET
) {
228 if (s
->port
.txBufferTail
!= s
->port
.txBufferHead
) {
229 USART_SendData(s
->USARTx
, s
->port
.txBuffer
[s
->port
.txBufferTail
]);
230 s
->port
.txBufferTail
= (s
->port
.txBufferTail
+ 1) % s
->port
.txBufferSize
;
232 USART_ITConfig(s
->USARTx
, USART_IT_TXE
, DISABLE
);
236 if (USART_GetITStatus(s
->USARTx
, USART_FLAG_ORE
) == SET
)
238 USART_ClearITPendingBit (s
->USARTx
, USART_IT_ORE
);
242 void uartGetPortPins(UARTDevice_e device
, serialPortPins_t
* pins
)
244 uartDevice_t
*uart
= uartHardwareMap
[device
];
247 pins
->txPin
= uart
->tx
;
248 pins
->rxPin
= uart
->rx
;
251 pins
->txPin
= IO_TAG(NONE
);
252 pins
->rxPin
= IO_TAG(NONE
);
256 void uartClearIdleFlag(uartPort_t
*s
)
258 (void) s
->USARTx
->SR
;
259 (void) s
->USARTx
->DR
;
262 uartPort_t
*serialUART(UARTDevice_e device
, uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
266 uartDevice_t
*uart
= uartHardwareMap
[device
];
267 if (!uart
) return NULL
;
270 s
->port
.vTable
= uartVTable
;
272 s
->port
.baudRate
= baudRate
;
274 s
->port
.rxBuffer
= uart
->rxBuffer
;
275 s
->port
.txBuffer
= uart
->txBuffer
;
276 s
->port
.rxBufferSize
= sizeof(uart
->rxBuffer
);
277 s
->port
.txBufferSize
= sizeof(uart
->txBuffer
);
279 s
->USARTx
= uart
->dev
;
281 IO_t tx
= IOGetByTag(uart
->tx
);
282 IO_t rx
= IOGetByTag(uart
->rx
);
285 RCC_ClockCmd(uart
->rcc_apb2
, ENABLE
);
288 RCC_ClockCmd(uart
->rcc_apb1
, ENABLE
);
291 RCC_AHB1PeriphClockCmd(uart
->rcc_ahb1
, ENABLE
);
293 if (options
& SERIAL_BIDIR
) {
294 IOInit(tx
, OWNER_SERIAL
, RESOURCE_UART_TXRX
, RESOURCE_INDEX(device
));
295 if (options
& SERIAL_BIDIR_PP
) {
296 IOConfigGPIOAF(tx
, IOCFG_AF_PP
, uart
->af
);
299 (options
& SERIAL_BIDIR_NOPULL
) ? IOCFG_AF_OD
: IOCFG_AF_OD_UP
,
304 if (mode
& MODE_TX
) {
305 IOInit(tx
, OWNER_SERIAL
, RESOURCE_UART_TX
, RESOURCE_INDEX(device
));
306 IOConfigGPIOAF(tx
, IOCFG_AF_PP
, uart
->af
);
309 if (mode
& MODE_RX
) {
310 IOInit(rx
, OWNER_SERIAL
, RESOURCE_UART_RX
, RESOURCE_INDEX(device
));
311 IOConfigGPIOAF(rx
, IOCFG_AF_PP
, uart
->af
);
315 NVIC_SetPriority(uart
->irq
, uart
->irqPriority
);
316 NVIC_EnableIRQ(uart
->irq
);
322 uartPort_t
*serialUART1(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
324 return serialUART(UARTDEV_1
, baudRate
, mode
, options
);
327 // USART1 Rx/Tx IRQ Handler
328 void USART1_IRQHandler(void)
330 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_1
]->port
);
337 // USART2 - GPS or Spektrum or ?? (RX + TX by IRQ)
338 uartPort_t
*serialUART2(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
340 return serialUART(UARTDEV_2
, baudRate
, mode
, options
);
343 void USART2_IRQHandler(void)
345 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_2
]->port
);
352 uartPort_t
*serialUART3(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
354 return serialUART(UARTDEV_3
, baudRate
, mode
, options
);
357 void USART3_IRQHandler(void)
359 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_3
]->port
);
366 uartPort_t
*serialUART4(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
368 return serialUART(UARTDEV_4
, baudRate
, mode
, options
);
371 void UART4_IRQHandler(void)
373 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_4
]->port
);
380 uartPort_t
*serialUART5(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
382 return serialUART(UARTDEV_5
, baudRate
, mode
, options
);
385 void UART5_IRQHandler(void)
387 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_5
]->port
);
394 uartPort_t
*serialUART6(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
396 return serialUART(UARTDEV_6
, baudRate
, mode
, options
);
399 void USART6_IRQHandler(void)
401 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_6
]->port
);
407 uartPort_t
*serialUART7(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
409 return serialUART(UARTDEV_7
, baudRate
, mode
, options
);
412 // UART7 Rx/Tx IRQ Handler
413 void UART7_IRQHandler(void)
415 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_7
]->port
);
421 uartPort_t
*serialUART8(uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
423 return serialUART(UARTDEV_8
, baudRate
, mode
, options
);
426 // UART8 Rx/Tx IRQ Handler
427 void UART8_IRQHandler(void)
429 uartPort_t
*s
= &(uartHardwareMap
[UARTDEV_8
]->port
);