PX4 Firmware
PX4 Autopilot Software http://px4.io
bmi055_main.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2018 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 #include "BMI055_accel.hpp"
35 #include "BMI055_gyro.hpp"
36 
37 /** driver 'main' command */
38 extern "C" { __EXPORT int bmi055_main(int argc, char *argv[]); }
39 
44 };
45 
46 namespace bmi055
47 {
48 
49 BMI055_accel *g_acc_dev_int; // on internal bus (accel)
50 BMI055_accel *g_acc_dev_ext; // on external bus (accel)
51 BMI055_gyro *g_gyr_dev_int; // on internal bus (gyro)
52 BMI055_gyro *g_gyr_dev_ext; // on external bus (gyro)
53 
54 void start(bool, enum Rotation, enum sensor_type);
55 void stop(bool, enum sensor_type);
56 void info(bool, enum sensor_type);
57 void regdump(bool, enum sensor_type);
58 void testerror(bool, enum sensor_type);
59 void usage();
60 
61 /**
62  * Start the driver.
63  *
64  * This function only returns if the driver is up and running
65  * or failed to detect the sensor.
66  */
67 void
68 start(bool external_bus, enum Rotation rotation, enum sensor_type sensor)
69 {
70  BMI055_accel **g_dev_acc_ptr = external_bus ? &g_acc_dev_ext : &g_acc_dev_int;
71  const char *path_accel = external_bus ? BMI055_DEVICE_PATH_ACCEL_EXT : BMI055_DEVICE_PATH_ACCEL;
72 
73  BMI055_gyro **g_dev_gyr_ptr = external_bus ? &g_gyr_dev_ext : &g_gyr_dev_int;
74  const char *path_gyro = external_bus ? BMI055_DEVICE_PATH_GYRO_EXT : BMI055_DEVICE_PATH_GYRO;
75 
76  if (sensor == BMI055_ACCEL) {
77  if (*g_dev_acc_ptr != nullptr)
78  /* if already started, the still command succeeded */
79  {
80  errx(0, "bmi055 accel sensor already started");
81  }
82 
83  /* create the driver */
84  if (external_bus) {
85 #if defined(PX4_SPI_BUS_EXT) && defined(PX4_SPIDEV_EXT_BMI)
86  *g_dev_acc_ptr = new BMI055_accel(PX4_SPI_BUS_EXT, path_accel, PX4_SPIDEV_EXT_BMI, rotation);
87 #else
88  errx(0, "External SPI not available");
89 #endif
90 
91  } else {
92  *g_dev_acc_ptr = new BMI055_accel(PX4_SPI_BUS_SENSORS, path_accel, PX4_SPIDEV_BMI055_ACC, rotation);
93  }
94 
95  if (*g_dev_acc_ptr == nullptr) {
96  goto fail_accel;
97  }
98 
99  if (OK != (*g_dev_acc_ptr)->init()) {
100  goto fail_accel;
101  }
102 
103  // start automatic data collection
104  (*g_dev_acc_ptr)->start();
105  }
106 
107  if (sensor == BMI055_GYRO) {
108 
109  if (*g_dev_gyr_ptr != nullptr) {
110  errx(0, "bmi055 gyro sensor already started");
111  }
112 
113  /* create the driver */
114  if (external_bus) {
115 #if defined(PX4_SPI_BUS_EXT) && defined(PX4_SPIDEV_EXT_BMI)
116  *g_dev_ptr = new BMI055_gyro(PX4_SPI_BUS_EXT, path_gyro, PX4_SPIDEV_EXT_BMI, rotation);
117 #else
118  errx(0, "External SPI not available");
119 #endif
120 
121  } else {
122  *g_dev_gyr_ptr = new BMI055_gyro(PX4_SPI_BUS_SENSORS, path_gyro, PX4_SPIDEV_BMI055_GYR, rotation);
123  }
124 
125  if (*g_dev_gyr_ptr == nullptr) {
126  goto fail_gyro;
127  }
128 
129  if (OK != (*g_dev_gyr_ptr)->init()) {
130  goto fail_gyro;
131  }
132 
133  // start automatic data collection
134  (*g_dev_gyr_ptr)->start();
135  }
136 
137  exit(PX4_OK);
138 
139 fail_accel:
140 
141  if (*g_dev_acc_ptr != nullptr) {
142  delete (*g_dev_acc_ptr);
143  *g_dev_acc_ptr = nullptr;
144  }
145 
146  PX4_WARN("No BMI055 accel found");
147  exit(PX4_ERROR);
148 
149 fail_gyro:
150 
151  if (*g_dev_gyr_ptr != nullptr) {
152  delete (*g_dev_gyr_ptr);
153  *g_dev_gyr_ptr = nullptr;
154  }
155 
156  PX4_WARN("No BMI055 gyro found");
157  exit(PX4_ERROR);
158 }
159 
160 void
161 stop(bool external_bus, enum sensor_type sensor)
162 {
163  BMI055_accel **g_dev_acc_ptr = external_bus ? &g_acc_dev_ext : &g_acc_dev_int;
164  BMI055_gyro **g_dev_gyr_ptr = external_bus ? &g_gyr_dev_ext : &g_gyr_dev_int;
165 
166  if (sensor == BMI055_ACCEL) {
167  if (*g_dev_acc_ptr != nullptr) {
168  delete *g_dev_acc_ptr;
169  *g_dev_acc_ptr = nullptr;
170 
171  } else {
172  /* warn, but not an error */
173  warnx("bmi055 accel sensor already stopped.");
174  }
175  }
176 
177  if (sensor == BMI055_GYRO) {
178  if (*g_dev_gyr_ptr != nullptr) {
179  delete *g_dev_gyr_ptr;
180  *g_dev_gyr_ptr = nullptr;
181 
182  } else {
183  /* warn, but not an error */
184  warnx("bmi055 gyro sensor already stopped.");
185  }
186  }
187 
188  exit(0);
189 
190 }
191 
192 /**
193  * Print a little info about the driver.
194  */
195 void
196 info(bool external_bus, enum sensor_type sensor)
197 {
198  BMI055_accel **g_dev_acc_ptr = external_bus ? &g_acc_dev_ext : &g_acc_dev_int;
199  BMI055_gyro **g_dev_gyr_ptr = external_bus ? &g_gyr_dev_ext : &g_gyr_dev_int;
200 
201  if (sensor == BMI055_ACCEL) {
202  if (*g_dev_acc_ptr == nullptr) {
203  errx(1, "bmi055 accel driver not running");
204  }
205 
206  printf("state @ %p\n", *g_dev_acc_ptr);
207  (*g_dev_acc_ptr)->print_info();
208  }
209 
210  if (sensor == BMI055_GYRO) {
211  if (*g_dev_gyr_ptr == nullptr) {
212  errx(1, "bmi055 gyro driver not running");
213  }
214 
215  printf("state @ %p\n", *g_dev_gyr_ptr);
216  (*g_dev_gyr_ptr)->print_info();
217  }
218 
219  exit(0);
220 }
221 
222 /**
223  * Dump the register information
224  */
225 void
226 regdump(bool external_bus, enum sensor_type sensor)
227 {
228  BMI055_accel **g_dev_acc_ptr = external_bus ? &g_acc_dev_ext : &g_acc_dev_int;
229  BMI055_gyro **g_dev_gyr_ptr = external_bus ? &g_gyr_dev_ext : &g_gyr_dev_int;
230 
231  if (sensor == BMI055_ACCEL) {
232  if (*g_dev_acc_ptr == nullptr) {
233  errx(1, "bmi055 accel driver not running");
234  }
235 
236  printf("regdump @ %p\n", *g_dev_acc_ptr);
237  (*g_dev_acc_ptr)->print_registers();
238  }
239 
240  if (sensor == BMI055_GYRO) {
241  if (*g_dev_gyr_ptr == nullptr) {
242  errx(1, "bmi055 gyro driver not running");
243  }
244 
245  printf("regdump @ %p\n", *g_dev_gyr_ptr);
246  (*g_dev_gyr_ptr)->print_registers();
247  }
248 
249  exit(0);
250 }
251 
252 /**
253  * deliberately produce an error to test recovery
254  */
255 void
256 testerror(bool external_bus, enum sensor_type sensor)
257 {
258  BMI055_accel **g_dev_acc_ptr = external_bus ? &g_acc_dev_ext : &g_acc_dev_int;
259  BMI055_gyro **g_dev_gyr_ptr = external_bus ? &g_gyr_dev_ext : &g_gyr_dev_int;
260 
261  if (sensor == BMI055_ACCEL) {
262  if (*g_dev_acc_ptr == nullptr) {
263  errx(1, "bmi055 accel driver not running");
264  }
265 
266  (*g_dev_acc_ptr)->test_error();
267  }
268 
269  if (sensor == BMI055_GYRO) {
270  if (*g_dev_gyr_ptr == nullptr) {
271  errx(1, "bmi055 gyro driver not running");
272  }
273 
274  (*g_dev_gyr_ptr)->test_error();
275  }
276 
277  exit(0);
278 }
279 
280 void
282 {
283  warnx("missing command: try 'start', 'info', 'stop', 'regdump', 'testerror'");
284  warnx("options:");
285  warnx(" -X (external bus)");
286  warnx(" -R rotation");
287  warnx(" -A (Enable Accelerometer)");
288  warnx(" -G (Enable Gyroscope)");
289 }
290 
291 }//namespace ends
292 
293 
294 BMI055::BMI055(const char *name, const char *devname, int bus, uint32_t device, enum spi_mode_e mode,
295  uint32_t frequency, enum Rotation rotation):
296  SPI(name, devname, bus, device, mode, frequency),
297  _whoami(0),
298  _register_wait(0),
299  _reset_wait(0),
300  _rotation(rotation),
301  _checked_next(0)
302 {
303 }
304 
305 uint8_t
306 BMI055::read_reg(unsigned reg)
307 {
308  uint8_t cmd[2] = { (uint8_t)(reg | DIR_READ), 0};
309 
310  transfer(cmd, cmd, sizeof(cmd));
311 
312  return cmd[1];
313 }
314 
315 uint16_t
316 BMI055::read_reg16(unsigned reg)
317 {
318  uint8_t cmd[3] = { (uint8_t)(reg | DIR_READ), 0, 0 };
319 
320  transfer(cmd, cmd, sizeof(cmd));
321 
322  return (uint16_t)(cmd[1] << 8) | cmd[2];
323 }
324 
325 void
326 BMI055::write_reg(unsigned reg, uint8_t value)
327 {
328  uint8_t cmd[2];
329 
330  cmd[0] = reg | DIR_WRITE;
331  cmd[1] = value;
332 
333  transfer(cmd, nullptr, sizeof(cmd));
334 }
335 
336 int
337 bmi055_main(int argc, char *argv[])
338 {
339  bool external_bus = false;
340  int ch;
341  enum Rotation rotation = ROTATION_NONE;
342  enum sensor_type sensor = BMI055_NONE;
343  int myoptind = 1;
344  const char *myoptarg = NULL;
345 
346  /* jump over start/off/etc and look at options first */
347  while ((ch = px4_getopt(argc, argv, "XR:AG", &myoptind, &myoptarg)) != EOF) {
348  switch (ch) {
349  case 'X':
350  external_bus = true;
351  break;
352 
353  case 'R':
354  rotation = (enum Rotation)atoi(myoptarg);
355  break;
356 
357  case 'A':
358  sensor = BMI055_ACCEL;
359  break;
360 
361  case 'G':
362  sensor = BMI055_GYRO;
363  break;
364 
365  default:
366  bmi055::usage();
367  exit(0);
368  }
369  }
370 
371  const char *verb = argv[myoptind];
372 
373  if (sensor == BMI055_NONE) {
374  bmi055::usage();
375  exit(0);
376  }
377 
378  /*
379  * Start/load the driver.
380  */
381  if (!strcmp(verb, "start")) {
382  bmi055::start(external_bus, rotation, sensor);
383  }
384 
385  /*
386  * Stop the driver.
387  */
388  if (!strcmp(verb, "stop")) {
389  bmi055::stop(external_bus, sensor);
390  }
391 
392  /*
393  * Print driver information.
394  */
395  if (!strcmp(verb, "info")) {
396  bmi055::info(external_bus, sensor);
397  }
398 
399  /*
400  * Print register information.
401  */
402  if (!strcmp(verb, "regdump")) {
403  bmi055::regdump(external_bus, sensor);
404  }
405 
406  if (!strcmp(verb, "testerror")) {
407  bmi055::testerror(external_bus, sensor);
408  }
409 
410  bmi055::usage();
411  exit(1);
412 }
BMI055_gyro * g_gyr_dev_ext
Definition: bmi055_main.cpp:52
void usage()
Prints info about the driver argument usage.
spi_mode_e
Definition: SPI.hpp:46
void regdump(bool, enum sensor_type)
Dump the register information.
Definition: I2C.hpp:51
void testerror(bool, enum sensor_type)
deliberately produce an error to test recovery
#define BMI055_DEVICE_PATH_ACCEL_EXT
void info(bool, enum sensor_type)
Print a little info about the driver.
Namespace encapsulating all device framework classes, functions and data.
Definition: CDev.cpp:47
void write_reg(unsigned reg, uint8_t value)
Write a register in the BMI055.
BMI055(const BMI055 &)
uint8_t read_reg(unsigned reg)
Read a register from the BMI055.
#define DIR_READ
Definition: bmp388_spi.cpp:46
sensor_type
Definition: bmi055_main.cpp:40
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
uint16_t read_reg16(unsigned reg)
#define warnx(...)
Definition: err.h:95
void start(bool, enum Rotation, enum sensor_type)
Start the driver.
Definition: bmi055_main.cpp:68
#define DIR_WRITE
Definition: bmp388_spi.cpp:47
const char * name
Definition: tests_main.c:58
#define BMI055_DEVICE_PATH_ACCEL
BMI055_gyro * g_gyr_dev_int
Definition: bmi055_main.cpp:51
#define errx(eval,...)
Definition: err.h:89
#define BMI055_DEVICE_PATH_GYRO
Definition: BMI055_gyro.hpp:40
#define OK
Definition: uavcan_main.cpp:71
void stop(bool, enum sensor_type)
#define BMI055_DEVICE_PATH_GYRO_EXT
Definition: BMI055_gyro.hpp:41
mode
Definition: vtol_type.h:76
__EXPORT int bmi055_main(int argc, char *argv[])
driver &#39;main&#39; command
BMI055_accel * g_acc_dev_ext
Definition: bmi055_main.cpp:50
BMI055_accel * g_acc_dev_int
Definition: bmi055_main.cpp:49