APM:Libraries
board_drivers.cpp
Go to the documentation of this file.
1 /*
2  This program is free software: you can redistribute it and/or modify
3  it under the terms of the GNU General Public License as published by
4  the Free Software Foundation, either version 3 of the License, or
5  (at your option) any later version.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 /*
16  * AP_BoardConfig - px4 driver loading and setup
17  */
18 
19 #include <AP_HAL/AP_HAL.h>
20 #include "AP_BoardConfig.h"
21 #include <stdio.h>
22 
23 extern const AP_HAL::HAL& hal;
24 
25 #if AP_FEATURE_SAFETY_BUTTON
26 /*
27  init safety state
28  */
30 {
31  if (state.safety_enable.get() == 0) {
32  hal.rcout->force_safety_off();
34  // wait until safety has been turned off
35  uint8_t count = 20;
36  while (hal.util->safety_switch_state() != AP_HAL::Util::SAFETY_ARMED && count--) {
37  hal.scheduler->delay(20);
38  }
39  }
40 }
41 #endif
42 
43 
44 #if AP_FEATURE_BOARD_DETECT
45 
47 
48 #if defined(CONFIG_ARCH_BOARD_PX4FMU_V4)
49 extern "C" {
50  int fmu_main(int, char **);
51 };
52 #endif
53 
55 {
56 #if defined(CONFIG_ARCH_BOARD_PX4FMU_V4)
57  /*
58  this works around an issue with some FMUv4 hardware (eg. copies
59  of the Pixracer) which have incorrect components leading to
60  sensor brownout on boot
61  */
62  if (px4_start_driver(fmu_main, "fmu", "sensor_reset 20")) {
63  printf("FMUv4 sensor reset complete\n");
64  }
65 #endif
66 
67  if (state.board_type == PX4_BOARD_OLDDRIVERS) {
68  printf("Old drivers no longer supported\n");
69  state.board_type = PX4_BOARD_AUTO;
70  }
71 
72  // run board auto-detection
74 
75  if (state.board_type == PX4_BOARD_PH2SLIM ||
76  state.board_type == PX4_BOARD_PIXHAWK2) {
77  _imu_target_temperature.set_default(45);
78  if (_imu_target_temperature.get() < 0) {
79  // don't allow a value of -1 on the cube, or it could cook
80  // the IMU
82  }
83  }
84 
85  px4_configured_board = (enum px4_board_type)state.board_type.get();
86 
87  switch (px4_configured_board) {
88  case PX4_BOARD_PX4V1:
89  case PX4_BOARD_PIXHAWK:
90  case PX4_BOARD_PIXHAWK2:
91  case PX4_BOARD_SP01:
92  case PX4_BOARD_PIXRACER:
93  case PX4_BOARD_PHMINI:
94  case PX4_BOARD_AUAV21:
95  case PX4_BOARD_PH2SLIM:
96  case VRX_BOARD_BRAIN51:
97  case VRX_BOARD_BRAIN52:
98  case VRX_BOARD_BRAIN52E:
99  case VRX_BOARD_UBRAIN51:
100  case VRX_BOARD_UBRAIN52:
101  case VRX_BOARD_CORE10:
102  case VRX_BOARD_BRAIN54:
103  case PX4_BOARD_AEROFC:
105  case PX4_BOARD_PCNC1:
106  case PX4_BOARD_MINDPXV2:
107  break;
108  default:
109  sensor_config_error("Unknown board type");
110  break;
111  }
112 }
113 
114 /*
115  check a SPI device for a register value
116  */
117 bool AP_BoardConfig::spi_check_register(const char *devname, uint8_t regnum, uint8_t value, uint8_t read_flag)
118 {
119  auto dev = hal.spi->get_device(devname);
120  if (!dev) {
121  hal.console->printf("%s: no device\n", devname);
122  return false;
123  }
124  dev->set_read_flag(read_flag);
126  return false;
127  }
128  uint8_t v;
129  if (!dev->read_registers(regnum, &v, 1)) {
130  hal.console->printf("%s: reg %02x read fail\n", devname, (unsigned)regnum);
131  dev->get_semaphore()->give();
132  return false;
133  }
134  dev->get_semaphore()->give();
135  hal.console->printf("%s: reg %02x expected:%02x got:%02x\n", devname, (unsigned)regnum, (unsigned)value, (unsigned)v);
136  return v == value;
137 }
138 
139 #define MPUREG_WHOAMI 0x75
140 #define MPU_WHOAMI_MPU60X0 0x68
141 #define MPU_WHOAMI_MPU9250 0x71
142 #define MPU_WHOAMI_ICM20608 0xaf
143 #define MPU_WHOAMI_ICM20602 0x12
144 
145 #define LSMREG_WHOAMI 0x0f
146 #define LSM_WHOAMI_LSM303D 0x49
147 
148 /*
149  validation of the board type
150  */
152 {
153  /* some boards can be damaged by the user setting the wrong board
154  type. The key one is the cube which has a heater which can
155  cook the IMUs if the user uses an old paramater file. We
156  override the board type for that specific case
157  */
158 #if defined(CONFIG_ARCH_BOARD_PX4FMU_V2) || defined(HAL_CHIBIOS_ARCH_FMUV3)
159  if (state.board_type == PX4_BOARD_PIXHAWK &&
165  // Pixhawk2 has LSM303D and MPUxxxx on external bus. If we
166  // detect those, then force PIXHAWK2, even if the user has
167  // configured for PIXHAWK1
168 #if !defined(CONFIG_ARCH_BOARD_PX4FMU_V3) && !defined(HAL_CHIBIOS_ARCH_FMUV3)
169  // force user to load the right firmware
170  sensor_config_error("Pixhawk2 requires FMUv3 firmware");
171 #endif
172  state.board_type.set(PX4_BOARD_PIXHAWK2);
173  hal.console->printf("Forced PIXHAWK2\n");
174  }
175 #endif
176 
177 #if defined(CONFIG_ARCH_BOARD_PX4FMU_V4PRO)
178  // Nothing to do for the moment
179 #endif
180 }
181 
182 /*
183  auto-detect board type
184  */
186 {
187  if (state.board_type != PX4_BOARD_AUTO) {
189  // user has chosen a board type
190  return;
191  }
192 
193 #if defined(CONFIG_ARCH_BOARD_PX4FMU_V1)
194  // only one choice
195  state.board_type.set(PX4_BOARD_PX4V1);
196  hal.console->printf("Detected PX4v1\n");
197 
198 #elif defined(CONFIG_ARCH_BOARD_PX4FMU_V2) || defined(HAL_CHIBIOS_ARCH_FMUV3)
199  if ((spi_check_register("mpu6000_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU60X0) ||
206  // Pixhawk2 has LSM303D and MPUxxxx on external bus
207  state.board_type.set(PX4_BOARD_PIXHAWK2);
208  hal.console->printf("Detected PIXHAWK2\n");
209  } else if ((spi_check_register("icm20608-am", MPUREG_WHOAMI, MPU_WHOAMI_ICM20608) ||
212  // PHMINI has an ICM20608 and MPU9250 on sensor bus
213  state.board_type.set(PX4_BOARD_PHMINI);
214  hal.console->printf("Detected PixhawkMini\n");
215  } else if (spi_check_register("lsm9ds0_am", LSMREG_WHOAMI, LSM_WHOAMI_LSM303D) &&
220 
221  // classic or upgraded Pixhawk1
222  state.board_type.set(PX4_BOARD_PIXHAWK);
223  hal.console->printf("Detected Pixhawk\n");
224  } else {
225  sensor_config_error("Unable to detect board type");
226  }
227 #elif defined(CONFIG_ARCH_BOARD_PX4FMU_V4) || defined(HAL_CHIBIOS_ARCH_FMUV4)
228  // only one choice
229  state.board_type.set_and_notify(PX4_BOARD_PIXRACER);
230  hal.console->printf("Detected Pixracer\n");
231 #elif defined(HAL_CHIBIOS_ARCH_MINDPXV2)
232  // only one choice
233  state.board_type.set_and_notify(PX4_BOARD_MINDPXV2);
234  hal.console->printf("Detected MindPX-V2\n");
235 #elif defined(CONFIG_ARCH_BOARD_PX4FMU_V4PRO)
236  // only one choice
237  state.board_type.set_and_notify(PX4_BOARD_PIXHAWK_PRO);
238  hal.console->printf("Detected Pixhawk Pro\n");
239 #elif defined(CONFIG_ARCH_BOARD_AEROFC_V1)
240  state.board_type.set_and_notify(PX4_BOARD_AEROFC);
241  hal.console->printf("Detected Aero FC\n");
242 #elif defined(CONFIG_ARCH_BOARD_VRBRAIN_V51)
243  state.board_type.set_and_notify(VRX_BOARD_BRAIN51);
244  hal.console->printf("Detected VR Brain 5.1\n");
245 #elif defined(CONFIG_ARCH_BOARD_VRBRAIN_V52)
246  state.board_type.set_and_notify(VRX_BOARD_BRAIN52);
247  hal.console->printf("Detected VR Brain 5.2\n");
248 #elif defined(CONFIG_ARCH_BOARD_VRBRAIN_V52E)
249  state.board_type.set_and_notify(VRX_BOARD_BRAIN52E);
250  hal.console->printf("Detected VR Brain 5.2E\n");
251 #elif defined(CONFIG_ARCH_BOARD_VRUBRAIN_V51)
252  state.board_type.set_and_notify(VRX_BOARD_UBRAIN51);
253  hal.console->printf("Detected VR Micro Brain 5.1\n");
254 #elif defined(CONFIG_ARCH_BOARD_VRUBRAIN_V52)
255  state.board_type.set_and_notify(VRX_BOARD_UBRAIN52);
256  hal.console->printf("Detected VR Micro Brain 5.2\n");
257 #elif defined(CONFIG_ARCH_BOARD_VRCORE_V10)
258  state.board_type.set_and_notify(VRX_BOARD_CORE10);
259  hal.console->printf("Detected VR Core 1.0\n");
260 #elif defined(CONFIG_ARCH_BOARD_VRBRAIN_V54)
261  state.board_type.set_and_notify(VRX_BOARD_BRAIN54);
262  hal.console->printf("Detected VR Brain 5.4\n");
263 #endif
264 
265 }
266 
267 #endif // AP_FEATURE_BOARD_DETECT
268 
269 /*
270  setup flow control on UARTs
271  */
273 {
274 #if AP_FEATURE_RTSCTS
276  if (hal.uartD != nullptr) {
278  }
279 #endif
280 }
281 
282 /*
283  setup SBUS
284  */
286 {
287 #if AP_FEATURE_SBUS_OUT
288  if (state.sbus_out_rate.get() >= 1) {
289  static const struct {
290  uint8_t value;
291  uint16_t rate;
292  } rates[] = {
293  { 1, 50 },
294  { 2, 75 },
295  { 3, 100 },
296  { 4, 150 },
297  { 5, 200 },
298  { 6, 250 },
299  { 7, 300 }
300  };
301  uint16_t rate = 300;
302  for (uint8_t i=0; i<ARRAY_SIZE(rates); i++) {
303  if (rates[i].value == state.sbus_out_rate) {
304  rate = rates[i].rate;
305  }
306  }
307  if (!hal.rcout->enable_px4io_sbus_out(rate)) {
308  hal.console->printf("Failed to enable SBUS out\n");
309  }
310  }
311 #endif
312 }
313 
314 
315 /*
316  setup peripherals and drivers
317  */
319 {
320 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4 || CONFIG_HAL_BOARD == HAL_BOARD_VRBRAIN
322  px4_setup_pwm();
324 #elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
325  // init needs to be done after boardconfig is read so parameters are set
326  hal.gpio->init();
327  hal.rcin->init();
328  hal.rcout->init();
329 #endif
332 #if AP_FEATURE_BOARD_DETECT
334 #endif
335 }
336 
virtual void init()=0
int printf(const char *fmt,...)
Definition: stdio.c:113
#define MPUREG_WHOAMI
virtual void force_safety_no_wait(void)
Definition: RCOutput.h:103
void px4_setup_pwm(void)
Definition: px4_drivers.cpp:47
virtual void force_safety_off(void)
Definition: RCOutput.h:98
void board_init_safety(void)
AP_HAL::UARTDriver * console
Definition: HAL.h:110
AP_Int8 _imu_target_temperature
virtual AP_HAL::Semaphore * get_semaphore()=0
AP_HAL::Util * util
Definition: HAL.h:115
void validate_board_type(void)
#define HAL_SEMAPHORE_BLOCK_FOREVER
Definition: Semaphores.h:5
virtual bool take(uint32_t timeout_ms) WARN_IF_UNUSED=0
const AP_HAL::HAL & hal
Definition: AC_PID_test.cpp:14
struct AP_BoardConfig::@14 state
#define MPU_WHOAMI_MPU60X0
void board_setup_uart(void)
static enum px4_board_type px4_configured_board
int fmu_main(int, char **)
void px4_setup_safety_mask(void)
Definition: px4_drivers.cpp:96
virtual void delay(uint16_t ms)=0
AP_HAL::UARTDriver * uartC
Definition: HAL.h:102
bool spi_check_register(const char *devname, uint8_t regnum, uint8_t value, uint8_t read_flag=0x80)
virtual void init()=0
virtual void printf(const char *,...) FMT_PRINTF(2
Definition: BetterStream.cpp:5
void board_autodetect(void)
virtual OwnPtr< SPIDevice > get_device(const char *name)
Definition: SPIDevice.h:68
void board_setup(void)
static AP_HAL::OwnPtr< AP_HAL::Device > dev
Definition: ICM20789.cpp:16
#define MPU_WHOAMI_MPU9250
#define MPU_WHOAMI_ICM20608
static bool px4_start_driver(main_fn_t main_function, const char *name, const char *arguments)
virtual bool enable_px4io_sbus_out(uint16_t rate_hz)
Definition: RCOutput.h:126
AP_HAL::UARTDriver * uartD
Definition: HAL.h:103
virtual enum safety_state safety_switch_state(void)
Definition: Util.h:42
void board_setup_sbus(void)
virtual void set_flow_control(enum flow_control flow_control_setting)
Definition: UARTDriver.h:50
virtual bool give()=0
void px4_setup_peripherals(void)
float v
Definition: Printf.cpp:15
AP_HAL::SPIDeviceManager * spi
Definition: HAL.h:107
#define ARRAY_SIZE(_arr)
Definition: AP_Common.h:80
#define MPU_WHOAMI_ICM20602
virtual void init()=0
void set_read_flag(uint8_t flag)
Definition: Device.h:221
#define LSMREG_WHOAMI
AP_HAL::GPIO * gpio
Definition: HAL.h:111
AP_HAL::RCOutput * rcout
Definition: HAL.h:113
void board_setup_drivers(void)
float value
bool read_registers(uint8_t first_reg, uint8_t *recv, uint32_t recv_len)
Definition: Device.h:113
AP_HAL::RCInput * rcin
Definition: HAL.h:112
AP_HAL::Scheduler * scheduler
Definition: HAL.h:114
#define LSM_WHOAMI_LSM303D
static void sensor_config_error(const char *reason)