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/>.
20 * Dominic Clifton - Serial port abstraction, Separation of common STM32 code for cleanflight, various cleanups.
21 * Hamasaki/Timecop - Initial baseflight code
28 #include "build/build_config.h"
30 #include "common/utils.h"
32 #include "drivers/uart_inverter.h"
35 #include "serial_uart.h"
36 #include "serial_uart_impl.h"
38 static void usartConfigurePinInversion(uartPort_t
*uartPort
) {
39 #if !defined(USE_UART_INVERTER) && !defined(STM32F7)
42 bool inverted
= uartPort
->port
.options
& SERIAL_INVERTED
;
44 #ifdef USE_UART_INVERTER
45 uartInverterLine_e invertedLines
= UART_INVERTER_LINE_NONE
;
46 if (uartPort
->port
.mode
& MODE_RX
) {
47 invertedLines
|= UART_INVERTER_LINE_RX
;
49 if (uartPort
->port
.mode
& MODE_TX
) {
50 invertedLines
|= UART_INVERTER_LINE_TX
;
52 uartInverterSet(uartPort
->USARTx
, invertedLines
, inverted
);
58 static void uartReconfigure(uartPort_t
*uartPort
)
60 USART_InitTypeDef USART_InitStructure
;
61 USART_Cmd(uartPort
->USARTx
, DISABLE
);
63 USART_InitStructure
.USART_BaudRate
= uartPort
->port
.baudRate
;
65 // according to the stm32 documentation wordlen has to be 9 for parity bits
66 // this does not seem to matter for rx but will give bad data on tx!
67 if (uartPort
->port
.options
& SERIAL_PARITY_EVEN
) {
68 USART_InitStructure
.USART_WordLength
= USART_WordLength_9b
;
70 USART_InitStructure
.USART_WordLength
= USART_WordLength_8b
;
73 USART_InitStructure
.USART_StopBits
= (uartPort
->port
.options
& SERIAL_STOPBITS_2
) ? USART_StopBits_2
: USART_StopBits_1
;
74 USART_InitStructure
.USART_Parity
= (uartPort
->port
.options
& SERIAL_PARITY_EVEN
) ? USART_Parity_Even
: USART_Parity_No
;
76 USART_InitStructure
.USART_HardwareFlowControl
= USART_HardwareFlowControl_None
;
77 USART_InitStructure
.USART_Mode
= 0;
78 if (uartPort
->port
.mode
& MODE_RX
)
79 USART_InitStructure
.USART_Mode
|= USART_Mode_Rx
;
80 if (uartPort
->port
.mode
& MODE_TX
)
81 USART_InitStructure
.USART_Mode
|= USART_Mode_Tx
;
83 USART_Init(uartPort
->USARTx
, &USART_InitStructure
);
85 usartConfigurePinInversion(uartPort
);
87 if (uartPort
->port
.options
& SERIAL_BIDIR
)
88 USART_HalfDuplexCmd(uartPort
->USARTx
, ENABLE
);
90 USART_HalfDuplexCmd(uartPort
->USARTx
, DISABLE
);
92 USART_Cmd(uartPort
->USARTx
, ENABLE
);
95 serialPort_t
*uartOpen(USART_TypeDef
*USARTx
, serialReceiveCallbackPtr rxCallback
, void *rxCallbackData
, uint32_t baudRate
, portMode_t mode
, portOptions_t options
)
101 } else if (USARTx
== USART1
) {
102 s
= serialUART1(baudRate
, mode
, options
);
106 } else if (USARTx
== USART2
) {
107 s
= serialUART2(baudRate
, mode
, options
);
110 } else if (USARTx
== USART3
) {
111 s
= serialUART3(baudRate
, mode
, options
);
114 } else if (USARTx
== UART4
) {
115 s
= serialUART4(baudRate
, mode
, options
);
118 } else if (USARTx
== UART5
) {
119 s
= serialUART5(baudRate
, mode
, options
);
122 } else if (USARTx
== USART6
) {
123 s
= serialUART6(baudRate
, mode
, options
);
126 } else if (USARTx
== UART7
) {
127 s
= serialUART7(baudRate
, mode
, options
);
130 } else if (USARTx
== UART8
) {
131 s
= serialUART8(baudRate
, mode
, options
);
135 return (serialPort_t
*)s
;
138 // common serial initialisation code should move to serialPort::init()
139 s
->port
.rxBufferHead
= s
->port
.rxBufferTail
= 0;
140 s
->port
.txBufferHead
= s
->port
.txBufferTail
= 0;
141 // callback works for IRQ-based RX ONLY
142 s
->port
.rxCallback
= rxCallback
;
143 s
->port
.rxCallbackData
= rxCallbackData
;
145 s
->port
.baudRate
= baudRate
;
146 s
->port
.options
= options
;
150 if (mode
& MODE_RX
) {
151 USART_ClearITPendingBit(s
->USARTx
, USART_IT_RXNE
);
152 USART_ITConfig(s
->USARTx
, USART_IT_RXNE
, ENABLE
);
155 if (mode
& MODE_TX
) {
156 USART_ITConfig(s
->USARTx
, USART_IT_TXE
, ENABLE
);
159 USART_Cmd(s
->USARTx
, ENABLE
);
161 return (serialPort_t
*)s
;
164 void uartSetBaudRate(serialPort_t
*instance
, uint32_t baudRate
)
166 uartPort_t
*uartPort
= (uartPort_t
*)instance
;
167 uartPort
->port
.baudRate
= baudRate
;
168 uartReconfigure(uartPort
);
171 void uartSetMode(serialPort_t
*instance
, portMode_t mode
)
173 uartPort_t
*uartPort
= (uartPort_t
*)instance
;
174 uartPort
->port
.mode
= mode
;
175 uartReconfigure(uartPort
);
178 uint32_t uartTotalRxBytesWaiting(const serialPort_t
*instance
)
180 const uartPort_t
*s
= (const uartPort_t
*)instance
;
182 if (s
->port
.rxBufferHead
>= s
->port
.rxBufferTail
) {
183 return s
->port
.rxBufferHead
- s
->port
.rxBufferTail
;
185 return s
->port
.rxBufferSize
+ s
->port
.rxBufferHead
- s
->port
.rxBufferTail
;
189 uint32_t uartTotalTxBytesFree(const serialPort_t
*instance
)
191 const uartPort_t
*s
= (const uartPort_t
*)instance
;
195 if (s
->port
.txBufferHead
>= s
->port
.txBufferTail
) {
196 bytesUsed
= s
->port
.txBufferHead
- s
->port
.txBufferTail
;
198 bytesUsed
= s
->port
.txBufferSize
+ s
->port
.txBufferHead
- s
->port
.txBufferTail
;
201 return (s
->port
.txBufferSize
- 1) - bytesUsed
;
204 bool isUartTransmitBufferEmpty(const serialPort_t
*instance
)
206 const uartPort_t
*s
= (const uartPort_t
*)instance
;
207 return s
->port
.txBufferTail
== s
->port
.txBufferHead
;
210 uint8_t uartRead(serialPort_t
*instance
)
213 uartPort_t
*s
= (uartPort_t
*)instance
;
215 ch
= s
->port
.rxBuffer
[s
->port
.rxBufferTail
];
216 if (s
->port
.rxBufferTail
+ 1 >= s
->port
.rxBufferSize
) {
217 s
->port
.rxBufferTail
= 0;
219 s
->port
.rxBufferTail
++;
225 void uartWrite(serialPort_t
*instance
, uint8_t ch
)
227 uartPort_t
*s
= (uartPort_t
*)instance
;
228 s
->port
.txBuffer
[s
->port
.txBufferHead
] = ch
;
229 if (s
->port
.txBufferHead
+ 1 >= s
->port
.txBufferSize
) {
230 s
->port
.txBufferHead
= 0;
232 s
->port
.txBufferHead
++;
235 USART_ITConfig(s
->USARTx
, USART_IT_TXE
, ENABLE
);
238 bool isUartIdle(serialPort_t
*instance
)
240 uartPort_t
*s
= (uartPort_t
*)instance
;
241 if(USART_GetFlagStatus(s
->USARTx
, USART_FLAG_IDLE
)) {
242 uartClearIdleFlag(s
);
249 const struct serialPortVTable uartVTable
[] = {
251 .serialWrite
= uartWrite
,
252 .serialTotalRxWaiting
= uartTotalRxBytesWaiting
,
253 .serialTotalTxFree
= uartTotalTxBytesFree
,
254 .serialRead
= uartRead
,
255 .serialSetBaudRate
= uartSetBaudRate
,
256 .isSerialTransmitBufferEmpty
= isUartTransmitBufferEmpty
,
257 .setMode
= uartSetMode
,
262 .isIdle
= isUartIdle
,