Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
uart_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Antoine Drouin <poinix@gmail.com>
3  *
4  * This file is part of Paparazzi.
5  *
6  * Paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
26 #include BOARD_CONFIG
27 
28 #include "mcu_periph/uart.h"
29 
30 #include <stdint.h>
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 
37 #include "serial_port.h"
38 #include "rt_priority.h"
39 
40 #include <pthread.h>
41 #include <sys/select.h>
42 
43 #ifndef UART_THREAD_PRIO
44 #define UART_THREAD_PRIO 11
45 #endif
46 
47 static void uart_receive_handler(struct uart_periph *periph);
48 static void *uart_thread(void *data __attribute__((unused)));
49 static pthread_mutex_t uart_mutex = PTHREAD_MUTEX_INITIALIZER;
50 
51 //#define TRACE(fmt,args...) fprintf(stderr, fmt, args)
52 #define TRACE(fmt,args...)
53 
54 void uart_arch_init(void)
55 {
56  pthread_mutex_init(&uart_mutex, NULL);
57 
58  pthread_t tid;
59  if (pthread_create(&tid, NULL, uart_thread, NULL) != 0) {
60  fprintf(stderr, "uart_arch_init: Could not create UART reading thread.\n");
61  return;
62  }
63 #ifndef __APPLE__
64  pthread_setname_np(tid, "uart");
65 #endif
66 }
67 
68 static void *uart_thread(void *data __attribute__((unused)))
69 {
71 
72  /* file descriptor list */
73  fd_set fds_master;
74  /* maximum file descriptor number */
75  int fdmax = 0;
76 
77  /* clear the fd list */
78  FD_ZERO(&fds_master);
79  /* add used fds */
80  int __attribute__((unused)) fd;
81 #if USE_UART0
82  if (uart0.reg_addr != NULL) {
83  fd = ((struct SerialPort *)uart0.reg_addr)->fd;
84  FD_SET(fd, &fds_master);
85  if (fd > fdmax) {
86  fdmax = fd;
87  }
88  }
89 #endif
90 #if USE_UART1
91  if (uart1.reg_addr != NULL) {
92  fd = ((struct SerialPort *)uart1.reg_addr)->fd;
93  FD_SET(fd, &fds_master);
94  if (fd > fdmax) {
95  fdmax = fd;
96  }
97  }
98 #endif
99 #if USE_UART2
100  if (uart2.reg_addr != NULL) {
101  fd = ((struct SerialPort *)uart2.reg_addr)->fd;
102  FD_SET(fd, &fds_master);
103  if (fd > fdmax) {
104  fdmax = fd;
105  }
106  }
107 #endif
108 #if USE_UART3
109  if (uart3.reg_addr != NULL) {
110  fd = ((struct SerialPort *)uart3.reg_addr)->fd;
111  FD_SET(fd, &fds_master);
112  if (fd > fdmax) {
113  fdmax = fd;
114  }
115  }
116 #endif
117 #if USE_UART4
118  if (uart4.reg_addr != NULL) {
119  fd = ((struct SerialPort *)uart4.reg_addr)->fd;
120  FD_SET(fd, &fds_master);
121  if (fd > fdmax) {
122  fdmax = fd;
123  }
124  }
125 #endif
126 #if USE_UART5
127  if (uart5.reg_addr != NULL) {
128  fd = ((struct SerialPort *)uart5.reg_addr)->fd;
129  FD_SET(fd, &fds_master);
130  if (fd > fdmax) {
131  fdmax = fd;
132  }
133  }
134 #endif
135 #if USE_UART6
136  if (uart6.reg_addr != NULL) {
137  fd = ((struct SerialPort *)uart6.reg_addr)->fd;
138  FD_SET(fd, &fds_master);
139  if (fd > fdmax) {
140  fdmax = fd;
141  }
142  }
143 #endif
144 
145  /* fds to be read, modified after each select */
146  fd_set fds;
147 
148  while (1) {
149  /* reset list of fds to check */
150  fds = fds_master;
151 
152  if (select(fdmax + 1, &fds, NULL, NULL, NULL) < 0) {
153  fprintf(stderr, "uart_thread: select failed!");
154  } else {
155 #if USE_UART0
156  if (uart0.reg_addr != NULL) {
157  fd = ((struct SerialPort *)uart0.reg_addr)->fd;
158  if (FD_ISSET(fd, &fds)) {
159  uart_receive_handler(&uart0);
160  }
161  }
162 #endif
163 #if USE_UART1
164  if (uart1.reg_addr != NULL) {
165  fd = ((struct SerialPort *)uart1.reg_addr)->fd;
166  if (FD_ISSET(fd, &fds)) {
167  uart_receive_handler(&uart1);
168  }
169  }
170 #endif
171 #if USE_UART2
172  if (uart2.reg_addr != NULL) {
173  fd = ((struct SerialPort *)uart2.reg_addr)->fd;
174  if (FD_ISSET(fd, &fds)) {
175  uart_receive_handler(&uart2);
176  }
177  }
178 #endif
179 #if USE_UART3
180  if (uart3.reg_addr != NULL) {
181  fd = ((struct SerialPort *)uart3.reg_addr)->fd;
182  if (FD_ISSET(fd, &fds)) {
183  uart_receive_handler(&uart3);
184  }
185  }
186 #endif
187 #if USE_UART4
188  if (uart4.reg_addr != NULL) {
189  fd = ((struct SerialPort *)uart4.reg_addr)->fd;
190  if (FD_ISSET(fd, &fds)) {
191  uart_receive_handler(&uart4);
192  }
193  }
194 #endif
195 #if USE_UART5
196  if (uart5.reg_addr != NULL) {
197  fd = ((struct SerialPort *)uart5.reg_addr)->fd;
198  if (FD_ISSET(fd, &fds)) {
199  uart_receive_handler(&uart5);
200  }
201  }
202 #endif
203 #if USE_UART6
204  if (uart6.reg_addr != NULL) {
205  fd = ((struct SerialPort *)uart6.reg_addr)->fd;
206  if (FD_ISSET(fd, &fds)) {
207  uart_receive_handler(&uart6);
208  }
209  }
210 #endif
211  }
212  }
213 
214  return 0;
215 }
216 
217 // open serial link
218 // close first if already openned
219 static void uart_periph_open(struct uart_periph *periph, uint32_t baud)
220 {
221  periph->baudrate = baud;
222 
223  struct SerialPort *port;
224  // close serial port if already open
225  if (periph->reg_addr != NULL) {
226  port = (struct SerialPort *)(periph->reg_addr);
227  serial_port_close(port);
228  serial_port_free(port);
229  }
230  // open serial port
231  port = serial_port_new();
232  // use register address to store SerialPort structure pointer...
233  periph->reg_addr = (void *)port;
234 
235  //TODO: set device name in application and pass as argument
236  // FIXME: paparazzi baud is 9600 for B9600 while open_raw needs 12 for B9600
237  // /printf("opening %s on uart0 at termios.h baud value=%d\n", periph->dev, baud);
238  int ret = serial_port_open_raw(port, periph->dev, baud);
239  if (ret != 0) {
240  TRACE("Error opening %s code %d\n", periph->dev, ret);
241  serial_port_free(port);
242  periph->reg_addr = NULL;
243  }
244 }
245 
247 {
248  periph->baudrate = baud;
249 
250  // open serial port if not done
251  if (periph->reg_addr == NULL) {
252  uart_periph_open(periph, baud);
253  }
254  if (periph->reg_addr == NULL) {
255  // periph not started, do nothiing
256  return;
257  }
258  struct SerialPort *port = (struct SerialPort *)(periph->reg_addr);
259  serial_port_set_baudrate(port, baud);
260 }
261 
262 void uart_periph_set_bits_stop_parity(struct uart_periph *periph, uint8_t bits, uint8_t stop, uint8_t parity)
263 {
264  if (periph->reg_addr == NULL) {
265  // periph not started, do nothiing
266  return;
267  }
268  struct SerialPort *port = (struct SerialPort *)(periph->reg_addr);
269  serial_port_set_bits_stop_parity(port, bits, stop, parity);
270 }
271 
272 void uart_put_byte(struct uart_periph *periph, long fd __attribute__((unused)), uint8_t data)
273 {
274  if (periph->reg_addr == NULL) { return; } // device not initialized ?
275 
276  /* write single byte to serial port */
277  struct SerialPort *port = (struct SerialPort *)(periph->reg_addr);
278 
279  int ret = 0;
280  do {
281  ret = write((int)(port->fd), &data, 1);
282  } while (ret < 1 && errno == EAGAIN); //FIXME: max retry
283 
284  if (ret < 1) {
285  TRACE("uart_put_byte: write %d failed [%d: %s]\n", data, ret, strerror(errno));
286  }
287 }
288 
289 
290 static void __attribute__((unused)) uart_receive_handler(struct uart_periph *periph)
291 {
292  unsigned char c = 'D';
293 
294  if (periph->reg_addr == NULL) { return; } // device not initialized ?
295 
296  struct SerialPort *port = (struct SerialPort *)(periph->reg_addr);
297  int fd = port->fd;
298 
299  pthread_mutex_lock(&uart_mutex);
300 
301  while (read(fd, &c, 1) > 0) {
302  uint16_t temp = (periph->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE;
303  // check for more room in queue
304  if (temp != periph->rx_extract_idx) {
305  periph->rx_buf[periph->rx_insert_idx] = c;
306  periph->rx_insert_idx = temp; // update insert index
307  } else {
308  TRACE("uart_receive_handler: rx_buf full! discarding received byte: %x %c\n", c, c);
309  }
310  }
311  pthread_mutex_unlock(&uart_mutex);
312 }
313 
315 {
316  pthread_mutex_lock(&uart_mutex);
317  uint8_t ret = p->rx_buf[p->rx_extract_idx];
318  p->rx_extract_idx = (p->rx_extract_idx + 1) % UART_RX_BUFFER_SIZE;
319  pthread_mutex_unlock(&uart_mutex);
320  return ret;
321 }
322 
324 {
325  pthread_mutex_lock(&uart_mutex);
326  int available = p->rx_insert_idx - p->rx_extract_idx;
327  if (available < 0) {
328  available += UART_RX_BUFFER_SIZE;
329  }
330  pthread_mutex_unlock(&uart_mutex);
331  return available;
332 }
333 
334 #if USE_UART0
335 void uart0_init(void)
336 {
337  uart_periph_init(&uart0);
338  strncpy(uart0.dev, STRINGIFY(UART0_DEV), UART_DEV_NAME_SIZE);
339  uart_periph_set_baudrate(&uart0, UART0_BAUD);
340 }
341 #endif /* USE_UART0 */
342 
343 #if USE_UART1
344 void uart1_init(void)
345 {
346  uart_periph_init(&uart1);
347  strncpy(uart1.dev, STRINGIFY(UART1_DEV), UART_DEV_NAME_SIZE);
348  uart_periph_set_baudrate(&uart1, UART1_BAUD);
349 }
350 #endif /* USE_UART1 */
351 
352 #if USE_UART2
353 void uart2_init(void)
354 {
355  uart_periph_init(&uart2);
356  strncpy(uart2.dev, STRINGIFY(UART2_DEV), UART_DEV_NAME_SIZE);
357  uart_periph_set_baudrate(&uart2, UART2_BAUD);
358 }
359 #endif /* USE_UART2 */
360 
361 #if USE_UART3
362 void uart3_init(void)
363 {
364  uart_periph_init(&uart3);
365  strncpy(uart3.dev, STRINGIFY(UART3_DEV), UART_DEV_NAME_SIZE);
366  uart_periph_set_baudrate(&uart3, UART3_BAUD);
367 }
368 #endif /* USE_UART3 */
369 
370 #if USE_UART4
371 void uart4_init(void)
372 {
373  uart_periph_init(&uart4);
374  strncpy(uart4.dev, STRINGIFY(UART4_DEV), UART_DEV_NAME_SIZE);
375  uart_periph_set_baudrate(&uart4, UART4_BAUD);
376 }
377 #endif /* USE_UART4 */
378 
379 #if USE_UART5
380 void uart5_init(void)
381 {
382  uart_periph_init(&uart5);
383  strncpy(uart5.dev, STRINGIFY(UART5_DEV), UART_DEV_NAME_SIZE);
384  uart_periph_set_baudrate(&uart5, UART5_BAUD);
385 }
386 #endif /* USE_UART5 */
387 
388 #if USE_UART6
389 void uart6_init(void)
390 {
391  uart_periph_init(&uart6);
392  strncpy(uart6.dev, STRINGIFY(UART6_DEV), UART_DEV_NAME_SIZE);
393  uart_periph_set_baudrate(&uart6, UART6_BAUD);
394 }
395 #endif /* USE_UART6 */
UART5_DEV
#define UART5_DEV
Definition: bebop.h:46
uart_periph::rx_extract_idx
uint16_t rx_extract_idx
Definition: uart.h:74
c
VIC slots used for the LPC2148 define name e g gps UART1_VIC_SLOT e g modem SPI1_VIC_SLOT SPI1 in mcu_periph spi_arch c or spi_slave_hs_arch c(and some others not using the SPI peripheral yet..) I2C0_VIC_SLOT 8 mcu_periph/i2c_arch.c I2C1_VIC_SLOT 9 mcu_periph/i2c_arch.c USB_VIC_SLOT 10 usb
uint16_t
unsigned short uint16_t
Definition: types.h:16
rt_priority.h
uart_getch
uint8_t uart_getch(struct uart_periph *p)
Definition: uart_arch.c:968
SerialPort::fd
int fd
Definition: serial_port.h:30
serial_port.h
uart_periph_set_bits_stop_parity
void uart_periph_set_bits_stop_parity(struct uart_periph *p, uint8_t bits, uint8_t stop, uint8_t parity)
Set parity and stop bits.
Definition: uart_arch.c:1013
uart_char_available
int uart_char_available(struct uart_periph *p)
Check UART for available chars in receive buffer.
Definition: uart_arch.c:323
uint32_t
unsigned long uint32_t
Definition: types.h:18
uart_periph::rx_insert_idx
uint16_t rx_insert_idx
Definition: uart.h:73
uart_periph::rx_buf
uint8_t rx_buf[UART_RX_BUFFER_SIZE]
Receive buffer.
Definition: uart.h:72
serial_port_open_raw
int serial_port_open_raw(struct SerialPort *me, const char *device, speed_t speed)
Definition: serial_port.c:111
serial_port_set_bits_stop_parity
int serial_port_set_bits_stop_parity(struct SerialPort *me, const int bits, const int stop, const int parity)
Definition: serial_port.c:224
uart_periph::dev
char dev[UART_DEV_NAME_SIZE]
UART Dev (linux)
Definition: uart.h:87
TRACE
#define TRACE(fmt, args...)
Definition: uart_arch.c:52
uart.h
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
uart_periph::baudrate
int baudrate
UART Baudrate.
Definition: uart.h:83
uart_periph_set_baudrate
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
Set baudrate.
Definition: uart_arch.c:984
uart_arch_init
void uart_arch_init(void)
Definition: uart_arch.c:54
serial_port_set_baudrate
int serial_port_set_baudrate(struct SerialPort *me, speed_t speed)
Definition: serial_port.c:210
serial_port_close
void serial_port_close(struct SerialPort *me)
Definition: serial_port.c:184
uart_thread
static void * uart_thread(void *data)
Definition: uart_arch.c:68
UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE
Definition: uart_arch.h:31
uint8_t
unsigned char uint8_t
Definition: types.h:14
serial_port_new
struct SerialPort * serial_port_new(void)
Definition: serial_port.c:74
UART3_DEV
#define UART3_DEV
uart connected to SBUS input
Definition: disco.h:52
uart_put_byte
void uart_put_byte(struct uart_periph *p, long fd, uint8_t data)
Uart transmit implementation.
Definition: uart_arch.c:1095
uart_receive_handler
static void uart_receive_handler(struct uart_periph *periph)
Definition: uart_arch.c:290
UART2_DEV
#define UART2_DEV
Definition: beagle_bone_black.h:5
uart_periph_open
static void uart_periph_open(struct uart_periph *periph, uint32_t baud)
Definition: uart_arch.c:219
UART_DEV_NAME_SIZE
#define UART_DEV_NAME_SIZE
Definition: uart.h:51
fd
int fd
Definition: serial.c:26
get_rt_prio
static int get_rt_prio(int prio)
Definition: rt_priority.h:32
UART6_DEV
#define UART6_DEV
Definition: bebop.h:49
UART_THREAD_PRIO
#define UART_THREAD_PRIO
Definition: uart_arch.c:44
uart_periph
UART peripheral.
Definition: uart.h:70
UART1_DEV
#define UART1_DEV
Definition: ardrone2.h:7
uart_mutex
static pthread_mutex_t uart_mutex
Definition: uart_arch.c:49
uart_periph_init
void uart_periph_init(struct uart_periph *p)
Definition: uart.c:231
SerialPort
Definition: serial_port.h:29
uart_periph::reg_addr
void * reg_addr
UART Register.
Definition: uart.h:81
p
static float p[2][2]
Definition: ins_alt_float.c:268
serial_port_free
void serial_port_free(struct SerialPort *me)
Definition: serial_port.c:80
UART4_DEV
#define UART4_DEV
Definition: beagle_bone_black.h:6