Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / serial_uart_hal.c
blobcce384228485f977cc46f429706b265902f7c057
1 /*
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/>.
19 * Authors:
20 * Dominic Clifton - Serial port abstraction, Separation of common STM32 code for cleanflight, various cleanups.
21 * Hamasaki/Timecop - Initial baseflight code
23 #include <stdbool.h>
24 #include <stdint.h>
25 #include <stdlib.h>
27 #include "platform.h"
29 #include "build/build_config.h"
31 #include "common/utils.h"
32 #include "drivers/io.h"
33 #include "drivers/nvic.h"
35 #include "serial.h"
36 #include "serial_uart.h"
37 #include "serial_uart_impl.h"
39 static void usartConfigurePinInversion(uartPort_t *uartPort) {
40 bool inverted = uartPort->port.options & SERIAL_INVERTED;
42 if (inverted)
44 if (uartPort->port.mode & MODE_RX)
46 uartPort->Handle.AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_RXINVERT_INIT;
47 uartPort->Handle.AdvancedInit.RxPinLevelInvert = UART_ADVFEATURE_RXINV_ENABLE;
49 if (uartPort->port.mode & MODE_TX)
51 uartPort->Handle.AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_TXINVERT_INIT;
52 uartPort->Handle.AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE;
57 static void uartReconfigure(uartPort_t *uartPort)
59 /*RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
60 RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_USART3|
61 RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_UART5|RCC_PERIPHCLK_USART6|RCC_PERIPHCLK_UART7|RCC_PERIPHCLK_UART8;
62 RCC_PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
63 RCC_PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
64 RCC_PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;
65 RCC_PeriphClkInit.Uart4ClockSelection = RCC_UART4CLKSOURCE_SYSCLK;
66 RCC_PeriphClkInit.Uart5ClockSelection = RCC_UART5CLKSOURCE_SYSCLK;
67 RCC_PeriphClkInit.Usart6ClockSelection = RCC_USART6CLKSOURCE_SYSCLK;
68 RCC_PeriphClkInit.Uart7ClockSelection = RCC_UART7CLKSOURCE_SYSCLK;
69 RCC_PeriphClkInit.Uart8ClockSelection = RCC_UART8CLKSOURCE_SYSCLK;
70 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);*/
72 HAL_UART_DeInit(&uartPort->Handle);
73 uartPort->Handle.Init.BaudRate = uartPort->port.baudRate;
74 uartPort->Handle.Init.WordLength = (uartPort->port.options & SERIAL_PARITY_EVEN) ? UART_WORDLENGTH_9B : UART_WORDLENGTH_8B;
75 uartPort->Handle.Init.StopBits = (uartPort->port.options & SERIAL_STOPBITS_2) ? USART_STOPBITS_2 : USART_STOPBITS_1;
76 uartPort->Handle.Init.Parity = (uartPort->port.options & SERIAL_PARITY_EVEN) ? USART_PARITY_EVEN : USART_PARITY_NONE;
77 uartPort->Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
78 uartPort->Handle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
79 uartPort->Handle.Init.Mode = 0;
81 if (uartPort->port.mode & MODE_RX)
82 uartPort->Handle.Init.Mode |= UART_MODE_RX;
83 if (uartPort->port.mode & MODE_TX)
84 uartPort->Handle.Init.Mode |= UART_MODE_TX;
87 usartConfigurePinInversion(uartPort);
89 if (uartPort->port.options & SERIAL_BIDIR)
91 HAL_HalfDuplex_Init(&uartPort->Handle);
93 else
95 HAL_UART_Init(&uartPort->Handle);
98 if (uartPort->port.mode & MODE_RX) {
99 /* Enable the UART Parity Error Interrupt */
100 SET_BIT(uartPort->USARTx->CR1, USART_CR1_PEIE);
102 /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
103 SET_BIT(uartPort->USARTx->CR3, USART_CR3_EIE);
105 /* Enable the UART Data Register not empty Interrupt */
106 SET_BIT(uartPort->USARTx->CR1, USART_CR1_RXNEIE);
109 // Transmit IRQ
110 if (uartPort->port.mode & MODE_TX) {
111 /* Enable the UART Transmit Data Register Empty Interrupt */
112 SET_BIT(uartPort->USARTx->CR1, USART_CR1_TXEIE);
114 return;
117 serialPort_t *uartOpen(USART_TypeDef *USARTx, serialReceiveCallbackPtr callback, void *rxCallbackData, uint32_t baudRate, portMode_t mode, portOptions_t options)
119 uartPort_t *s = NULL;
121 if (false) {
122 #ifdef USE_UART1
123 } else if (USARTx == USART1) {
124 s = serialUART1(baudRate, mode, options);
125 #endif
126 #ifdef USE_UART2
127 } else if (USARTx == USART2) {
128 s = serialUART2(baudRate, mode, options);
129 #endif
130 #ifdef USE_UART3
131 } else if (USARTx == USART3) {
132 s = serialUART3(baudRate, mode, options);
133 #endif
134 #ifdef USE_UART4
135 } else if (USARTx == UART4) {
136 s = serialUART4(baudRate, mode, options);
137 #endif
138 #ifdef USE_UART5
139 } else if (USARTx == UART5) {
140 s = serialUART5(baudRate, mode, options);
141 #endif
142 #ifdef USE_UART6
143 } else if (USARTx == USART6) {
144 s = serialUART6(baudRate, mode, options);
145 #endif
146 #ifdef USE_UART7
147 } else if (USARTx == UART7) {
148 s = serialUART7(baudRate, mode, options);
149 #endif
150 #ifdef USE_UART8
151 } else if (USARTx == UART8) {
152 s = serialUART8(baudRate, mode, options);
153 #endif
154 } else {
155 return (serialPort_t *)s;
159 // common serial initialisation code should move to serialPort::init()
160 s->port.rxBufferHead = s->port.rxBufferTail = 0;
161 s->port.txBufferHead = s->port.txBufferTail = 0;
162 // callback works for IRQ-based RX ONLY
163 s->port.rxCallback = callback;
164 s->port.rxCallbackData = rxCallbackData;
165 s->port.mode = mode;
166 s->port.baudRate = baudRate;
167 s->port.options = options;
169 uartReconfigure(s);
171 return (serialPort_t *)s;
174 void uartSetBaudRate(serialPort_t *instance, uint32_t baudRate)
176 uartPort_t *uartPort = (uartPort_t *)instance;
177 uartPort->port.baudRate = baudRate;
178 uartReconfigure(uartPort);
181 void uartSetMode(serialPort_t *instance, portMode_t mode)
183 uartPort_t *uartPort = (uartPort_t *)instance;
184 uartPort->port.mode = mode;
185 uartReconfigure(uartPort);
188 void uartSetOptions(serialPort_t *instance, portOptions_t options)
190 uartPort_t *uartPort = (uartPort_t *)instance;
191 uartPort->port.options = options;
192 uartReconfigure(uartPort);
195 uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance)
197 uartPort_t *s = (uartPort_t*)instance;
199 if (s->port.rxBufferHead >= s->port.rxBufferTail) {
200 return s->port.rxBufferHead - s->port.rxBufferTail;
201 } else {
202 return s->port.rxBufferSize + s->port.rxBufferHead - s->port.rxBufferTail;
206 uint32_t uartTotalTxBytesFree(const serialPort_t *instance)
208 uartPort_t *s = (uartPort_t*)instance;
210 uint32_t bytesUsed;
212 if (s->port.txBufferHead >= s->port.txBufferTail) {
213 bytesUsed = s->port.txBufferHead - s->port.txBufferTail;
214 } else {
215 bytesUsed = s->port.txBufferSize + s->port.txBufferHead - s->port.txBufferTail;
218 return (s->port.txBufferSize - 1) - bytesUsed;
221 bool isUartTransmitBufferEmpty(const serialPort_t *instance)
223 uartPort_t *s = (uartPort_t *)instance;
224 return s->port.txBufferTail == s->port.txBufferHead;
227 uint8_t uartRead(serialPort_t *instance)
229 uint8_t ch;
230 uartPort_t *s = (uartPort_t *)instance;
233 ch = s->port.rxBuffer[s->port.rxBufferTail];
234 if (s->port.rxBufferTail + 1 >= s->port.rxBufferSize) {
235 s->port.rxBufferTail = 0;
236 } else {
237 s->port.rxBufferTail++;
240 return ch;
243 void uartWrite(serialPort_t *instance, uint8_t ch)
245 uartPort_t *s = (uartPort_t *)instance;
246 s->port.txBuffer[s->port.txBufferHead] = ch;
247 if (s->port.txBufferHead + 1 >= s->port.txBufferSize) {
248 s->port.txBufferHead = 0;
249 } else {
250 s->port.txBufferHead++;
253 __HAL_UART_ENABLE_IT(&s->Handle, UART_IT_TXE);
256 bool isUartIdle(serialPort_t *instance)
258 uartPort_t *s = (uartPort_t *)instance;
259 if(__HAL_UART_GET_FLAG(&s->Handle, UART_FLAG_IDLE)) {
260 __HAL_UART_CLEAR_IDLEFLAG(&s->Handle);
261 return true;
262 } else {
263 return false;
267 const struct serialPortVTable uartVTable[] = {
269 .serialWrite = uartWrite,
270 .serialTotalRxWaiting = uartTotalRxBytesWaiting,
271 .serialTotalTxFree = uartTotalTxBytesFree,
272 .serialRead = uartRead,
273 .serialSetBaudRate = uartSetBaudRate,
274 .isSerialTransmitBufferEmpty = isUartTransmitBufferEmpty,
275 .setMode = uartSetMode,
276 .setOptions = uartSetOptions,
277 .isConnected = NULL,
278 .writeBuf = NULL,
279 .beginWrite = NULL,
280 .endWrite = NULL,
281 .isIdle = isUartIdle,