Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
uart_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Antoine Drouin <poinix@gmail.com>
3  * Copyright (C) 2013 Felix Ruess <felix.ruess@gmail.com>
4  *
5  * This file is part of paparazzi.
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
30 #include "mcu_periph/uart.h"
31 #include "mcu_periph/gpio.h"
32 
33 #include <libopencm3/stm32/gpio.h>
34 #include <libopencm3/stm32/rcc.h>
35 #include <libopencm3/stm32/usart.h>
36 #include <libopencm3/cm3/nvic.h>
37 
38 #include "std.h"
39 
40 #include BOARD_CONFIG
41 
43 
44  /* Configure USART */
45  usart_set_baudrate((u32)p->reg_addr, baud);
46  usart_set_databits((u32)p->reg_addr, 8);
47  usart_set_stopbits((u32)p->reg_addr, USART_STOPBITS_1);
48  usart_set_parity((u32)p->reg_addr, USART_PARITY_NONE);
49 
50  /* Disable Idle Line interrupt */
51  USART_CR1((u32)p->reg_addr) &= ~USART_CR1_IDLEIE;
52 
53  /* Disable LIN break detection interrupt */
54  USART_CR2((u32)p->reg_addr) &= ~USART_CR2_LBDIE;
55 
56  /* Enable USART1 Receive interrupts */
57  USART_CR1((u32)p->reg_addr) |= USART_CR1_RXNEIE;
58 
59  /* Enable the USART */
60  usart_enable((u32)p->reg_addr);
61 
62 }
63 
64 void uart_periph_set_mode(struct uart_periph* p, bool_t tx_enabled, bool_t rx_enabled, bool_t hw_flow_control) {
65  u32 mode = 0;
66  if (tx_enabled)
67  mode |= USART_MODE_TX;
68  if (rx_enabled)
69  mode |= USART_MODE_RX;
70 
71  /* set mode to Tx, Rx or TxRx */
72  usart_set_mode((u32)p->reg_addr, mode);
73 
74  if (hw_flow_control) {
75  usart_set_flow_control((u32)p->reg_addr, USART_FLOWCONTROL_RTS_CTS);
76  }
77  else {
78  usart_set_flow_control((u32)p->reg_addr, USART_FLOWCONTROL_NONE);
79  }
80 }
81 
82 void uart_transmit(struct uart_periph* p, uint8_t data ) {
83 
84  uint16_t temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE;
85 
86  if (temp == p->tx_extract_idx)
87  return; // no room
88 
89  USART_CR1((u32)p->reg_addr) &= ~USART_CR1_TXEIE; // Disable TX interrupt
90 
91  // check if in process of sending data
92  if (p->tx_running) { // yes, add to queue
93  p->tx_buf[p->tx_insert_idx] = data;
94  p->tx_insert_idx = temp;
95  }
96  else { // no, set running flag and write to output register
97  p->tx_running = TRUE;
98  usart_send((u32)p->reg_addr, data);
99  }
100 
101  USART_CR1((u32)p->reg_addr) |= USART_CR1_TXEIE; // Enable TX interrupt
102 
103 }
104 
105 static inline void usart_isr(struct uart_periph* p) {
106 
107  if (((USART_CR1((u32)p->reg_addr) & USART_CR1_TXEIE) != 0) &&
108  ((USART_SR((u32)p->reg_addr) & USART_SR_TXE) != 0)) {
109  // check if more data to send
110  if (p->tx_insert_idx != p->tx_extract_idx) {
111  usart_send((u32)p->reg_addr,p->tx_buf[p->tx_extract_idx]);
112  p->tx_extract_idx++;
114  }
115  else {
116  p->tx_running = FALSE; // clear running flag
117  USART_CR1((u32)p->reg_addr) &= ~USART_CR1_TXEIE; // Disable TX interrupt
118  }
119  }
120 
121  if (((USART_CR1((u32)p->reg_addr) & USART_CR1_RXNEIE) != 0) &&
122  ((USART_SR((u32)p->reg_addr) & USART_SR_RXNE) != 0) &&
123  ((USART_SR((u32)p->reg_addr) & USART_SR_ORE) == 0) &&
124  ((USART_SR((u32)p->reg_addr) & USART_SR_NE) == 0) &&
125  ((USART_SR((u32)p->reg_addr) & USART_SR_FE) == 0)) {
126  uint16_t temp = (p->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE;;
127  p->rx_buf[p->rx_insert_idx] = usart_recv((u32)p->reg_addr);
128  // check for more room in queue
129  if (temp != p->rx_extract_idx)
130  p->rx_insert_idx = temp; // update insert index
131  }
132  else {
133  /* ORE, NE or FE error - read USART_DR reg and log the error */
134  if (((USART_CR1((u32)p->reg_addr) & USART_CR1_RXNEIE) != 0) &&
135  ((USART_SR((u32)p->reg_addr) & USART_SR_ORE) != 0)) {
136  usart_recv((u32)p->reg_addr);
137  p->ore++;
138  }
139  if (((USART_CR1((u32)p->reg_addr) & USART_CR1_RXNEIE) != 0) &&
140  ((USART_SR((u32)p->reg_addr) & USART_SR_NE) != 0)) {
141  usart_recv((u32)p->reg_addr);
142  p->ne_err++;
143  }
144  if (((USART_CR1((u32)p->reg_addr) & USART_CR1_RXNEIE) != 0) &&
145  ((USART_SR((u32)p->reg_addr) & USART_SR_FE) != 0)) {
146  usart_recv((u32)p->reg_addr);
147  p->fe_err++;
148  }
149  }
150 }
151 
152 static inline void usart_enable_irq(u8 IRQn) {
153  /* Note:
154  * In libstm32 times the priority of this interrupt was set to
155  * preemption priority 2 and sub priority 1
156  */
157  /* Enable USART interrupts */
158  nvic_enable_irq(IRQn);
159 }
160 
161 
162 #ifdef USE_UART1
163 
164 /* by default enable UART Tx and Rx */
165 #ifndef USE_UART1_TX
166 #define USE_UART1_TX TRUE
167 #endif
168 #ifndef USE_UART1_RX
169 #define USE_UART1_RX TRUE
170 #endif
171 
172 #ifndef UART1_HW_FLOW_CONTROL
173 #define UART1_HW_FLOW_CONTROL FALSE
174 #endif
175 
176 void uart1_init( void ) {
177 
178  uart_periph_init(&uart1);
179  uart1.reg_addr = (void *)USART1;
180 
181  /* init RCC and GPIOs */
182  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_USART1EN);
183 
184 #if USE_UART1_TX
186 #endif
187 #if USE_UART1_RX
189 #endif
190 
191  /* Enable USART interrupts in the interrupt controller */
192  usart_enable_irq(NVIC_USART1_IRQ);
193 
194 #if UART1_HW_FLOW_CONTROL
195 #warning "USING UART1 FLOW CONTROL. Make sure to pull down CTS if you are not connecting any flow-control-capable hardware."
196  /* setup CTS and RTS gpios */
197  gpio_setup_pin_af(UART1_GPIO_PORT_CTS, UART1_GPIO_CTS, UART1_GPIO_AF, FALSE);
198  gpio_setup_pin_af(UART1_GPIO_PORT_RTS, UART1_GPIO_RTS, UART1_GPIO_AF, TRUE);
199 #endif
200 
201  /* Configure USART1, enable hardware flow control*/
202  uart_periph_set_mode(&uart1, USE_UART1_TX, USE_UART1_RX, UART1_HW_FLOW_CONTROL);
203 
204  /* Set USART1 baudrate and enable interrupt */
205  uart_periph_set_baudrate(&uart1, UART1_BAUD);
206 }
207 
208 void usart1_isr(void) { usart_isr(&uart1); }
209 
210 #endif /* USE_UART1 */
211 
212 
213 #ifdef USE_UART2
214 
215 /* by default enable UART Tx and Rx */
216 #ifndef USE_UART2_TX
217 #define USE_UART2_TX TRUE
218 #endif
219 #ifndef USE_UART2_RX
220 #define USE_UART2_RX TRUE
221 #endif
222 
223 #ifndef UART2_HW_FLOW_CONTROL
224 #define UART2_HW_FLOW_CONTROL FALSE
225 #endif
226 
227 void uart2_init( void ) {
228 
229  uart_periph_init(&uart2);
230  uart2.reg_addr = (void *)USART2;
231 
232  /* init RCC and GPIOs */
233  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
234 
235 #if USE_UART2_TX
237 #endif
238 #if USE_UART2_RX
240 #endif
241 
242  /* Enable USART interrupts in the interrupt controller */
243  usart_enable_irq(NVIC_USART2_IRQ);
244 
245 #if UART2_HW_FLOW_CONTROL && defined(STM32F4)
246 #warning "USING UART2 FLOW CONTROL. Make sure to pull down CTS if you are not connecting any flow-control-capable hardware."
247  /* setup CTS and RTS pins */
248  gpio_setup_pin_af(UART2_GPIO_PORT_CTS, UART2_GPIO_CTS, UART2_GPIO_AF, FALSE);
249  gpio_setup_pin_af(UART2_GPIO_PORT_RTS, UART2_GPIO_RTS, UART2_GPIO_AF, TRUE);
250 #endif
251 
252  /* Configure USART Tx,Rx, and hardware flow control*/
253  uart_periph_set_mode(&uart2, USE_UART2_TX, USE_UART2_RX, UART2_HW_FLOW_CONTROL);
254 
255  /* Configure USART */
256  uart_periph_set_baudrate(&uart2, UART2_BAUD);
257 }
258 
259 void usart2_isr(void) { usart_isr(&uart2); }
260 
261 #endif /* USE_UART2 */
262 
263 
264 #ifdef USE_UART3
265 
266 /* by default enable UART Tx and Rx */
267 #ifndef USE_UART3_TX
268 #define USE_UART3_TX TRUE
269 #endif
270 #ifndef USE_UART3_RX
271 #define USE_UART3_RX TRUE
272 #endif
273 
274 #ifndef UART3_HW_FLOW_CONTROL
275 #define UART3_HW_FLOW_CONTROL FALSE
276 #endif
277 
278 void uart3_init( void ) {
279 
280  uart_periph_init(&uart3);
281  uart3.reg_addr = (void *)USART3;
282 
283  /* init RCC */
284  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART3EN);
285 
286 #if USE_UART3_TX
288 #endif
289 #if USE_UART3_RX
291 #endif
292 
293  /* Enable USART interrupts in the interrupt controller */
294  usart_enable_irq(NVIC_USART3_IRQ);
295 
296 #if UART3_HW_FLOW_CONTROL && defined(STM32F4)
297 #warning "USING UART3 FLOW CONTROL. Make sure to pull down CTS if you are not connecting any flow-control-capable hardware."
298  /* setup CTS and RTS pins */
299  gpio_setup_pin_af(UART3_GPIO_PORT_CTS, UART3_GPIO_CTS, UART3_GPIO_AF, FALSE);
300  gpio_setup_pin_af(UART3_GPIO_PORT_RTS, UART3_GPIO_RTS, UART3_GPIO_AF, TRUE);
301 #endif
302 
303  /* Configure USART Tx,Rx, and hardware flow control*/
304  uart_periph_set_mode(&uart3, USE_UART3_TX, USE_UART3_RX, UART3_HW_FLOW_CONTROL);
305 
306  /* Configure USART */
307  uart_periph_set_baudrate(&uart3, UART3_BAUD);
308 }
309 
310 void usart3_isr(void) { usart_isr(&uart3); }
311 
312 #endif /* USE_UART3 */
313 
314 
315 #if defined USE_UART4 && defined STM32F4
316 
317 /* by default enable UART Tx and Rx */
318 #ifndef USE_UART4_TX
319 #define USE_UART4_TX TRUE
320 #endif
321 #ifndef USE_UART4_RX
322 #define USE_UART4_RX TRUE
323 #endif
324 
325 void uart4_init( void ) {
326 
327  uart_periph_init(&uart4);
328  uart4.reg_addr = (void *)UART4;
329 
330  /* init RCC and GPIOs */
331  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_UART4EN);
332 
333 #if USE_UART4_TX
335 #endif
336 #if USE_UART4_RX
338 #endif
339 
340  /* Enable USART interrupts in the interrupt controller */
341  usart_enable_irq(NVIC_UART4_IRQ);
342 
343  /* Configure USART */
344  uart_periph_set_mode(&uart4, USE_UART4_TX, USE_UART4_RX, FALSE);
345  uart_periph_set_baudrate(&uart4, UART4_BAUD);
346 }
347 
348 void uart4_isr(void) { usart_isr(&uart4); }
349 
350 #endif /* USE_UART4 */
351 
352 
353 #ifdef USE_UART5
354 
355 /* by default enable UART Tx and Rx */
356 #ifndef USE_UART5_TX
357 #define USE_UART5_TX TRUE
358 #endif
359 #ifndef USE_UART5_RX
360 #define USE_UART5_RX TRUE
361 #endif
362 
363 void uart5_init( void ) {
364 
365  uart_periph_init(&uart5);
366  uart5.reg_addr = (void *)UART5;
367 
368  /* init RCC and GPIOs */
369  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_UART5EN);
370 
371 #if USE_UART5_TX
373 #endif
374 #if USE_UART5_RX
376 #endif
377 
378  /* Enable USART interrupts in the interrupt controller */
379  usart_enable_irq(NVIC_UART5_IRQ);
380 
381  /* Configure USART */
382  uart_periph_set_mode(&uart5, USE_UART5_TX, USE_UART5_RX, FALSE);
383  uart_periph_set_baudrate(&uart5, UART5_BAUD);
384 }
385 
386 void uart5_isr(void) { usart_isr(&uart5); }
387 
388 #endif /* USE_UART5 */
389 
390 
391 #if defined USE_UART6 && defined STM32F4
392 
393 /* by default enable UART Tx and Rx */
394 #ifndef USE_UART6_TX
395 #define USE_UART6_TX TRUE
396 #endif
397 #ifndef USE_UART6_RX
398 #define USE_UART6_RX TRUE
399 #endif
400 
401 #ifndef UART6_HW_FLOW_CONTROL
402 #define UART6_HW_FLOW_CONTROL FALSE
403 #endif
404 
405 void uart6_init( void ) {
406 
407  uart_periph_init(&uart6);
408  uart6.reg_addr = (void *)USART6;
409 
410  /* enable uart clock */
411  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_USART6EN);
412 
413  /* init RCC and GPIOs */
414 #if USE_UART6_TX
416 #endif
417 #if USE_UART6_RX
419 #endif
420 
421  /* Enable USART interrupts in the interrupt controller */
422  usart_enable_irq(NVIC_USART6_IRQ);
423 
424 #if UART6_HW_FLOW_CONTROL
425 #warning "USING UART6 FLOW CONTROL. Make sure to pull down CTS if you are not connecting any flow-control-capable hardware."
426  /* setup CTS and RTS pins */
427  gpio_setup_pin_af(UART6_GPIO_PORT_CTS, UART6_GPIO_CTS, UART6_GPIO_AF, FALSE);
428  gpio_setup_pin_af(UART6_GPIO_PORT_RTS, UART6_GPIO_RTS, UART6_GPIO_AF, TRUE);
429 #endif
430 
431  /* Configure USART Tx,Rx and hardware flow control*/
432  uart_periph_set_mode(&uart6, USE_UART6_TX, USE_UART6_RX, UART6_HW_FLOW_CONTROL);
433 
434  uart_periph_set_baudrate(&uart6, UART6_BAUD);
435 }
436 
437 void usart6_isr(void) { usart_isr(&uart6); }
438 
439 #endif /* USE_UART6 */
unsigned short uint16_t
Definition: types.h:16
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
volatile uint16_t ore
overrun error counter
Definition: uart.h:70
volatile uint16_t fe_err
framing error counter
Definition: uart.h:72
Some architecture independent helper functions for GPIOs.
uint8_t tx_running
Definition: uart.h:65
volatile uint16_t ne_err
noise error counter
Definition: uart.h:71
#define UART2_GPIO_PORT_TX
Definition: lisa_l_1.0.h:69
#define UART3_GPIO_AF
Definition: krooz_sd.h:90
void * reg_addr
UART Register.
Definition: uart.h:67
uint16_t tx_extract_idx
Definition: uart.h:64
#define UART4_GPIO_AF
Definition: apogee_0.99.h:51
#define UART3_GPIO_TX
Definition: krooz_sd.h:94
void uart_transmit(struct uart_periph *p, uint8_t data)
Definition: uart_arch.c:71
static void usart_isr(struct uart_periph *p)
Definition: uart_arch.c:105
#define UART5_GPIO_PORT_RX
Definition: krooz_sd.h:97
#define UART5_GPIO_RX
Definition: krooz_sd.h:98
#define FALSE
Definition: imu_chimu.h:141
#define UART4_GPIO_PORT_TX
Definition: apogee_0.99.h:54
UART peripheral.
Definition: uart.h:56
#define UART4_GPIO_TX
Definition: apogee_0.99.h:55
#define UART2_GPIO_TX
Definition: lisa_l_1.0.h:70
#define UART2_GPIO_AF
Definition: lisa_l_1.0.h:66
#define UART1_GPIO_TX
Definition: apogee_0.99.h:49
#define UART_TX_BUFFER_SIZE
Definition: uart.h:35
void uart_periph_init(struct uart_periph *p)
Definition: uart.c:53
unsigned long uint32_t
Definition: types.h:18
#define UART1_GPIO_PORT_RX
Definition: apogee_0.99.h:46
#define UART6_GPIO_AF
Definition: apogee_0.99.h:57
#define UART1_GPIO_RX
Definition: apogee_0.99.h:47
void uart_periph_set_mode(struct uart_periph *p, bool_t tx_enabled, bool_t rx_enabled, bool_t hw_flow_control)
Definition: uart_arch.c:64
#define UART2_GPIO_RX
Definition: lisa_l_1.0.h:68
uint16_t rx_insert_idx
Definition: uart.h:59
#define UART4_GPIO_RX
Definition: apogee_0.99.h:53
#define UART4_GPIO_PORT_RX
Definition: apogee_0.99.h:52
#define UART3_GPIO_PORT_RX
Definition: krooz_sd.h:91
#define TRUE
Definition: imu_chimu.h:144
void gpio_setup_pin_af(uint32_t port, uint16_t pin, uint8_t af, bool_t is_output)
Setup a gpio for input or output with alternate function.
uint8_t tx_buf[UART_TX_BUFFER_SIZE]
Transmit buffer.
Definition: uart.h:62
static void usart_enable_irq(u8 IRQn)
Definition: uart_arch.c:152
#define UART6_GPIO_TX
Definition: apogee_0.99.h:61
#define UART3_GPIO_PORT_TX
Definition: krooz_sd.h:93
#define UART6_GPIO_RX
Definition: apogee_0.99.h:59
#define UART5_GPIO_PORT_TX
Definition: krooz_sd.h:99
unsigned char uint8_t
Definition: types.h:14
uint16_t tx_insert_idx
Definition: uart.h:63
#define UART5_GPIO_TX
Definition: krooz_sd.h:100
#define UART6_GPIO_PORT_RX
Definition: apogee_0.99.h:58
uint8_t rx_buf[UART_RX_BUFFER_SIZE]
Receive buffer.
Definition: uart.h:58
#define UART1_GPIO_PORT_TX
Definition: apogee_0.99.h:48
static float p[2][2]
uint16_t rx_extract_idx
Definition: uart.h:60
#define UART1_GPIO_AF
Definition: apogee_0.99.h:45
#define UART5_GPIO_AF
Definition: krooz_sd.h:96
#define UART6_GPIO_PORT_TX
Definition: apogee_0.99.h:60
#define UART_RX_BUFFER_SIZE
Definition: uart.h:34
#define UART3_GPIO_RX
Definition: krooz_sd.h:92
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
Definition: uart_arch.c:65
#define UART2_GPIO_PORT_RX
Definition: lisa_l_1.0.h:67