Path: blob/master/libraries/AP_BoardConfig/board_drivers.cpp
9420 views
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/14/*15* AP_BoardConfig - driver loading and setup16*/171819#include <AP_HAL/AP_HAL.h>20#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS21#include <hal.h>22#endif23#include "AP_BoardConfig.h"24#include <GCS_MAVLink/GCS.h>25#include <AP_Math/crc.h>26#include <stdio.h>2728extern const AP_HAL::HAL& hal;2930/*31init safety state32*/33void AP_BoardConfig::board_init_safety()34{35bool force_safety_off = (state.safety_enable.get() == 0);36if (!force_safety_off && hal.util->was_watchdog_safety_off()) {37GCS_SEND_TEXT(MAV_SEVERITY_INFO, "Forcing safety off for watchdog");38force_safety_off = true;39}40if (force_safety_off) {41hal.rcout->force_safety_off();42// wait until safety has been turned off43uint8_t count = 20;44while (hal.util->safety_switch_state() != AP_HAL::Util::SAFETY_ARMED && count--) {45hal.scheduler->delay(20);46}47}48}4950/*51init debug pins. We set debug pins as input if BRD_OPTIONS bit for debug enable is not set52this prevents possible ESD issues on the debug pins53*/54void AP_BoardConfig::board_init_debug()55{56#if !defined(HAL_BUILD_AP_PERIPH) && !defined(HAL_DEBUG_BUILD)57if ((_options & BOARD_OPTION_DEBUG_ENABLE) == 0) {58#ifdef HAL_GPIO_PIN_JTCK_SWCLK59palSetLineMode(HAL_GPIO_PIN_JTCK_SWCLK, PAL_MODE_INPUT);60#endif61#ifdef HAL_GPIO_PIN_JTMS_SWDIO62palSetLineMode(HAL_GPIO_PIN_JTMS_SWDIO, PAL_MODE_INPUT);63#endif64}65#endif // HAL_BUILD_AP_PERIPH && HAL_DEBUG_BUILD66}676869#if AP_FEATURE_BOARD_DETECT7071AP_BoardConfig::px4_board_type AP_BoardConfig::px4_configured_board;7273void AP_BoardConfig::board_setup_drivers(void)74{75if (state.board_type == PX4_BOARD_OLDDRIVERS) {76printf("Old drivers no longer supported\n");77state.board_type.set(PX4_BOARD_AUTO);78}7980// run board auto-detection81board_autodetect();8283px4_configured_board = (enum px4_board_type)state.board_type.get();8485switch (px4_configured_board) {86case PX4_BOARD_PX4V1:87case PX4_BOARD_PIXHAWK:88case PX4_BOARD_PIXHAWK2:89case PX4_BOARD_FMUV6:90case PX4_BOARD_PHMINI:91case PX4_BOARD_AUAV21:92case PX4_BOARD_PH2SLIM:93case PX4_BOARD_AEROFC:94case FMUV6_BOARD_HOLYBRO_6X:95case FMUV6_BOARD_HOLYBRO_6X_REV6:96case FMUV6_BOARD_HOLYBRO_6X_45686:97case FMUV6_BOARD_CUAV_6X:98break;99default:100config_error("Unknown board type %u", px4_configured_board);101break;102}103}104105#define SPI_PROBE_DEBUG 0106107/*108check a SPI device for a register value109*/110bool AP_BoardConfig::spi_check_register(const char *devname, uint8_t regnum, uint8_t value, uint8_t read_flag)111{112auto dev = hal.spi->get_device(devname);113if (!dev) {114#if SPI_PROBE_DEBUG115hal.console->printf("%s: no device\n", devname);116#endif117return false;118}119dev->set_read_flag(read_flag);120WITH_SEMAPHORE(dev->get_semaphore());121dev->set_speed(AP_HAL::Device::SPEED_LOW);122uint8_t v;123if (!dev->read_registers(regnum, &v, 1)) {124#if SPI_PROBE_DEBUG125hal.console->printf("%s: reg %02x read fail\n", devname, (unsigned)regnum);126#endif127return false;128}129#if SPI_PROBE_DEBUG130hal.console->printf("%s: reg %02x expected:%02x got:%02x\n", devname, (unsigned)regnum, (unsigned)value, (unsigned)v);131#endif132return v == value;133}134135136#define INV2REG_BANK_SEL 0x7F137/*138check a SPI device for a register value139*/140bool AP_BoardConfig::spi_check_register_inv2(const char *devname, uint8_t regnum, uint8_t value, uint8_t read_flag)141{142auto dev = hal.spi->get_device(devname);143if (!dev) {144#if SPI_PROBE_DEBUG145hal.console->printf("%s: no device\n", devname);146#endif147return false;148}149dev->set_read_flag(read_flag);150WITH_SEMAPHORE(dev->get_semaphore());151dev->set_speed(AP_HAL::Device::SPEED_LOW);152uint8_t v;153// select bank 0 for who am i154dev->write_register(INV2REG_BANK_SEL, 0, false);155if (!dev->read_registers(regnum, &v, 1)) {156#if SPI_PROBE_DEBUG157hal.console->printf("%s: reg %02x read fail\n", devname, (unsigned)regnum);158#endif159return false;160}161#if SPI_PROBE_DEBUG162hal.console->printf("%s: reg %02x expected:%02x got:%02x\n", devname, (unsigned)regnum, (unsigned)value, (unsigned)v);163#endif164return v == value;165}166167#if defined(HAL_VALIDATE_BOARD)168bool AP_BoardConfig::check_ms5611(const char* devname) {169auto dev = hal.spi->get_device(devname);170if (!dev) {171#if SPI_PROBE_DEBUG172hal.console->printf("%s: no device\n", devname);173#endif174return false;175}176177AP_HAL::Semaphore *dev_sem = dev->get_semaphore();178179if (!dev_sem) {180return false;181}182WITH_SEMAPHORE(dev_sem);183184static const uint8_t CMD_MS56XX_RESET = 0x1E;185static const uint8_t CMD_MS56XX_PROM = 0xA0;186187dev->transfer(&CMD_MS56XX_RESET, 1, nullptr, 0);188hal.scheduler->delay(4);189190uint16_t prom[8];191bool all_zero = true;192for (uint8_t i = 0; i < 8; i++) {193const uint8_t reg = CMD_MS56XX_PROM + (i << 1);194uint8_t val[2];195if (!dev->transfer(®, 1, val, sizeof(val))) {196#if SPI_PROBE_DEBUG197hal.console->printf("%s: transfer fail\n", devname);198#endif199return false;200}201prom[i] = (val[0] << 8) | val[1];202203if (prom[i] != 0) {204all_zero = false;205}206}207208uint16_t crc_read = prom[7]&0xf;209prom[7] &= 0xff00;210211if (crc_read != crc_crc4(prom) || all_zero) {212#if SPI_PROBE_DEBUG213hal.console->printf("%s: crc fail\n", devname);214#endif215return false;216}217218#if SPI_PROBE_DEBUG219hal.console->printf("%s: found successfully\n", devname);220#endif221222return true;223}224#endif // HAL_VALIDATE_BOARD225226#define MPUREG_WHOAMI 0x75227#define MPU_WHOAMI_MPU60X0 0x68228#define MPU_WHOAMI_MPU9250 0x71229#define MPU_WHOAMI_ICM20608 0xaf230#define MPU_WHOAMI_ICM20602 0x12231232#define LSMREG_WHOAMI 0x0f233#define LSM_WHOAMI_LSM303D 0x49234#define LSM_WHOAMI_L3GD20 0xd4235236#define INV2REG_WHOAMI 0x00237238#define INV2_WHOAMI_ICM20948 0xEA239#define INV2_WHOAMI_ICM20649 0xE1240241#define INV3REG_WHOAMI 0x75242#define INV3REG_456_WHOAMI 0x72243244#define INV3_WHOAMI_ICM42688 0x47245#define INV3_WHOAMI_ICM42670 0x67246#define INV3_WHOAMI_ICM45686 0xE9247#define INV3_WHOAMI_IIM42652 0x6f248249/*250validation of the board type251*/252void AP_BoardConfig::validate_board_type(void)253{254/* some boards can be damaged by the user setting the wrong board255type. The key one is the cube which has a heater which can256cook the IMUs if the user uses an old paramater file. We257override the board type for that specific case258*/259#if defined(HAL_CHIBIOS_ARCH_FMUV3)260if (state.board_type == PX4_BOARD_PIXHAWK &&261(spi_check_register("mpu6000_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU60X0) ||262spi_check_register("mpu9250_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU9250) ||263spi_check_register("icm20608", MPUREG_WHOAMI, MPU_WHOAMI_ICM20608) ||264spi_check_register("icm20608_ext", MPUREG_WHOAMI, MPU_WHOAMI_ICM20602) ||265spi_check_register("icm20602_ext", MPUREG_WHOAMI, MPU_WHOAMI_ICM20602)) &&266(spi_check_register("lsm9ds0_ext_am", LSMREG_WHOAMI, LSM_WHOAMI_LSM303D) ||267spi_check_register_inv2("icm20948_ext", INV2REG_WHOAMI, INV2_WHOAMI_ICM20948))) {268// Pixhawk2 has LSM303D and MPUxxxx on external bus. If we269// detect those, then force PIXHAWK2, even if the user has270// configured for PIXHAWK1271#if !defined(HAL_CHIBIOS_ARCH_FMUV3)272// force user to load the right firmware273config_error("Pixhawk2 requires FMUv3 firmware");274#endif275state.board_type.set(PX4_BOARD_PIXHAWK2);276DEV_PRINTF("Forced PIXHAWK2\n");277}278#endif279}280281/*282auto-detect board type283*/284void AP_BoardConfig::board_autodetect(void)285{286#if defined(HAL_VALIDATE_BOARD)287if((_options & SKIP_BOARD_VALIDATION) == 0) {288const char* errored_check = HAL_VALIDATE_BOARD;289if (errored_check == nullptr) {290return;291} else {292config_error("Board Validation %s Failed", errored_check);293return;294}295}296#endif297298if (state.board_type != PX4_BOARD_AUTO) {299validate_board_type();300// user has chosen a board type301return;302}303304#if defined(HAL_CHIBIOS_ARCH_FMUV3)305if ((spi_check_register("mpu6000_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU60X0) ||306spi_check_register("mpu6000_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU60X0) ||307spi_check_register("mpu9250_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU60X0) ||308spi_check_register("mpu9250_ext", MPUREG_WHOAMI, MPU_WHOAMI_MPU9250) ||309spi_check_register("icm20608_ext", MPUREG_WHOAMI, MPU_WHOAMI_ICM20608) ||310spi_check_register("icm20608_ext", MPUREG_WHOAMI, MPU_WHOAMI_ICM20602) ||311spi_check_register("icm20602_ext", MPUREG_WHOAMI, MPU_WHOAMI_ICM20602)) &&312(spi_check_register("lsm9ds0_ext_am", LSMREG_WHOAMI, LSM_WHOAMI_LSM303D) ||313spi_check_register_inv2("icm20948_ext", INV2REG_WHOAMI, INV2_WHOAMI_ICM20948))) {314// Pixhawk2 has LSM303D and MPUxxxx on external bus315state.board_type.set(PX4_BOARD_PIXHAWK2);316DEV_PRINTF("Detected PIXHAWK2\n");317} else if ((spi_check_register("icm20608-am", MPUREG_WHOAMI, MPU_WHOAMI_ICM20608) ||318spi_check_register("icm20608-am", MPUREG_WHOAMI, MPU_WHOAMI_ICM20602)) &&319spi_check_register("mpu9250", MPUREG_WHOAMI, MPU_WHOAMI_MPU9250)) {320// PHMINI has an ICM20608 and MPU9250 on sensor bus321state.board_type.set(PX4_BOARD_PHMINI);322DEV_PRINTF("Detected PixhawkMini\n");323} else if (spi_check_register("lsm9ds0_am", LSMREG_WHOAMI, LSM_WHOAMI_LSM303D) &&324(spi_check_register("mpu6000", MPUREG_WHOAMI, MPU_WHOAMI_MPU60X0) ||325spi_check_register("icm20608", MPUREG_WHOAMI, MPU_WHOAMI_ICM20608) ||326spi_check_register("icm20608", MPUREG_WHOAMI, MPU_WHOAMI_ICM20602) ||327spi_check_register("mpu9250", MPUREG_WHOAMI, MPU_WHOAMI_MPU9250))) {328329// classic or upgraded Pixhawk1330state.board_type.set(PX4_BOARD_PIXHAWK);331DEV_PRINTF("Detected Pixhawk\n");332} else {333config_error("Unable to detect board type");334}335#elif defined(HAL_CHIBIOS_ARCH_FMUV6)336detect_fmuv6_variant();337#endif338339}340341#endif // AP_FEATURE_BOARD_DETECT342343/*344setup flow control on UARTs345*/346void AP_BoardConfig::board_setup_uart()347{348#if AP_FEATURE_RTSCTS349#ifdef HAL_HAVE_RTSCTS_SERIAL1350if (hal.serial(1) != nullptr) {351hal.serial(1)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[1].get());352}353#endif354#ifdef HAL_HAVE_RTSCTS_SERIAL2355if (hal.serial(2) != nullptr) {356hal.serial(2)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[2].get());357}358#endif359#ifdef HAL_HAVE_RTSCTS_SERIAL3360if (hal.serial(3) != nullptr) {361hal.serial(3)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[3].get());362}363#endif364#ifdef HAL_HAVE_RTSCTS_SERIAL4365if (hal.serial(4) != nullptr) {366hal.serial(4)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[4].get());367}368#endif369#ifdef HAL_HAVE_RTSCTS_SERIAL5370if (hal.serial(5) != nullptr) {371hal.serial(5)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[5].get());372}373#endif374#ifdef HAL_HAVE_RTSCTS_SERIAL6375if (hal.serial(6) != nullptr) {376hal.serial(6)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[6].get());377}378#endif379#ifdef HAL_HAVE_RTSCTS_SERIAL7380if (hal.serial(7) != nullptr) {381hal.serial(7)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[7].get());382}383#endif384#ifdef HAL_HAVE_RTSCTS_SERIAL8385if (hal.serial(8) != nullptr) {386hal.serial(8)->set_flow_control((AP_HAL::UARTDriver::flow_control)state.ser_rtscts[8].get());387}388#endif389#endif390}391392/*393setup SBUS394*/395void AP_BoardConfig::board_setup_sbus(void)396{397#if AP_FEATURE_SBUS_OUT398if (state.sbus_out_rate.get() >= 1) {399static const struct {400uint8_t value;401uint16_t rate;402} rates[] = {403{ 1, 50 },404{ 2, 75 },405{ 3, 100 },406{ 4, 150 },407{ 5, 200 },408{ 6, 250 },409{ 7, 300 }410};411uint16_t rate = 300;412for (uint8_t i=0; i<ARRAY_SIZE(rates); i++) {413if (rates[i].value == state.sbus_out_rate) {414rate = rates[i].rate;415}416}417if (!hal.rcout->enable_px4io_sbus_out(rate)) {418hal.console->printf("Failed to enable SBUS out\n");419}420}421#endif422}423424425/*426setup peripherals and drivers427*/428void AP_BoardConfig::board_setup()429{430#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS431// init needs to be done after boardconfig is read so parameters are set432hal.gpio->init();433hal.rcin->init();434hal.rcout->init();435#endif436437#ifdef HAL_GPIO_PWM_VOLT_PIN438if (_pwm_volt_sel == 0) {439hal.gpio->write(HAL_GPIO_PWM_VOLT_PIN, HAL_GPIO_PWM_VOLT_3v3); //set pin for 3.3V PWM Output440} else if (_pwm_volt_sel == 1) {441hal.gpio->write(HAL_GPIO_PWM_VOLT_PIN, !HAL_GPIO_PWM_VOLT_3v3); //set pin for 5V PWM Output442}443#endif444board_setup_uart();445board_setup_sbus();446#if AP_FEATURE_BOARD_DETECT447board_setup_drivers();448#endif449}450451452#ifdef HAL_CHIBIOS_ARCH_FMUV6453454#define BMI088REG_CHIPID 0x00455#define CHIPID_BMI088_G 0x0F456457/*458detect which FMUV6 variant we are running on459*/460void AP_BoardConfig::detect_fmuv6_variant()461{462if (((spi_check_register_inv2("icm20649", INV2REG_WHOAMI, INV2_WHOAMI_ICM20649) ||463spi_check_register("bmi088_g", BMI088REG_CHIPID, CHIPID_BMI088_G)) && // alternative config464spi_check_register("icm42688", INV3REG_WHOAMI, INV3_WHOAMI_ICM42688) &&465spi_check_register("icm42670", INV3REG_WHOAMI, INV3_WHOAMI_ICM42670))) {466state.board_type.set_and_notify(FMUV6_BOARD_HOLYBRO_6X);467DEV_PRINTF("Detected Holybro 6X\n");468} else if ((spi_check_register_inv2("icm20649_2", INV2REG_WHOAMI, INV2_WHOAMI_ICM20649) &&469spi_check_register("icm42688", INV3REG_WHOAMI, INV3_WHOAMI_ICM42688) &&470spi_check_register("bmi088_g", BMI088REG_CHIPID, CHIPID_BMI088_G))) {471state.board_type.set_and_notify(FMUV6_BOARD_CUAV_6X);472DEV_PRINTF("Detected CUAV 6X\n");473AP_Param::load_defaults_file("@ROMFS/param/CUAV_V6X_defaults.parm", false);474} else if (spi_check_register("icm45686-1", INV3REG_456_WHOAMI, INV3_WHOAMI_ICM45686) &&475spi_check_register("icm45686-2", INV3REG_456_WHOAMI, INV3_WHOAMI_ICM45686) &&476spi_check_register("icm45686-3", INV3REG_456_WHOAMI, INV3_WHOAMI_ICM45686)) {477state.board_type.set_and_notify(FMUV6_BOARD_HOLYBRO_6X_45686);478DEV_PRINTF("Detected Holybro 6X_45686\n");479} else if (spi_check_register("iim42652", INV3REG_WHOAMI, INV3_WHOAMI_IIM42652) &&480spi_check_register("icm45686", INV3REG_456_WHOAMI, INV3_WHOAMI_ICM45686)) {481state.board_type.set_and_notify(FMUV6_BOARD_HOLYBRO_6X_REV6);482DEV_PRINTF("Detected Holybro 6X_Rev6\n");483}484}485#endif486487488