Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / serial_uart_stm32h7xx.c
blob9debfe66c729ace845a70251fe3eaf393683d090
1 /*
2 * This file is part of INAV.
4 * INAV 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 * INAV 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 INAV. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
21 #include "platform.h"
23 #include "drivers/time.h"
24 #include "drivers/io.h"
25 #include "rcc.h"
26 #include "drivers/nvic.h"
28 #include "serial.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_TX_BUFFER_SIZE
35 typedef struct uartDevice_s {
36 USART_TypeDef* dev;
37 uartPort_t port;
38 ioTag_t rx;
39 ioTag_t tx;
40 volatile uint8_t rxBuffer[UART_RX_BUFFER_SIZE];
41 volatile uint8_t txBuffer[UART_TX_BUFFER_SIZE];
42 rccPeriphTag_t rcc;
43 uint8_t af_rx;
44 uint8_t af_tx;
45 uint8_t irq;
46 } uartDevice_t;
48 #define UART_PIN_AF_HELPER(uart, pin) CONCAT4(UART_PIN_AF_UART, uart, _, pin)
50 #ifdef USE_UART1
51 #define UART_PIN_AF_UART1_PA9 GPIO_AF7_USART1
52 #define UART_PIN_AF_UART1_PA10 GPIO_AF7_USART1
53 #define UART_PIN_AF_UART1_PB6 GPIO_AF7_USART1
54 #define UART_PIN_AF_UART1_PB7 GPIO_AF7_USART1
55 #define UART_PIN_AF_UART1_PB14 GPIO_AF4_USART1
56 #define UART_PIN_AF_UART1_PB15 GPIO_AF4_USART1
58 static uartDevice_t uart1 =
60 .dev = USART1,
61 .rx = IO_TAG(UART1_RX_PIN),
62 .tx = IO_TAG(UART1_TX_PIN),
63 .af_rx = UART_PIN_AF_HELPER(1, UART1_RX_PIN),
64 .af_tx = UART_PIN_AF_HELPER(1, UART1_TX_PIN),
65 .rcc = RCC_APB2(USART1),
66 .irq = USART1_IRQn,
68 #endif
70 #ifdef USE_UART2
71 static uartDevice_t uart2 =
73 .dev = USART2,
74 .rx = IO_TAG(UART2_RX_PIN),
75 .tx = IO_TAG(UART2_TX_PIN),
76 .af_rx = GPIO_AF7_USART2,
77 .af_tx = GPIO_AF7_USART2,
78 .rcc = RCC_APB1L(USART2),
79 .irq = USART2_IRQn,
81 #endif
83 #ifdef USE_UART3
84 static uartDevice_t uart3 =
86 .dev = USART3,
87 .rx = IO_TAG(UART3_RX_PIN),
88 .tx = IO_TAG(UART3_TX_PIN),
89 .af_rx = GPIO_AF7_USART3,
90 .af_tx = GPIO_AF7_USART3,
91 .rcc = RCC_APB1L(USART3),
92 .irq = USART3_IRQn,
94 #endif
96 #ifdef USE_UART4
97 #define UART_PIN_AF_UART4_PA0 GPIO_AF8_UART4
98 #define UART_PIN_AF_UART4_PA1 GPIO_AF8_UART4
99 #define UART_PIN_AF_UART4_PA11 GPIO_AF6_UART4
100 #define UART_PIN_AF_UART4_PA12 GPIO_AF6_UART4
101 #define UART_PIN_AF_UART4_PB8 GPIO_AF8_UART4
102 #define UART_PIN_AF_UART4_PB9 GPIO_AF8_UART4
103 #define UART_PIN_AF_UART4_PC10 GPIO_AF8_UART4
104 #define UART_PIN_AF_UART4_PC11 GPIO_AF8_UART4
105 #define UART_PIN_AF_UART4_PD0 GPIO_AF8_UART4
106 #define UART_PIN_AF_UART4_PD1 GPIO_AF8_UART4
108 static uartDevice_t uart4 =
110 .dev = UART4,
111 .rx = IO_TAG(UART4_RX_PIN),
112 .tx = IO_TAG(UART4_TX_PIN),
113 .af_rx = UART_PIN_AF_HELPER(4, UART4_RX_PIN),
114 .af_tx = UART_PIN_AF_HELPER(4, UART4_TX_PIN),
115 .rcc = RCC_APB1L(UART4),
116 .irq = UART4_IRQn,
118 #endif
120 #ifdef USE_UART5
121 #define UART_PIN_AF_UART5_PB5 GPIO_AF14_UART5
122 #define UART_PIN_AF_UART5_PB6 GPIO_AF14_UART5
123 #define UART_PIN_AF_UART5_PB12 GPIO_AF14_UART5
124 #define UART_PIN_AF_UART5_PB13 GPIO_AF14_UART5
125 #define UART_PIN_AF_UART5_PD2 GPIO_AF8_UART5
126 #define UART_PIN_AF_UART5_PC12 GPIO_AF8_UART5
128 static uartDevice_t uart5 =
130 .dev = UART5,
131 .rx = IO_TAG(UART5_RX_PIN),
132 .tx = IO_TAG(UART5_TX_PIN),
133 .af_rx = UART_PIN_AF_HELPER(5, UART5_RX_PIN),
134 .af_tx = UART_PIN_AF_HELPER(5, UART5_TX_PIN),
135 .rcc = RCC_APB1L(UART5),
136 .irq = UART5_IRQn,
138 #endif
140 #ifdef USE_UART6
141 static uartDevice_t uart6 =
143 .dev = USART6,
144 .rx = IO_TAG(UART6_RX_PIN),
145 .tx = IO_TAG(UART6_TX_PIN),
146 .af_rx = GPIO_AF7_USART6,
147 .af_tx = GPIO_AF7_USART6,
148 .rcc = RCC_APB2(USART6),
149 .irq = USART6_IRQn,
151 #endif
153 #ifdef USE_UART7
154 #define UART_PIN_AF_UART7_PA8 GPIO_AF11_UART7
155 #define UART_PIN_AF_UART7_PA15 GPIO_AF11_UART7
156 #define UART_PIN_AF_UART7_PB3 GPIO_AF11_UART7
157 #define UART_PIN_AF_UART7_PB4 GPIO_AF11_UART7
158 #define UART_PIN_AF_UART7_PE7 GPIO_AF7_UART7
159 #define UART_PIN_AF_UART7_PE8 GPIO_AF7_UART7
160 #define UART_PIN_AF_UART7_PF6 GPIO_AF7_UART7
161 #define UART_PIN_AF_UART7_PF7 GPIO_AF7_UART7
163 static uartDevice_t uart7 =
165 .dev = UART7,
166 .rx = IO_TAG(UART7_RX_PIN),
167 #ifdef UART7_TX_PIN
168 .tx = IO_TAG(UART7_TX_PIN),
169 #endif
170 .af_rx = UART_PIN_AF_HELPER(7, UART7_RX_PIN),
171 #ifdef UART7_TX_PIN
172 .af_tx = UART_PIN_AF_HELPER(7, UART7_TX_PIN),
173 #endif
174 .rcc = RCC_APB1L(UART7),
175 .irq = UART7_IRQn,
177 #endif
179 #ifdef USE_UART8
180 static uartDevice_t uart8 =
182 .dev = UART8,
183 .rx = IO_TAG(UART8_RX_PIN),
184 .tx = IO_TAG(UART8_TX_PIN),
185 .af_rx = GPIO_AF8_UART8,
186 .af_tx = GPIO_AF8_UART8,
187 .rcc = RCC_APB1L(UART8),
188 .irq = UART8_IRQn,
190 #endif
194 static uartDevice_t* uartHardwareMap[] = {
195 #ifdef USE_UART1
196 &uart1,
197 #else
198 NULL,
199 #endif
200 #ifdef USE_UART2
201 &uart2,
202 #else
203 NULL,
204 #endif
205 #ifdef USE_UART3
206 &uart3,
207 #else
208 NULL,
209 #endif
210 #ifdef USE_UART4
211 &uart4,
212 #else
213 NULL,
214 #endif
215 #ifdef USE_UART5
216 &uart5,
217 #else
218 NULL,
219 #endif
220 #ifdef USE_UART6
221 &uart6,
222 #else
223 NULL,
224 #endif
225 #ifdef USE_UART7
226 &uart7,
227 #else
228 NULL,
229 #endif
230 #ifdef USE_UART8
231 &uart8,
232 #else
233 NULL,
234 #endif
237 void uartGetPortPins(UARTDevice_e device, serialPortPins_t * pins)
239 uartDevice_t *uart = uartHardwareMap[device];
241 if (uart) {
242 pins->txPin = uart->tx;
243 pins->rxPin = uart->rx;
245 else {
246 pins->txPin = IO_TAG(NONE);
247 pins->rxPin = IO_TAG(NONE);
251 void uartIrqHandler(uartPort_t *s)
253 UART_HandleTypeDef *huart = &s->Handle;
254 /* UART in mode Receiver ---------------------------------------------------*/
255 if ((__HAL_UART_GET_IT(huart, UART_IT_RXNE) != RESET)) {
256 uint8_t rbyte = (uint8_t)(huart->Instance->RDR & (uint8_t) 0xff);
258 if (s->port.rxCallback) {
259 s->port.rxCallback(rbyte, s->port.rxCallbackData);
260 } else {
261 s->port.rxBuffer[s->port.rxBufferHead] = rbyte;
262 s->port.rxBufferHead = (s->port.rxBufferHead + 1) % s->port.rxBufferSize;
264 CLEAR_BIT(huart->Instance->CR1, (USART_CR1_PEIE));
266 /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
267 CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
269 __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
272 /* UART parity error interrupt occurred -------------------------------------*/
273 if ((__HAL_UART_GET_IT(huart, UART_IT_PE) != RESET)) {
274 __HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF);
277 /* UART frame error interrupt occurred --------------------------------------*/
278 if ((__HAL_UART_GET_IT(huart, UART_IT_FE) != RESET)) {
279 __HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF);
282 /* UART noise error interrupt occurred --------------------------------------*/
283 if ((__HAL_UART_GET_IT(huart, UART_IT_NE) != RESET)) {
284 __HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF);
287 /* UART Over-Run interrupt occurred -----------------------------------------*/
288 if ((__HAL_UART_GET_IT(huart, UART_IT_ORE) != RESET)) {
289 __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF);
292 /* UART in mode Transmitter ------------------------------------------------*/
293 if (__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) {
294 /* Check that a Tx process is ongoing */
295 if (huart->gState != HAL_UART_STATE_BUSY_TX) {
296 if (s->port.txBufferTail == s->port.txBufferHead) {
297 huart->TxXferCount = 0;
298 /* Disable the UART Transmit Data Register Empty Interrupt */
299 CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
300 } else {
301 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) {
302 huart->Instance->TDR = (((uint16_t) s->port.txBuffer[s->port.txBufferTail]) & (uint16_t) 0x01FFU);
303 } else {
304 huart->Instance->TDR = (uint8_t)(s->port.txBuffer[s->port.txBufferTail]);
306 s->port.txBufferTail = (s->port.txBufferTail + 1) % s->port.txBufferSize;
311 /* UART in mode Transmitter (transmission end) -----------------------------*/
312 if ((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET)) {
313 HAL_UART_IRQHandler(huart);
317 uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_t mode, portOptions_t options)
319 uartPort_t *s;
321 uartDevice_t *uart = uartHardwareMap[device];
322 if (!uart) return NULL;
324 s = &(uart->port);
325 s->port.vTable = uartVTable;
327 s->port.baudRate = baudRate;
329 s->port.rxBuffer = uart->rxBuffer;
330 s->port.txBuffer = uart->txBuffer;
331 s->port.rxBufferSize = sizeof(uart->rxBuffer);
332 s->port.txBufferSize = sizeof(uart->txBuffer);
334 s->USARTx = uart->dev;
336 s->Handle.Instance = uart->dev;
338 if (uart->rcc) {
339 RCC_ClockCmd(uart->rcc, ENABLE);
342 IO_t tx = IOGetByTag(uart->tx);
343 IO_t rx = IOGetByTag(uart->rx);
345 if (options & SERIAL_BIDIR) {
346 IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TXRX, RESOURCE_INDEX(device));
347 IOConfigGPIOAF(tx, IOCFG_AF_PP, uart->af_tx);
349 else {
350 if (mode & MODE_TX) {
351 IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TX, RESOURCE_INDEX(device));
352 IOConfigGPIOAF(tx, IOCFG_AF_PP, uart->af_tx);
355 if (mode & MODE_RX) {
356 IOInit(rx, OWNER_SERIAL, RESOURCE_UART_RX, RESOURCE_INDEX(device));
357 IOConfigGPIOAF(rx, IOCFG_AF_PP, uart->af_rx);
361 HAL_NVIC_SetPriority(uart->irq, NVIC_PRIO_SERIALUART, 0);
362 HAL_NVIC_EnableIRQ(uart->irq);
364 return s;
367 #ifdef USE_UART1
368 uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t options)
370 return serialUART(UARTDEV_1, baudRate, mode, options);
373 // USART1 Rx/Tx IRQ Handler
374 void USART1_IRQHandler(void)
376 uartPort_t *s = &(uartHardwareMap[UARTDEV_1]->port);
377 uartIrqHandler(s);
379 #endif
381 #ifdef USE_UART2
382 uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t options)
384 return serialUART(UARTDEV_2, baudRate, mode, options);
387 // USART2 Rx/Tx IRQ Handler
388 void USART2_IRQHandler(void)
390 uartPort_t *s = &(uartHardwareMap[UARTDEV_2]->port);
391 uartIrqHandler(s);
393 #endif
395 #ifdef USE_UART3
396 uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t options)
398 return serialUART(UARTDEV_3, baudRate, mode, options);
401 // USART3 Rx/Tx IRQ Handler
402 void USART3_IRQHandler(void)
404 uartPort_t *s = &(uartHardwareMap[UARTDEV_3]->port);
405 uartIrqHandler(s);
407 #endif
409 #ifdef USE_UART4
410 uartPort_t *serialUART4(uint32_t baudRate, portMode_t mode, portOptions_t options)
412 return serialUART(UARTDEV_4, baudRate, mode, options);
415 // UART4 Rx/Tx IRQ Handler
416 void UART4_IRQHandler(void)
418 uartPort_t *s = &(uartHardwareMap[UARTDEV_4]->port);
419 uartIrqHandler(s);
421 #endif
423 #ifdef USE_UART5
424 uartPort_t *serialUART5(uint32_t baudRate, portMode_t mode, portOptions_t options)
426 return serialUART(UARTDEV_5, baudRate, mode, options);
429 // UART5 Rx/Tx IRQ Handler
430 void UART5_IRQHandler(void)
432 uartPort_t *s = &(uartHardwareMap[UARTDEV_5]->port);
433 uartIrqHandler(s);
435 #endif
437 #ifdef USE_UART6
438 uartPort_t *serialUART6(uint32_t baudRate, portMode_t mode, portOptions_t options)
440 return serialUART(UARTDEV_6, baudRate, mode, options);
443 // USART6 Rx/Tx IRQ Handler
444 void USART6_IRQHandler(void)
446 uartPort_t *s = &(uartHardwareMap[UARTDEV_6]->port);
447 uartIrqHandler(s);
449 #endif
451 #ifdef USE_UART7
452 uartPort_t *serialUART7(uint32_t baudRate, portMode_t mode, portOptions_t options)
454 return serialUART(UARTDEV_7, baudRate, mode, options);
457 // UART7 Rx/Tx IRQ Handler
458 void UART7_IRQHandler(void)
460 uartPort_t *s = &(uartHardwareMap[UARTDEV_7]->port);
461 uartIrqHandler(s);
463 #endif
465 #ifdef USE_UART8
466 uartPort_t *serialUART8(uint32_t baudRate, portMode_t mode, portOptions_t options)
468 return serialUART(UARTDEV_8, baudRate, mode, options);
471 // UART8 Rx/Tx IRQ Handler
472 void UART8_IRQHandler(void)
474 uartPort_t *s = &(uartHardwareMap[UARTDEV_8]->port);
475 uartIrqHandler(s);
477 #endif