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/Hydra - Various cleanups for Cleanflight
21 * Bill Nesbitt - Code from AutoQuad
22 * Hamasaki/Timecop - Initial baseflight code
36 #include "serial_uart.h"
37 #include "serial_uart_impl.h"
40 static uartPort_t uartPort1
;
44 static uartPort_t uartPort2
;
48 static uartPort_t uartPort3
;
51 // Using RX DMA disables the use of receive callbacks
52 #define USE_USART1_RX_DMA
54 #if defined(CC3D) // FIXME move board specific code to target.h files.
55 #undef USE_USART1_RX_DMA
58 void usartIrqCallback(uartPort_t
*s
)
60 uint16_t SR
= s
->USARTx
->SR
;
62 if (SR
& USART_FLAG_RXNE
&& !s
->rxDMAChannel
) {
63 // If we registered a callback, pass crap there
64 if (s
->port
.callback
) {
65 s
->port
.callback(s
->USARTx
->DR
);
67 s
->port
.rxBuffer
[s
->port
.rxBufferHead
++] = s
->USARTx
->DR
;
68 if (s
->port
.rxBufferHead
>= s
->port
.rxBufferSize
) {
69 s
->port
.rxBufferHead
= 0;
73 if (SR
& USART_FLAG_TXE
) {
74 if (s
->port
.txBufferTail
!= s
->port
.txBufferHead
) {
75 s
->USARTx
->DR
= s
->port
.txBuffer
[s
->port
.txBufferTail
++];
76 if (s
->port
.txBufferTail
>= s
->port
.txBufferSize
) {
77 s
->port
.txBufferTail
= 0;
80 USART_ITConfig(s
->USARTx
, USART_IT_TXE
, DISABLE
);
86 // USART1 - Telemetry (RX/TX by DMA)
87 uartPort_t
*serialUSART1(uint32_t baudRate
, portMode_t mode
)
90 static volatile uint8_t rx1Buffer
[UART1_RX_BUFFER_SIZE
];
91 static volatile uint8_t tx1Buffer
[UART1_TX_BUFFER_SIZE
];
93 NVIC_InitTypeDef NVIC_InitStructure
;
96 s
->port
.vTable
= uartVTable
;
98 s
->port
.baudRate
= baudRate
;
100 s
->port
.rxBuffer
= rx1Buffer
;
101 s
->port
.txBuffer
= tx1Buffer
;
102 s
->port
.rxBufferSize
= UART1_RX_BUFFER_SIZE
;
103 s
->port
.txBufferSize
= UART1_TX_BUFFER_SIZE
;
108 #ifdef USE_USART1_RX_DMA
109 s
->rxDMAChannel
= DMA1_Channel5
;
110 s
->rxDMAPeripheralBaseAddr
= (uint32_t)&s
->USARTx
->DR
;
112 s
->txDMAChannel
= DMA1_Channel4
;
113 s
->txDMAPeripheralBaseAddr
= (uint32_t)&s
->USARTx
->DR
;
115 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1
, ENABLE
);
116 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1
, ENABLE
);
120 gpio
.speed
= Speed_2MHz
;
122 gpio
.mode
= Mode_AF_PP
;
124 gpioInit(GPIOA
, &gpio
);
125 gpio
.mode
= Mode_AF_OD
;
126 if (mode
& MODE_BIDIR
)
127 gpioInit(GPIOA
, &gpio
);
129 gpio
.mode
= Mode_IPU
;
131 gpioInit(GPIOA
, &gpio
);
134 NVIC_InitStructure
.NVIC_IRQChannel
= DMA1_Channel4_IRQn
;
135 NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_TXDMA
);
136 NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_TXDMA
);
137 NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
138 NVIC_Init(&NVIC_InitStructure
);
140 #ifndef USE_USART1_RX_DMA
142 NVIC_InitStructure
.NVIC_IRQChannel
= USART1_IRQn
;
143 NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1
);
144 NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1
);
145 NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
146 NVIC_Init(&NVIC_InitStructure
);
153 // USART1 Tx DMA Handler
154 void DMA1_Channel4_IRQHandler(void)
156 uartPort_t
*s
= &uartPort1
;
157 DMA_ClearITPendingBit(DMA1_IT_TC4
);
158 DMA_Cmd(s
->txDMAChannel
, DISABLE
);
160 if (s
->port
.txBufferHead
!= s
->port
.txBufferTail
)
163 s
->txDMAEmpty
= true;
166 // USART1 Rx/Tx IRQ Handler
167 void USART1_IRQHandler(void)
169 uartPort_t
*s
= &uartPort1
;
176 // USART2 - GPS or Spektrum or ?? (RX + TX by IRQ)
177 uartPort_t
*serialUSART2(uint32_t baudRate
, portMode_t mode
)
180 static volatile uint8_t rx2Buffer
[UART2_RX_BUFFER_SIZE
];
181 static volatile uint8_t tx2Buffer
[UART2_TX_BUFFER_SIZE
];
183 NVIC_InitTypeDef NVIC_InitStructure
;
186 s
->port
.vTable
= uartVTable
;
188 s
->port
.baudRate
= baudRate
;
190 s
->port
.rxBufferSize
= UART2_RX_BUFFER_SIZE
;
191 s
->port
.txBufferSize
= UART2_TX_BUFFER_SIZE
;
192 s
->port
.rxBuffer
= rx2Buffer
;
193 s
->port
.txBuffer
= tx2Buffer
;
197 s
->txDMAPeripheralBaseAddr
= (uint32_t)&s
->USARTx
->DR
;
198 s
->rxDMAPeripheralBaseAddr
= (uint32_t)&s
->USARTx
->DR
;
200 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2
, ENABLE
);
201 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1
, ENABLE
);
205 gpio
.speed
= Speed_2MHz
;
207 gpio
.mode
= Mode_AF_PP
;
209 gpioInit(GPIOA
, &gpio
);
210 gpio
.mode
= Mode_AF_OD
;
211 if (mode
& MODE_BIDIR
)
212 gpioInit(GPIOA
, &gpio
);
214 gpio
.mode
= Mode_IPU
;
216 gpioInit(GPIOA
, &gpio
);
219 NVIC_InitStructure
.NVIC_IRQChannel
= USART2_IRQn
;
220 NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2
);
221 NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2
);
222 NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
223 NVIC_Init(&NVIC_InitStructure
);
229 // USART2 Rx/Tx IRQ Handler
230 void USART2_IRQHandler(void)
232 uartPort_t
*s
= &uartPort2
;
240 uartPort_t
*serialUSART3(uint32_t baudRate
, portMode_t mode
)
243 static volatile uint8_t rx3Buffer
[UART3_RX_BUFFER_SIZE
];
244 static volatile uint8_t tx3Buffer
[UART3_TX_BUFFER_SIZE
];
246 NVIC_InitTypeDef NVIC_InitStructure
;
249 s
->port
.vTable
= uartVTable
;
251 s
->port
.baudRate
= baudRate
;
253 s
->port
.rxBuffer
= rx3Buffer
;
254 s
->port
.txBuffer
= tx3Buffer
;
255 s
->port
.rxBufferSize
= UART3_RX_BUFFER_SIZE
;
256 s
->port
.txBufferSize
= UART3_TX_BUFFER_SIZE
;
260 s
->txDMAPeripheralBaseAddr
= (uint32_t)&s
->USARTx
->DR
;
261 s
->rxDMAPeripheralBaseAddr
= (uint32_t)&s
->USARTx
->DR
;
263 #ifdef USART3_APB1_PERIPHERALS
264 RCC_APB1PeriphClockCmd(USART3_APB1_PERIPHERALS
, ENABLE
);
266 #ifdef USART3_APB2_PERIPHERALS
267 RCC_APB2PeriphClockCmd(USART3_APB2_PERIPHERALS
, ENABLE
);
270 gpio
.speed
= Speed_2MHz
;
271 gpio
.pin
= USART3_TX_PIN
;
272 gpio
.mode
= Mode_AF_PP
;
274 gpioInit(USART3_GPIO
, &gpio
);
275 gpio
.mode
= Mode_AF_OD
;
276 if (mode
& MODE_BIDIR
)
277 gpioInit(USART3_GPIO
, &gpio
);
278 gpio
.pin
= USART3_RX_PIN
;
279 gpio
.mode
= Mode_IPU
;
281 gpioInit(USART3_GPIO
, &gpio
);
284 NVIC_InitStructure
.NVIC_IRQChannel
= USART3_IRQn
;
285 NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART3
);
286 NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART3
);
287 NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
288 NVIC_Init(&NVIC_InitStructure
);
293 // USART2 Rx/Tx IRQ Handler
294 void USART3_IRQHandler(void)
296 uartPort_t
*s
= &uartPort3
;