PX4 Firmware
PX4 Autopilot Software http://px4.io
mpu9250_main.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2019 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 <px4_platform_common/px4_config.h>
35 #include <px4_platform_common/getopt.h>
36 
37 #include "mpu9250.h"
38 
39 enum class MPU9250_BUS {
40  ALL = 0,
46 };
47 
48 namespace mpu9250
49 {
50 
51 // list of supported bus configurations
56  uint8_t busnum;
57  uint32_t address;
59 } bus_options[] = {
60 #if defined(USE_I2C)
61 # if defined(PX4_I2C_BUS_ONBOARD) && defined(PX4_I2C_OBDEV_MPU9250)
62  { MPU9250_BUS::I2C_INTERNAL, &MPU9250_I2C_interface, false, PX4_I2C_BUS_ONBOARD, PX4_I2C_OBDEV_MPU9250, nullptr },
63 # endif
64 # if defined(PX4_I2C_BUS_EXPANSION) && defined(PX4_I2C_OBDEV_MPU9250)
65  { MPU9250_BUS::I2C_EXTERNAL, &MPU9250_I2C_interface, false, PX4_I2C_BUS_EXPANSION, PX4_I2C_OBDEV_MPU9250, nullptr },
66 # endif
67 # if defined(PX4_I2C_BUS_EXPANSION1) && defined(PX4_I2C_OBDEV_MPU9250)
68  { MPU9250_BUS::I2C_EXTERNAL, &MPU9250_I2C_interface, false, PX4_I2C_BUS_EXPANSION1, PX4_I2C_OBDEV_MPU9250, nullptr },
69 # endif
70 # if defined(PX4_I2C_BUS_EXPANSION2) && defined(PX4_I2C_OBDEV_MPU9250)
71  { MPU9250_BUS::I2C_EXTERNAL, &MPU9250_I2C_interface, false, PX4_I2C_BUS_EXPANSION2, PX4_I2C_OBDEV_MPU9250, nullptr },
72 # endif
73 #endif
74 #if defined(PX4_SPI_BUS_SENSORS) && defined(PX4_SPIDEV_MPU)
75  { MPU9250_BUS::SPI_INTERNAL, &MPU9250_SPI_interface, true, PX4_SPI_BUS_SENSORS, PX4_SPIDEV_MPU, nullptr },
76 #endif
77 #if defined(PX4_SPI_BUS_SENSORS) && defined(PX4_SPIDEV_MPU2)
78  { MPU9250_BUS::SPI_INTERNAL2, &MPU9250_SPI_interface, true, PX4_SPI_BUS_SENSORS, PX4_SPIDEV_MPU2, nullptr },
79 #endif
80 #if defined(PX4_SPI_BUS_EXT) && defined(PX4_SPIDEV_EXT_MPU)
81  { MPU9250_BUS::SPI_EXTERNAL, &MPU9250_SPI_interface, true, PX4_SPI_BUS_EXT, PX4_SPIDEV_EXT_MPU, nullptr },
82 #endif
83 };
84 
85 // find a bus structure for a busid
87 {
88  for (mpu9250_bus_option &bus_option : bus_options) {
89  if ((busid == MPU9250_BUS::ALL ||
90  busid == bus_option.busid) && bus_option.dev != nullptr) {
91 
92  return &bus_option;
93  }
94  }
95 
96  return nullptr;
97 }
98 
99 static bool start_bus(mpu9250_bus_option &bus, enum Rotation rotation)
100 {
101  device::Device *interface = bus.interface_constructor(bus.busnum, bus.address);
102 
103  if ((interface == nullptr) || (interface->init() != PX4_OK)) {
104  PX4_WARN("no device on bus %u", (unsigned)bus.busid);
105  delete interface;
106  return false;
107  }
108 
109  device::Device *mag_interface = nullptr;
110 
111 #ifdef USE_I2C
112 
113  // For i2c interfaces, connect to the magnetomer directly
114  if ((bus.busid == MPU9250_BUS::I2C_INTERNAL) || (bus.busid == MPU9250_BUS::I2C_EXTERNAL)) {
115  mag_interface = AK8963_I2C_interface(bus.busnum);
116  }
117 
118 #endif // USE_I2C
119 
120  MPU9250 *dev = new MPU9250(interface, mag_interface, rotation);
121 
122  if (dev == nullptr || (dev->init() != PX4_OK)) {
123  PX4_ERR("driver start failed");
124  delete dev;
125  delete interface;
126  delete mag_interface;
127  return false;
128  }
129 
130  bus.dev = dev;
131 
132  return true;
133 }
134 
135 static int start(MPU9250_BUS busid, enum Rotation rotation)
136 {
137  for (mpu9250_bus_option &bus_option : bus_options) {
138  if (bus_option.dev != nullptr) {
139  // this device is already started
140  PX4_WARN("already started");
141  continue;
142  }
143 
144  if (busid != MPU9250_BUS::ALL && bus_option.busid != busid) {
145  // not the one that is asked for
146  continue;
147  }
148 
149  if (start_bus(bus_option, rotation)) {
150  return PX4_OK;
151  }
152  }
153 
154  return PX4_ERROR;
155 }
156 
157 static int stop(MPU9250_BUS busid)
158 {
159  mpu9250_bus_option *bus = find_bus(busid);
160 
161  if (bus != nullptr && bus->dev != nullptr) {
162  delete bus->dev;
163  bus->dev = nullptr;
164 
165  } else {
166  PX4_WARN("driver not running");
167  return PX4_ERROR;
168  }
169 
170  return PX4_OK;
171 }
172 
173 static int status(MPU9250_BUS busid)
174 {
175  mpu9250_bus_option *bus = find_bus(busid);
176 
177  if (bus != nullptr && bus->dev != nullptr) {
178  bus->dev->print_info();
179  return PX4_OK;
180  }
181 
182  PX4_WARN("driver not running");
183  return PX4_ERROR;
184 }
185 
186 static int usage()
187 {
188  PX4_INFO("missing command: try 'start', 'stop', 'status'");
189  PX4_INFO("options:");
190  PX4_INFO(" -X (i2c external bus)");
191  PX4_INFO(" -I (i2c internal bus)");
192  PX4_INFO(" -s (spi internal bus)");
193  PX4_INFO(" -S (spi external bus)");
194  PX4_INFO(" -t (spi internal bus, 2nd instance)");
195  PX4_INFO(" -R rotation");
196 
197  return 0;
198 }
199 
200 } // namespace
201 
202 extern "C" int mpu9250_main(int argc, char *argv[])
203 {
204  int myoptind = 1;
205  int ch;
206  const char *myoptarg = nullptr;
207 
209  enum Rotation rotation = ROTATION_NONE;
210 
211  while ((ch = px4_getopt(argc, argv, "XISstMR:", &myoptind, &myoptarg)) != EOF) {
212  switch (ch) {
213  case 'X':
215  break;
216 
217  case 'I':
219  break;
220 
221  case 'S':
223  break;
224 
225  case 's':
227  break;
228 
229  case 't':
231  break;
232 
233  case 'R':
234  rotation = (enum Rotation)atoi(myoptarg);
235  break;
236 
237  default:
238  return mpu9250::usage();
239  }
240  }
241 
242  if (myoptind >= argc) {
243  return mpu9250::usage();
244  }
245 
246  const char *verb = argv[myoptind];
247 
248  if (!strcmp(verb, "start")) {
249  return mpu9250::start(busid, rotation);
250 
251  } else if (!strcmp(verb, "stop")) {
252  return mpu9250::stop(busid);
253 
254  } else if (!strcmp(verb, "status")) {
255  return mpu9250::status(busid);
256  }
257 
258  return mpu9250::usage();
259 }
int mpu9250_main(int argc, char *argv[])
static int stop(MPU9250_BUS busid)
void usage(const char *reason)
Print the correct usage.
Definition: Commander.cpp:4238
device::Device * AK8963_I2C_interface(int bus)
static bool start_bus(mpu9250_bus_option &bus, enum Rotation rotation)
void print_info()
Diagnostics - print some basic information about the driver.
Definition: mpu9250.cpp:743
static void stop()
Definition: dataman.cpp:1491
MPU9250_constructor interface_constructor
virtual int init()
Definition: mpu9250.cpp:104
device::Device * MPU9250_I2C_interface(int bus, uint32_t address)
device::Device * MPU9250_SPI_interface(int bus, uint32_t cs)
Definition: mpu9250_spi.cpp:83
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
static int start(MPU9250_BUS busid, enum Rotation rotation)
static int status(MPU9250_BUS busid)
static int start()
Definition: dataman.cpp:1452
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
static struct mpu9250_bus_option * find_bus(MPU9250_BUS busid)
MPU9250_BUS
device::Device *(* MPU9250_constructor)(int, uint32_t)
Definition: mpu9250.h:222
struct mpu9250::mpu9250_bus_option bus_options[]
static int usage()