Paparazzi UAS  v5.15_devel-111-g8fb4629
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
pipe_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2018 Kirk Scheper <kirkscheper@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 "mcu_periph/pipe.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <pthread.h>
31 #include <sys/select.h>
32 
33 // FIFO
34 #include <fcntl.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 
39 #include "rt_priority.h"
40 
41 #ifndef PIPE_THREAD_PRIO
42 #define PIPE_THREAD_PRIO 10
43 #endif
44 
45 static void *pipe_thread(void *data __attribute__((unused)));
46 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
47 
48 void pipe_arch_init(void)
49 {
50  pthread_mutex_init(&pipe_mutex, NULL);
51 
52 #if defined(USE_PIPE0_WRITER) || defined(USE_PIPE0_READER)
53  PIPE0Init();
54 #endif
55 #if defined(USE_PIPE1_WRITER) || defined(USE_PIPE1_READER)
56  PIPE1Init();
57 #endif
58 #if defined(USE_PIPE2_WRITER) || defined(USE_PIPE2_READER)
59  PIPE2Init();
60 #endif
61 
62  pthread_t tid;
63  if (pthread_create(&tid, NULL, pipe_thread, NULL) != 0) {
64  fprintf(stderr, "pipe_arch_init: Could not create PIPE reading thread.\n");
65  return;
66  }
67 #ifndef __APPLE__
68  pthread_setname_np(tid, "pipe");
69 #endif
70 }
71 
76 void pipe_arch_periph_init(struct pipe_periph *p, char *read_name, char* write_name)
77 {
78  if(read_name != NULL)
79  {
80  if( access( read_name, F_OK ) == -1 ) {
81  mkfifo(read_name, 0666);
82  }
83  p->fd_read = open(read_name, O_RDWR | O_NONBLOCK);
84  } else {
85  p->fd_read = -1;
86  }
87 
88  if(write_name != NULL)
89  {
90  if( access( write_name, F_OK ) == -1 ) {
91  mkfifo(write_name, 0666);
92  }
93  p->fd_write = open(write_name, O_RDWR | O_NONBLOCK);
94  } else {
95  p->fd_write = -1;
96  }
97 }
98 
105 {
106  pthread_mutex_lock(&pipe_mutex);
107  int16_t available = p->rx_insert_idx - p->rx_extract_idx;
108  if (available < 0) {
109  available += PIPE_RX_BUFFER_SIZE;
110  }
111  pthread_mutex_unlock(&pipe_mutex);
112  return (uint16_t)available;
113 }
114 
121 {
122  pthread_mutex_lock(&pipe_mutex);
123  uint8_t ret = p->rx_buf[p->rx_extract_idx];
125  pthread_mutex_unlock(&pipe_mutex);
126  return ret;
127 }
128 
133 {
134  if (p == NULL) { return; }
135  if (p->fd_read < 0) { return; }
136 
137  int16_t i;
140 
141  if (available <= 0) {
142  return; // No space
143  }
144 
145  ssize_t bytes_read = read(p->fd_read, buf, available);
146 
147  pthread_mutex_lock(&pipe_mutex);
148  if (bytes_read > 0) {
149  for (i = 0; i < bytes_read; i++) {
150  p->rx_buf[p->rx_insert_idx] = buf[i];
152  }
153  }
154  pthread_mutex_unlock(&pipe_mutex);
155 }
156 
160 void pipe_send_message(struct pipe_periph *p, long fd __attribute__((unused)))
161 {
162  if (p == NULL) { return; }
163  if (p->fd_write < 0) { return; }
164 
165  if (p->tx_insert_idx > 0) {
166  ssize_t bytes_sent = write(p->fd_write, p->tx_buf, p->tx_insert_idx);
167  if (bytes_sent != p->tx_insert_idx) {
168  if (bytes_sent < 0) {
169  fprintf(stderr, "pipe_send_message failed\n");
170  } else {
171  fprintf(stderr, "pipe_send_message: only sent %d bytes instead of %d\n",
172  (int)bytes_sent, p->tx_insert_idx);
173  }
174  }
175  p->tx_insert_idx = 0;
176  }
177 }
178 
182 void pipe_send_raw(struct pipe_periph *p, long fd __attribute__((unused)), uint8_t *buffer, uint16_t size)
183 {
184  if (p == NULL) { return; }
185  if (p->fd_write < 0) { return; }
186 
187  ssize_t test __attribute__((unused)) = write(p->fd_write, buffer, size);
188 }
189 
193 static void *pipe_thread(void *data __attribute__((unused)))
194 {
196 
197  /* file descriptor list */
198  fd_set fds_master;
199  /* maximum file descriptor number */
200  int fdmax = 0;
201 
202  /* clear the fd list */
203  FD_ZERO(&fds_master);
204  /* add used file descriptors */
205  int fd __attribute__((unused));
206 #ifdef USE_PIPE0_READER
207  if (pipe0.fd_read >= 0){
208  FD_SET(pipe0.fd_read, &fds_master);
209  if (pipe0.fd_read > fdmax) {
210  fdmax = pipe0.fd_read;
211  }
212  }
213 #endif
214 #ifdef USE_PIPE1_READER
215  if(pipe1.fd_read >= 0){
216  FD_SET(pipe1.fd_read, &socks_master);
217  if (pipe1.fd_read > fdmax) {
218  fdmax = pipe1.fd_read;
219  }
220  }
221 #endif
222 #ifdef USE_PIPE2_READER
223  if(pipe2.fd_read >= 0){
224  FD_SET(pipe2.fd_read, &socks_master);
225  if (pipe2.fd_read > fdmax) {
226  fdmax = pipe2.fd_read;
227  }
228  }
229 #endif
230 
231  /* files to be read, modified after each select */
232  fd_set fds;
233 
234  while (1) {
235  /* reset list of socks to check */
236  fds = fds_master;
237 
238  if (select(fdmax + 1, &fds, NULL, NULL, NULL) < 0) {
239  fprintf(stderr, "pipe_thread: select failed!");
240  } else {
241 #ifdef USE_PIPE0_READER
242  if (FD_ISSET(pipe0.fd_read, &fds)) {
243  pipe_receive(&pipe0);
244  }
245 #endif
246 #ifdef USE_PIPE1_READER
247  if (FD_ISSET(pipe1.fd_read, &fds)) {
248  pipe_receive(&pipe1);
249  }
250 #endif
251 #ifdef USE_PIPE2_READER
252  if (FD_ISSET(pipe2.fd_read, &fds)) {
253  pipe_receive(&pipe2);
254  }
255 #endif
256  }
257  }
258  return 0;
259 }
unsigned short uint16_t
Definition: types.h:16
arch independent PIPE API
void pipe_receive(struct pipe_periph *p)
Read bytes from PIPE.
Definition: pipe_arch.c:132
static void * pipe_thread(void *data)
check for new pipe packets to receive.
Definition: pipe_arch.c:193
uint16_t tx_insert_idx
Definition: pipe.h:42
uint8_t rx_buf[PIPE_RX_BUFFER_SIZE]
Receive buffer.
Definition: pipe.h:37
uint16_t rx_extract_idx
Definition: pipe.h:39
void pipe_arch_periph_init(struct pipe_periph *p, char *read_name, char *write_name)
Initialize the PIPE peripheral.
Definition: pipe_arch.c:76
Functions to obtain rt priority or set the nice level.
void pipe_send_raw(struct pipe_periph *p, long fd, uint8_t *buffer, uint16_t size)
Send a packet from another buffer.
Definition: pipe_arch.c:182
signed short int16_t
Definition: types.h:17
uint16_t rx_insert_idx
Definition: pipe.h:38
int fd_read
PIPE file descriptor.
Definition: pipe.h:44
uint8_t tx_buf[PIPE_TX_BUFFER_SIZE]
Transmit buffer.
Definition: pipe.h:41
unsigned char uint8_t
Definition: types.h:14
int fd
Definition: serial.c:26
#define PIPE_THREAD_PRIO
Definition: pipe_arch.c:42
#define PIPE_RX_BUFFER_SIZE
Definition: pipe_arch.h:31
static float p[2][2]
static pthread_mutex_t pipe_mutex
Definition: pipe_arch.c:46
int fd_write
Definition: pipe.h:45
uint8_t pipe_getch(struct pipe_periph *p)
Get the last character from the receive buffer.
Definition: pipe_arch.c:120
static int get_rt_prio(int prio)
Definition: rt_priority.h:32
uint16_t pipe_char_available(struct pipe_periph *p)
Get number of bytes available in receive buffer.
Definition: pipe_arch.c:104
void pipe_send_message(struct pipe_periph *p, long fd)
Send a message.
Definition: pipe_arch.c:160
void pipe_arch_init(void)
Definition: pipe_arch.c:48