diff --git a/src/drivers/boards/common/stm32/CMakeLists.txt b/src/drivers/boards/common/stm32/CMakeLists.txt index 7721a56fa7..861c4b81df 100644 --- a/src/drivers/boards/common/stm32/CMakeLists.txt +++ b/src/drivers/boards/common/stm32/CMakeLists.txt @@ -39,6 +39,7 @@ if (NOT ${LABEL} STREQUAL "bootloader") list(APPEND SRCS board_mcu_version.c board_reset.c + board_hw_rev_ver.c ) endif() diff --git a/src/drivers/boards/common/stm32/board_hw_rev_ver.c b/src/drivers/boards/common/stm32/board_hw_rev_ver.c new file mode 100644 index 0000000000..19f277f978 --- /dev/null +++ b/src/drivers/boards/common/stm32/board_hw_rev_ver.c @@ -0,0 +1,343 @@ +/**************************************************************************** + * + * Copyright (C) 2017 PX4 Development Team. All rights reserved. + * Author: @author David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file board_hw_rev_ver.c + * Implementation of STM32 based Board Hardware Revision and Version ID API + */ + +#include +#include +#include "board_config.h" + +#include "../board_internal_common.h" + +#include + +#if defined(BOARD_HAS_HW_VERSIONING) +/**************************************************************************** + * Private Data + ****************************************************************************/ +static int hw_version = -1; +static int hw_revision = -1; +static char hw_info[] = HW_INFO_INIT; + +/**************************************************************************** + * Protected Functions + ****************************************************************************/ +/**************************************************************************** + * Name: determin_hw_version + * + * Description: + * + * This function fist determines if revision and version resistors are in place. + * if they it will read the ADC channels and decode the DN to ordinal numbers + * that will be returned by board_get_hw_version and board_get_hw_revision API + * + * This will return OK on success and -1 on not supported +* + * + ****************************************************************************/ + +static int dn_to_ordinal(uint16_t dn) +{ + + const struct { + uint16_t low; // High(n-1) + 1 + uint16_t high; // Average High(n)+Low(n+1) EX. 1356 = AVRG(1331,1382) + } dn2o[] = { + // R1(up) R2(down) V min V Max DN Min DN Max + {0, 0 }, // 0 No Resistors + {1, 579 }, // 1 24.9K 442K 0.166255191 0.44102252 204 553 + {580, 967 }, // 2 32.4K 174K 0.492349322 0.770203609 605 966 + {968, 1356}, // 3 38.3K 115K 0.787901749 1.061597759 968 1331 + {1357, 1756}, // 4 46.4K 84.5K 1.124833577 1.386007306 1382 1738 + {1757, 2137}, // 5 51.1K 61.9K 1.443393279 1.685367869 1774 2113 + {2138, 2519}, // 6 61.9K 51.1K 1.758510242 1.974702534 2161 2476 + {2520, 2919}, // 7 84.5K 46.4K 2.084546498 2.267198261 2562 2842 + {2920, 3308}, // 8 115K 38.3K 2.437863827 2.57656294 2996 3230 + {3309, 3699}, // 9 174K 32.4K 2.755223792 2.847933804 3386 3571 + {3700, 4095}, // 10 442K 24.9K 3.113737849 3.147347506 3827 3946 + }; + + for (unsigned int i = 0; i < arraySize(dn2o); i++) { + if (dn >= dn2o[i].low && dn <= dn2o[i].high) { + return i; + } + } + + return -1; +} + +/************************************************************************************ + * Name: read_id_dn + * + * Description: + * Read the HW sense set to get a DN of the value formed by + * 0 VDD + * | + * / + * \ R1 + * / + * | + * +--------------- GPIO_HW_xxx_SENCE | ADC channel N + * | + * / + * \ R2 + * / + * | + * | + * +--------------- GPIO_HW_xxx_DRIVE + * + * Input Parameters: + * id - pointer to receive the dn for the id set + * gpio_drive - gpio that is the drive + * gpio_sense - gpio that is the sence + * adc_channel - the Channel number associated with gpio_sense + * + * Returned Value: + * 0 - Success and id is set + * -EIO - FAiled to init or read the ADC + * + ************************************************************************************/ + +static int read_id_dn(int *id, uint32_t gpio_drive, uint32_t gpio_sense, int adc_channel) +{ + int rv = -EIO; + const unsigned int samples = 16; + /* + * Step one is there resistors? + * + * If we set the mid-point of the ladder which is the ADC input to an + * output, then whatever state is driven out should be seen by the GPIO + * that is on the bottom of the ladder that is switched to an input. + * The SENCE line is effectively an output with a high value pullup + * resistor on it driving an input through a series resistor with a pull up. + * If present the series resistor will form a low pass filter due to stray + * capacitance, but this is fine as long as we give it time to settle. + */ + + /* Turn the drive lines to digital inputs with No pull up */ + + stm32_configgpio(_MK_GPIO_INPUT(gpio_drive) & ~GPIO_PUPD_MASK); + + /* Turn the sense lines to digital outputs LOW */ + + stm32_configgpio(_MK_GPIO_OUTPUT(gpio_sense)); + + + up_udelay(100); /* About 10 TC assuming 485 K */ + + /* Read Drive lines while sense are driven low */ + + int low = stm32_gpioread(_MK_GPIO_INPUT(gpio_drive)); + + + /* Write the sense lines HIGH */ + + stm32_gpiowrite(_MK_GPIO_OUTPUT(gpio_sense), 1); + + up_udelay(100); /* About 10 TC assuming 485 K */ + + /* Read Drive lines while sense are driven high */ + + int high = stm32_gpioread(_MK_GPIO_INPUT(gpio_drive)); + + /* restore the pins to ANALOG */ + + stm32_configgpio(gpio_sense); + + /* Turn the drive lines to digital outputs LOW */ + + stm32_configgpio(gpio_drive ^ GPIO_OUTPUT_SET); + + up_udelay(100); /* About 10 TC assuming 485 K */ + + /* Are Resistors in place ?*/ + + uint32_t dn_sum = 0; + uint16_t dn = 0; + + if ((high ^ low) && low == 0) { + + + /* Yes - Fire up the ADC (it has once control) */ + + if (board_adc_init() == OK) { + + /* Read the value */ + for (unsigned av = 0; av < samples; av++) { + dn = board_adc_sample(adc_channel); + + if (dn == 0xffff) { + break; + } + + dn_sum += dn; + } + + if (dn != 0xffff) { + *id = dn_sum / samples; + rv = OK; + } + } + + } else { + /* No - No Resistors is ID 0 */ + *id = 0; + rv = OK; + } + + /* Turn the drive lines to digital outputs High */ + + stm32_configgpio(gpio_drive); + return rv; +} + + +static int determine_hw_info(int *revision, int *version) +{ + int dn; + int rv = read_id_dn(&dn, GPIO_HW_REV_DRIVE, GPIO_HW_REV_SENSE, ADC_HW_REV_SENSE_CHANNEL); + + if (rv == OK) { + *revision = dn_to_ordinal(dn); + rv = read_id_dn(&dn, GPIO_HW_VER_DRIVE, GPIO_HW_VER_SENSE, ADC_HW_VER_SENSE_CHANNEL); + + if (rv == OK) { + *version = dn_to_ordinal(dn); + } + } + + return rv; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/************************************************************************************ + * Name: board_get_hw_type + * + * Description: + * Optional returns a 0 terminated string defining the HW type. + * + * Input Parameters: + * None + * + * Returned Value: + * a 0 terminated string defining the HW type. This my be a 0 length string "" + * + ************************************************************************************/ + +__EXPORT const char *board_get_hw_type_name() +{ + return (const char *) hw_info; +} + +/************************************************************************************ + * Name: board_get_hw_version + * + * Description: + * Optional returns a integer HW version + * + * Input Parameters: + * None + * + * Returned Value: + * An integer value of this boards hardware version. + * A value of 0 is the default for boards not supporting the BOARD_HAS_VERSIONING API. + * A value of -1 is the default for boards supporting the API but not having version. + * + ************************************************************************************/ + +__EXPORT int board_get_hw_version() +{ + return hw_version; +} + +/************************************************************************************ + * Name: board_get_hw_revision + * + * Description: + * Optional returns a integer HW revision + * + * Input Parameters: + * None + * + * Returned Value: + * An integer value of this boards hardware revision. + * A value of 0 is the default for boards not supporting the BOARD_HAS_VERSIONING API. + * A value of -1 is the default for boards supporting the API but not having revision. + * + ************************************************************************************/ + +__EXPORT int board_get_hw_revision() +{ + return hw_revision; +} + +/************************************************************************************ + * Name: board_determine_hw_info + * + * Description: + * Uses the HW revision and version detection added in FMUv5. + * See https://docs.google.com/spreadsheets/d/1-n0__BYDedQrc_2NHqBenG1DNepAgnHpSGglke-QQwY + * HW REV and VER ID tab. + * + * Input Parameters: + * None + * + * Returned Value: + * 0 - on success or negated errono + * 1) The values for integer value of this boards hardware revision is set + * 2) The integer value of this boards hardware version is set. + * 3) hw_info is populated + * + * A value of 0 is the default for boards supporting the BOARD_HAS_HW_VERSIONING API. + * but not having R1 and R2. + * + ************************************************************************************/ + +int board_determine_hw_info() +{ + int rv = determine_hw_info(&hw_revision, &hw_version); + + if (rv == OK) { + hw_info[HW_INFO_INIT_REV] = board_get_hw_revision() + '0'; + hw_info[HW_INFO_INIT_VER] = board_get_hw_version() + '0'; + } + + return rv; +} +#endif