APM:Libraries
HAL_Linux_Class.cpp
Go to the documentation of this file.
1 #include "HAL_Linux_Class.h"
2 
3 #include <assert.h>
4 #include <signal.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 
9 #include <AP_HAL/AP_HAL.h>
14 #include <AP_Module/AP_Module.h>
15 
16 #include "AnalogIn_ADS1115.h"
17 #include "AnalogIn_IIO.h"
18 #include "AnalogIn_Navio2.h"
19 #include "GPIO.h"
20 #include "I2CDevice.h"
21 #include "OpticalFlow_Onboard.h"
22 #include "RCInput.h"
23 #include "RCInput_AioPRU.h"
24 #include "RCInput_Navio2.h"
25 #include "RCInput_PRU.h"
26 #include "RCInput_RPI.h"
27 #include "RCInput_SBUS.h"
28 #include "RCInput_SoloLink.h"
29 #include "RCInput_UART.h"
30 #include "RCInput_UDP.h"
31 #include "RCInput_115200.h"
32 #include "RCInput_Multi.h"
33 #include "RCInput_ZYNQ.h"
34 #include "RCOutput_AioPRU.h"
35 #include "RCOutput_Bebop.h"
36 #include "RCOutput_Disco.h"
37 #include "RCOutput_PCA9685.h"
38 #include "RCOutput_PRU.h"
39 #include "RCOutput_Sysfs.h"
40 #include "RCOutput_ZYNQ.h"
41 #include "SPIDevice.h"
42 #include "SPIUARTDriver.h"
43 #include "Scheduler.h"
44 #include "Storage.h"
45 #include "UARTDriver.h"
46 #include "Util.h"
47 #include "Util_RPI.h"
48 
49 using namespace Linux;
50 
51 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || \
52  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 || \
53  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_EDGE || \
54  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBRAIN2 || \
55  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH || \
56  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DARK || \
57  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXFMINI
59 #else
60 static Util utilInstance;
61 #endif
62 
63 // 5 serial ports on Linux
64 static UARTDriver uartADriver(true);
65 static UARTDriver uartCDriver(false);
66 static UARTDriver uartDDriver(false);
67 static UARTDriver uartEDriver(false);
68 static UARTDriver uartFDriver(false);
69 
72 
73 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || \
74  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 || \
75  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH
77 #else
78 static UARTDriver uartBDriver(false);
79 #endif
80 
81 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || \
82  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBRAIN2 || \
83  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH || \
84  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXFMINI
86 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || \
87  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD || \
88  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI || \
89  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE || \
90  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET || \
91  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_MINLURE
92 static AnalogIn_IIO analogIn;
93 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 || \
94  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_EDGE
96 #else
98 #endif
99 
101 
102 /*
103  use the BBB gpio driver on ERLE, PXF, BBBMINI, BLUE and PocketPilot
104  */
105 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || \
106  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD || \
107  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI || \
108  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE || \
109  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET
111 /*
112  use the RPI gpio driver on Navio
113  */
114 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBRAIN2 || \
115  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH || \
116  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DARK || \
117  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXFMINI
118 static GPIO_RPI gpioDriver;
119 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || \
120  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 || \
121  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_EDGE
122 static GPIO_Sysfs gpioDriver;
123 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_MINLURE || \
124  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP || \
125  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO || \
126  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_AERO
127 static GPIO_Sysfs gpioDriver;
128 #else
129 static Empty::GPIO gpioDriver;
130 #endif
131 
132 /*
133  use the PRU based RCInput driver on ERLE and PXF
134  */
135 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD
137 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI || \
138  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET
140 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE
141 static RCInput_Multi rcinDriver{2, new RCInput_AioPRU, new RCInput_115200("/dev/ttyO4")};
142 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || \
143  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBRAIN2 || \
144  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH || \
145  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DARK || \
146  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXFMINI
147 static RCInput_RPI rcinDriver;
148 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ZYNQ || \
149  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_OCPOC_ZYNQ
150 static RCInput_ZYNQ rcinDriver;
151 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP
152 static RCInput_UDP rcinDriver;
153 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_MINLURE
154 static RCInput_UART rcinDriver("/dev/ttyS5");
155 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO
156 static RCInput_Multi rcinDriver{2, new RCInput_SBUS, new RCInput_115200("/dev/uart-sumd")};
157 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_AERO
159 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 || \
160  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_EDGE
162 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_RST_ZYNQ
163 static RCInput_SBUS rcinDriver;
164 #else
165 static RCInput rcinDriver;
166 #endif
167 
168 /*
169  use the PRU based RCOutput driver on ERLE and PXF
170  */
171 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD
173 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI || \
174  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE || \
175  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET
177 /*
178  use the PCA9685 based RCOutput driver on Navio and Erle-Brain 2
179  */
180 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBRAIN2 || \
181  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXFMINI
182 static RCOutput_PCA9685 rcoutDriver(i2c_mgr_instance.get_device(1, PCA9685_PRIMARY_ADDRESS), true, 3, RPI_GPIO_27);
183 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO
185 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH
186 static RCOutput_PCA9685 rcoutDriver(i2c_mgr_instance.get_device(1, PCA9685_QUATENARY_ADDRESS), false, 0, RPI_GPIO_4);
187 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DARK
188 static RCOutput_PCA9685 rcoutDriver(i2c_mgr_instance.get_device(1, PCA9685_QUINARY_ADDRESS), false, 0, RPI_GPIO_27);
189 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ZYNQ || \
190  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_OCPOC_ZYNQ
192 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP
193 static RCOutput_Bebop rcoutDriver(i2c_mgr_instance.get_device(HAL_RCOUT_BEBOP_BLDC_I2C_BUS, HAL_RCOUT_BEBOP_BLDC_I2C_ADDR));
194 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_MINLURE
195 static RCOutput_PCA9685 rcoutDriver(i2c_mgr_instance.get_device(
196  { /* UEFI with lpss set to ACPI */
197  "platform/80860F41:05",
198  /* UEFI with lpss set to PCI */
199  "pci0000:00/0000:00:18.6" },
201 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO
202 static RCOutput_Disco rcoutDriver(i2c_mgr_instance.get_device(HAL_RCOUT_DISCO_BLDC_I2C_BUS, HAL_RCOUT_DISCO_BLDC_I2C_ADDR));
203 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2
204 static RCOutput_Sysfs rcoutDriver(0, 0, 14);
205 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_AERO
207 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_EDGE
208 static RCOutput_Sysfs rcoutDriver(0, 0, 15);
209 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_RST_ZYNQ
210 static RCOutput_Sysfs rcoutDriver(0, 0, 8);
211 #else
213 #endif
214 
216 
217 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP ||\
218  CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_MINLURE
220 #else
222 #endif
223 
225  AP_HAL::HAL(
226  &uartADriver,
227  &uartBDriver,
228  &uartCDriver,
229  &uartDDriver,
230  &uartEDriver,
231  &uartFDriver,
232  &i2c_mgr_instance,
233  &spi_mgr_instance,
234  &analogIn,
235  &storageDriver,
236  &uartADriver,
237  &gpioDriver,
238  &rcinDriver,
239  &rcoutDriver,
240  &schedulerInstance,
241  &utilInstance,
242  &opticalFlow,
243  nullptr)
244 {}
245 
246 void _usage(void)
247 {
248  printf("Usage: -A uartAPath -B uartBPath -C uartCPath -D uartDPath -E uartEPath -F uartFPath\n");
249  printf("Options:\n");
250  printf("\tserial:\n");
251  printf(" -A /dev/ttyO4\n");
252  printf("\t -B /dev/ttyS1\n");
253  printf("\tnetworking tcp:\n");
254  printf("\t -C tcp:192.168.2.15:1243:wait\n");
255  printf("\t -A tcp:11.0.0.2:5678\n");
256  printf("\t -A udp:11.0.0.2:14550\n");
257  printf("\tnetworking UDP:\n");
258  printf("\t -A udp:11.0.0.255:14550:bcast\n");
259  printf("\t -A udpin:0.0.0.0:14550\n");
260  printf("\tcustom log path:\n");
261  printf("\t --log-directory /var/APM/logs\n");
262  printf("\t -l /var/APM/logs\n");
263  printf("\tcustom terrain path:\n");
264  printf("\t --terrain-directory /var/APM/terrain\n");
265  printf("\t -t /var/APM/terrain\n");
266 #if AP_MODULE_SUPPORTED
267  printf("\tmodule support:\n");
268  printf("\t --module-directory %s\n", AP_MODULE_DEFAULT_DIRECTORY);
269  printf("\t -M %s\n", AP_MODULE_DEFAULT_DIRECTORY);
270 #endif
271 }
272 
273 void HAL_Linux::run(int argc, char* const argv[], Callbacks* callbacks) const
274 {
275 #if AP_MODULE_SUPPORTED
276  const char *module_path = AP_MODULE_DEFAULT_DIRECTORY;
277 #endif
278 
279  assert(callbacks);
280 
281  int opt;
282  const struct GetOptLong::option options[] = {
283  {"uartA", true, 0, 'A'},
284  {"uartB", true, 0, 'B'},
285  {"uartC", true, 0, 'C'},
286  {"uartD", true, 0, 'D'},
287  {"uartE", true, 0, 'E'},
288  {"uartF", true, 0, 'F'},
289  {"log-directory", true, 0, 'l'},
290  {"terrain-directory", true, 0, 't'},
291  {"storage-directory", true, 0, 's'},
292  {"module-directory", true, 0, 'M'},
293  {"help", false, 0, 'h'},
294  {0, false, 0, 0}
295  };
296 
297  GetOptLong gopt(argc, argv, "A:B:C:D:E:F:l:t:s:he:SM:",
298  options);
299 
300  /*
301  parse command line options
302  */
303  while ((opt = gopt.getoption()) != -1) {
304  switch (opt) {
305  case 'A':
307  break;
308  case 'B':
309  uartBDriver.set_device_path(gopt.optarg);
310  break;
311  case 'C':
313  break;
314  case 'D':
316  break;
317  case 'E':
319  break;
320  case 'F':
322  break;
323  case 'l':
324  utilInstance.set_custom_log_directory(gopt.optarg);
325  break;
326  case 't':
327  utilInstance.set_custom_terrain_directory(gopt.optarg);
328  break;
329  case 's':
330  utilInstance.set_custom_storage_directory(gopt.optarg);
331  break;
332 #if AP_MODULE_SUPPORTED
333  case 'M':
334  module_path = gopt.optarg;
335  break;
336 #endif
337  case 'h':
338  _usage();
339  exit(0);
340  default:
341  printf("Unknown option '%c'\n", (char)opt);
342  exit(1);
343  }
344  }
345 
347 
348  scheduler->init();
349  gpio->init();
350  rcout->init();
351  rcin->init();
352  uartA->begin(115200);
353  uartE->begin(115200);
354  uartF->begin(115200);
355  analogin->init();
356  utilInstance.init(argc+gopt.optind-1, &argv[gopt.optind-1]);
357 
358  // NOTE: See commit 9f5b4ffca ("AP_HAL_Linux_Class: Correct
359  // deadlock, and infinite loop in setup()") for details about the
360  // order of scheduler initialize and setup on Linux.
362 
363  // possibly load external modules
364 #if AP_MODULE_SUPPORTED
365  if (module_path != nullptr) {
366  AP_Module::init(module_path);
367  }
368 #endif
369 
370 #if AP_MODULE_SUPPORTED
371  AP_Module::call_hook_setup_start();
372 #endif
373  callbacks->setup();
374 #if AP_MODULE_SUPPORTED
375  AP_Module::call_hook_setup_complete();
376 #endif
377 
378  while (!_should_exit) {
379  callbacks->loop();
380  }
381 
382  rcin->teardown();
383  I2CDeviceManager::from(i2c_mgr)->teardown();
384  SPIDeviceManager::from(spi)->teardown();
385  Scheduler::from(scheduler)->teardown();
386 }
387 
389 {
390  struct sigaction sa = { };
391 
392  sa.sa_flags = SA_NOCLDSTOP;
393  sa.sa_handler = HAL_Linux::exit_signal_handler;
394  sigaction(SIGTERM, &sa, NULL);
395  sigaction(SIGINT, &sa, NULL);
396 }
397 
399 
401 {
402  halInstance._should_exit = true;
403 }
404 
406 {
407  return halInstance;
408 }
void setup_signal_handlers() const
static UtilRPI utilInstance
virtual void init()=0
int printf(const char *fmt,...)
Definition: stdio.c:113
virtual void setup()=0
static void exit_signal_handler(int)
AP_HAL::UARTDriver * uartE
Definition: HAL.h:104
static SPIUARTDriver uartBDriver
virtual void loop()=0
static AnalogIn_ADS1115 analogIn
virtual void begin(uint32_t baud)=0
static UARTDriver uartDDriver(false)
#define PCA9685_PRIMARY_ADDRESS
static GPIO_BBB gpioDriver
void _usage(void)
static Storage storageDriver
static UARTDriver uartADriver(true)
static UARTDriver uartEDriver(false)
static Scheduler schedulerInstance
static UARTDriver uartCDriver(false)
#define PCA9685_QUATENARY_ADDRESS
const char * optarg
Definition: getopt_cpp.h:29
virtual void init()=0
#define RPI_GPIO_27
Definition: GPIO_RPI.h:38
AP_HAL::OwnPtr< AP_HAL::I2CDevice > get_device(std::vector< const char *> devpaths, uint8_t address) override
Definition: I2CDevice.cpp:286
void set_custom_storage_directory(const char *_custom_storage_directory)
Definition: Util.h:54
virtual void init()=0
int optind
Definition: getopt_cpp.h:26
void set_device_path(const char *path)
Definition: UARTDriver.cpp:46
static RCInput_PRU rcinDriver
AP_HAL::UARTDriver * uartF
Definition: HAL.h:105
virtual void init()=0
static RCOutput_PRU rcoutDriver
void init(int argc, char *const *argv)
Definition: Util.cpp:27
AP_HAL::SPIDeviceManager * spi
Definition: HAL.h:107
#define NULL
Definition: hal_types.h:59
const HAL & get_HAL()
static SPIDeviceManager spi_mgr_instance
AP_HAL::I2CDeviceManager * i2c_mgr
Definition: HAL.h:106
virtual void init()=0
static I2CDeviceManager i2c_mgr_instance
virtual void teardown()
Definition: RCInput.h:17
AP_HAL::UARTDriver * uartA
Definition: HAL.h:100
bool _should_exit
AP_HAL::GPIO * gpio
Definition: HAL.h:111
void init()
Generic board initialization function.
Definition: system.cpp:136
AP_HAL::RCOutput * rcout
Definition: HAL.h:113
static HAL_Linux halInstance
void set_custom_log_directory(const char *_custom_log_directory)
Definition: Util.h:52
void run(int argc, char *const *argv, Callbacks *callbacks) const override
#define PCA9685_QUINARY_ADDRESS
AP_HAL::RCInput * rcin
Definition: HAL.h:112
void set_custom_terrain_directory(const char *_custom_terrain_directory)
Definition: Util.h:53
int getoption(void)
#define RPI_GPIO_4
Definition: GPIO_RPI.h:15
static UARTDriver uartFDriver(false)
static OpticalFlow_Onboard opticalFlow
AP_HAL::Scheduler * scheduler
Definition: HAL.h:114
AP_HAL::AnalogIn * analogin
Definition: HAL.h:108
virtual void system_initialized()=0