From f9ffb72f681232ae26c9c6ebaa489e6e3a465823 Mon Sep 17 00:00:00 2001 From: Rocco Marco Guglielmi Date: Sun, 25 Sep 2016 18:14:04 +0000 Subject: [PATCH] Added support for LPS25H. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9797 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ex/ST/lps25h.c | 318 +++++++++++ os/ex/ST/lps25h.h | 456 +++++++++++++++ os/ex/ST/lps25h.mk | 6 + testhal/STM32/STM32F4xx/I2C-LPS25H/.cproject | 55 ++ testhal/STM32/STM32F4xx/I2C-LPS25H/.project | 38 ++ testhal/STM32/STM32F4xx/I2C-LPS25H/Makefile | 223 ++++++++ .../STM32/STM32F4xx/I2C-LPS25H/build/ch.elf | Bin 0 -> 188386 bytes testhal/STM32/STM32F4xx/I2C-LPS25H/chconf.h | 520 ++++++++++++++++++ ...I2C-LPS25H (OpenOCD, Flash and Run).launch | 52 ++ testhal/STM32/STM32F4xx/I2C-LPS25H/halconf.h | 388 +++++++++++++ testhal/STM32/STM32F4xx/I2C-LPS25H/main.c | 180 ++++++ testhal/STM32/STM32F4xx/I2C-LPS25H/mcuconf.h | 251 +++++++++ testhal/STM32/STM32F4xx/I2C-LPS25H/readme.txt | 32 ++ 13 files changed, 2519 insertions(+) create mode 100644 os/ex/ST/lps25h.c create mode 100644 os/ex/ST/lps25h.h create mode 100644 os/ex/ST/lps25h.mk create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/.cproject create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/.project create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/Makefile create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/build/ch.elf create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/chconf.h create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/debug/STM32F4xx-I2C-LPS25H (OpenOCD, Flash and Run).launch create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/halconf.h create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/main.c create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/mcuconf.h create mode 100644 testhal/STM32/STM32F4xx/I2C-LPS25H/readme.txt diff --git a/os/ex/ST/lps25h.c b/os/ex/ST/lps25h.c new file mode 100644 index 000000000..28c00816c --- /dev/null +++ b/os/ex/ST/lps25h.c @@ -0,0 +1,318 @@ +/* + ChibiOS - Copyright (C) 2016 Rocco Marco Guglielmi + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +/** + * @file lps25h.c + * @brief LPS25H MEMS interface module code. + * + * @addtogroup lps25h + * @{ + */ + +#include "hal.h" +#include "lps25h.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if (LPS25H_USE_I2C) || defined(__DOXYGEN__) +/** + * @brief Reads registers value using I2C. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] reg first sub-register address + * @return the read value. + */ +uint8_t lps25hI2CReadRegister(I2CDriver *i2cp, lps25h_sad_t sad, uint8_t reg, + msg_t* msgp) { + msg_t msg; + uint8_t rxbuf; + msg = i2cMasterTransmitTimeout(i2cp, sad, ®, 1, &rxbuf, 1, + TIME_INFINITE); + if(msgp != NULL){ + *msgp = msg; + } + return rxbuf; +} + +/** + * @brief Writes a value into a register using I2C. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] sad slave address without R bit + * @param[in] sub sub-register address + * @param[in] value the value to be written + * @return the operation status. + */ +msg_t lps25hI2CWriteRegister(I2CDriver *i2cp, lps25h_sad_t sad, uint8_t reg, + uint8_t value) { + uint8_t txbuf[2]; + txbuf[0] = reg; + txbuf[1] = value; + return i2cMasterTransmitTimeout(i2cp, sad, txbuf, 2, NULL, 0, TIME_INFINITE); +} +#endif /* LPS25H_USE_I2C */ + +/* + * Interface implementation. + */ +static size_t get_axes_number(void *ip) { + + osalDbgCheck(ip != NULL); + return LPS25H_NUMBER_OF_AXES; +} + +static msg_t read_raw(void *ip, int32_t* axis) { + int32_t tmp; + msg_t msg = MSG_OK; + osalDbgCheck((ip != NULL) && (axis != NULL)); + osalDbgAssert((((LPS25HDriver *)ip)->state == LPS25H_READY), + "read_raw(), invalid state"); + +#if LPS25H_USE_I2C + osalDbgAssert((((LPS25HDriver *)ip)->config->i2cp->state == I2C_READY), + "read_raw(), channel not ready"); +#if LPS25H_SHARED_I2C + i2cAcquireBus(((LPS25HDriver *)ip)->config->i2cp); + i2cStart(((LPS25HDriver *)ip)->config->i2cp, + ((LPS25HDriver *)ip)->config->i2ccfg); +#endif /* LPS25H_SHARED_I2C */ + tmp = lps25hI2CReadRegister(((LPS25HDriver *)ip)->config->i2cp, + ((LPS25HDriver *)ip)->config->slaveaddress, + LPS25H_AD_PRESS_OUT_XL, NULL); + if (msg != MSG_OK) + return msg; + tmp += lps25hI2CReadRegister(((LPS25HDriver *)ip)->config->i2cp, + ((LPS25HDriver *)ip)->config->slaveaddress, + LPS25H_AD_PRESS_OUT_L, NULL) << 8; + if (msg != MSG_OK) + return msg; + tmp += lps25hI2CReadRegister(((LPS25HDriver *)ip)->config->i2cp, + ((LPS25HDriver *)ip)->config->slaveaddress, + LPS25H_AD_PRESS_OUT_H, NULL) << 16; + if (msg != MSG_OK) + return msg; + *axis = (int32_t)tmp; + + +#if LPS25H_SHARED_I2C + i2cReleaseBus(((LPS25HDriver *)ip)->config->i2cp); +#endif /* LPS25H_SHARED_I2C */ +#endif /* LPS25H_USE_I2C */ + return MSG_OK; +} + +static msg_t read_cooked(void *ip, float* axis) { + int32_t raw; + msg_t msg; + + osalDbgCheck((ip != NULL) && (axis != NULL)); + + osalDbgAssert((((LPS25HDriver *)ip)->state == LPS25H_READY), + "read_cooked(), invalid state"); + + msg = read_raw(ip, &raw); + + *axis = raw / ((LPS25HDriver *)ip)->sensitivity; + *axis -= ((LPS25HDriver *)ip)->bias; + return msg; +} + + +static msg_t set_bias(void *ip, int32_t *bp) { + osalDbgCheck((ip != NULL) && (bp != NULL)); + + osalDbgAssert((((LPS25HDriver *)ip)->state == LPS25H_READY) || + (((LPS25HDriver *)ip)->state == LPS25H_STOP), + "set_bias(), invalid state"); + + ((LPS25HDriver *)ip)->bias = *bp; + return MSG_OK; +} + +static msg_t reset_bias(void *ip) { + osalDbgCheck(ip != NULL); + + osalDbgAssert((((LPS25HDriver *)ip)->state == LPS25H_READY) || + (((LPS25HDriver *)ip)->state == LPS25H_STOP), + "reset_bias(), invalid state"); + + ((LPS25HDriver *)ip)->bias = 0; + return MSG_OK; +} + + +static msg_t set_sensivity(void *ip, float *sp) { + + osalDbgCheck((ip != NULL) && (sp !=NULL)); + + osalDbgAssert((((LPS25HDriver *)ip)->state == LPS25H_READY), + "set_sensivity(), invalid state"); + + ((LPS25HDriver *)ip)->sensitivity = *sp; + return MSG_OK; +} + +static msg_t reset_sensivity(void *ip) { + + osalDbgCheck(ip != NULL); + + osalDbgAssert((((LPS25HDriver *)ip)->state == LPS25H_READY), + "reset_sensivity(), invalid state"); + + ((LPS25HDriver *)ip)->sensitivity = LPS25H_SENS; + return MSG_OK; +} + +static const struct BaseSensorVMT vmt_basesensor = { + get_axes_number, read_raw, read_cooked +}; + +static const struct BaseBarometerVMT vmt_basebarometer = { + get_axes_number, read_raw, read_cooked, + set_bias, reset_bias, set_sensivity, reset_sensivity +}; + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes an instance. + * + * @param[out] devp pointer to the @p LPS25HDriver object + * + * @init + */ +void lps25hObjectInit(LPS25HDriver *devp) { + + devp->vmt_basesensor = &vmt_basesensor; + devp->vmt_basebarometer = &vmt_basebarometer; + devp->config = NULL; + devp->bias = 0; + devp->state = LPS25H_STOP; +} + +/** + * @brief Configures and activates LPS25H Complex Driver peripheral. + * + * @param[in] devp pointer to the @p LPS25HDriver object + * @param[in] config pointer to the @p LPS25HConfig object + * + * @api + */ +void lps25hStart(LPS25HDriver *devp, const LPS25HConfig *config) { + uint8_t cr; + osalDbgCheck((devp != NULL) && (config != NULL)); + + osalDbgAssert((devp->state == LPS25H_STOP) || (devp->state == LPS25H_READY), + "lps25hStart(), invalid state"); + + devp->config = config; + +#if LPS25H_USE_I2C +#if LPS25H_SHARED_I2C + i2cAcquireBus((devp)->config->i2cp); +#endif /* LPS25H_SHARED_I2C */ + i2cStart((devp)->config->i2cp, + (devp)->config->i2ccfg); + + /* Control register 1 configuration block.*/ + { + cr = devp->config->outputdatarate | LPS25H_CTRL_REG1_PD; +#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__) + cr |= devp->config->blockdataupdate; + +#endif + lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, + LPS25H_AD_CTRL_REG1, cr); + } + + /* Control register 1 configuration block.*/ + { + cr = 0x05; +#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__) + cr = devp->config->respressure | devp->config->restemperature; + +#endif + lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, + LPS25H_AD_RES_CONF, cr); + } + +#if LPS25H_SHARED_I2C + i2cReleaseBus((devp)->config->i2cp); +#endif /* LPS25H_SHARED_I2C */ +#endif /* LPS25H_USE_I2C */ + /* Storing sensitivity information according to full scale value */ + devp->sensitivity = LPS25H_SENS; + /* This is the Barometer transient recovery time */ + osalThreadSleepMilliseconds(5); + + devp->state = LPS25H_READY; +} + +/** + * @brief Deactivates the LPS25H Complex Driver peripheral. + * + * @param[in] devp pointer to the @p LPS25HDriver object + * + * @api + */ +void lps25hStop(LPS25HDriver *devp) { + + osalDbgCheck(devp != NULL); + + osalDbgAssert((devp->state == LPS25H_STOP) || (devp->state == LPS25H_READY), + "lps25hStop(), invalid state"); + +#if (LPS25H_USE_I2C) + if (devp->state == LPS25H_STOP) { +#if LPS25H_SHARED_I2C + i2cAcquireBus((devp)->config->i2cp); + i2cStart((devp)->config->i2cp, + (devp)->config->i2ccfg); +#endif /* LPS25H_SHARED_I2C */ + lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, + LPS25H_AD_CTRL_REG1, 0); + i2cStop((devp)->config->i2cp); +#if LPS25H_SHARED_I2C + i2cReleaseBus((devp)->config->i2cp); +#endif /* LPS25H_SHARED_I2C */ + } +#endif /* LPS25H_USE_I2C */ + devp->state = LPS25H_STOP; +} +/** @} */ diff --git a/os/ex/ST/lps25h.h b/os/ex/ST/lps25h.h new file mode 100644 index 000000000..7cffb881d --- /dev/null +++ b/os/ex/ST/lps25h.h @@ -0,0 +1,456 @@ +/* + ChibiOS - Copyright (C) 2016 Rocco Marco Guglielmi + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +/** + * @file lps25h.h + * @brief LPS25H MEMS interface module header. + * + * @{ + */ +#ifndef _LPS25H_H_ +#define _LPS25H_H_ + +#include "hal_barometer.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Version identification + * @{ + */ +/** + * @brief LPS25H driver version string. + */ +#define EX_LPS25H_VERSION "1.0.0" + +/** + * @brief LPS25H driver version major number. + */ +#define EX_LPS25H_MAJOR 1 + +/** + * @brief LPS25H driver version minor number. + */ +#define EX_LPS25H_MINOR 0 + +/** + * @brief LPS25H driver version patch number. + */ +#define EX_LPS25H_PATCH 0 +/** @} */ + +/** + * @brief LPS25H characteristics. + * + * @{ + */ +#define LPS25H_NUMBER_OF_AXES 1U + +#define LPS25H_SENS 4096.0f /**< LSB/hPa */ +/** @} */ + +/** + * @name LPS25H communication interfaces related bit masks + * @{ + */ +#define LPS25H_DI_MASK 0xFF /**< Data In mask */ +#define LPS25H_DI(n) (1 << n) /**< Data In bit n */ +#define LPS25H_AD_MASK 0x3F /**< Address Data mask */ +#define LPS25H_AD(n) (1 << n) /**< Address Data bit n */ +#define LPS25H_MS (1 << 6) /**< Multiple read write */ +#define LPS25H_RW (1 << 7) /**< Read Write selector */ + +#define LPS25H_SUB_MS (1 << 7) /**< Multiple read write in I2C mode */ +/** @} */ + +/** + * @name LPS25H register addresses + * @{ + */ +#define LPS25H_AD_REF_P_XL 0x08 +#define LPS25H_AD_REF_P_L 0x09 +#define LPS25H_AD_REF_P_H 0x0A +#define LPS25H_AD_WHO_AM_I 0x0F +#define LPS25H_AD_RES_CONF 0x10 +#define LPS25H_AD_CTRL_REG1 0x20 +#define LPS25H_AD_CTRL_REG2 0x21 +#define LPS25H_AD_CTRL_REG3 0x22 +#define LPS25H_AD_CTRL_REG4 0x23 +#define LPS25H_AD_INT_CFG 0x24 +#define LPS25H_AD_INT_SRC 0x25 +#define LPS25H_AD_STATUS_REG 0x27 +#define LPS25H_AD_CTRL_REG5 0x24 +#define LPS25H_AD_REFERENCE 0x25 +#define LPS25H_AD_OUT_TEMP 0x26 +#define LPS25H_AD_PRESS_OUT_XL 0x28 +#define LPS25H_AD_PRESS_OUT_L 0x29 +#define LPS25H_AD_PRESS_OUT_H 0x2A +#define LPS25H_AD_TEMP_OUT_L 0x2B +#define LPS25H_AD_TEMP_OUT_H 0x2C +#define LPS25H_AD_FIFO_CTRL 0x2E +#define LPS25H_AD_FIFO_SRC 0x2F +#define LPS25H_AD_THS_P_L 0x30 +#define LPS25H_AD_THS_P_H 0x31 +#define LPS25H_AD_RPDS_L 0x39 +#define LPS25H_AD_RPDS_H 0x3A +/** @} */ + +/** + * @name LPS25H_CTRL_REG1 register bits definitions + * @{ + */ +#define LPS25H_CTRL_REG1_MASK 0xFF +#define LPS25H_CTRL_REG1_SIM (1 << 0) +#define LPS25H_CTRL_REG1_RESET_AZ (1 << 1) +#define LPS25H_CTRL_REG1_BDU (1 << 2) +#define LPS25H_CTRL_REG1_DIFF_EN (1 << 3) +#define LPS25H_CTRL_REG1_ODR0 (1 << 4) +#define LPS25H_CTRL_REG1_ODR1 (1 << 5) +#define LPS25H_CTRL_REG1_ODR2 (1 << 6) +#define LPS25H_CTRL_REG1_PD (1 << 7) +/** @} */ + +/** + * @name LPS25H_CTRL_REG2 register bits definitions + * @{ + */ +#define LPS25H_CTRL_REG2_MASK 0xF3 +#define LPS25H_CTRL_REG2_ONE_SHOT (1 << 0) +#define LPS25H_CTRL_REG2_AUTO_ZERO (1 << 1) +#define LPS25H_CTRL_REG2_SWRESET (1 << 2) +#define LPS25H_CTRL_REG2_FIFO_MEAN_DEC (1 << 4) +#define LPS25H_CTRL_REG2_WTM_EN (1 << 5) +#define LPS25H_CTRL_REG2_FIFO_EN (1 << 6) +#define LPS25H_CTRL_REG2_BOOT (1 << 7) +/** @} */ + +/** + * @name LPS25H_CTRL_REG3 register bits definitions + * @{ + */ +#define LPS25H_CTRL_REG3_MASK 0xC3 +#define LPS25H_CTRL_REG3_INT_S1 (1 << 0) +#define LPS25H_CTRL_REG3_INT_S2 (1 << 1) +#define LPS25H_CTRL_REG3_PP_OD (1 << 6) +#define LPS25H_CTRL_REG3_INT_H_L (1 << 7) +/** @} */ + +/** + * @name LPS25H_CTRL_REG4 register bits definitions + * @{ + */ +#define LPS25H_CTRL_REG4_MASK 0x0F +#define LPS25H_CTRL_REG4_P1_DRDY (1 << 0) +#define LPS25H_CTRL_REG4_P1_OVERRUN (1 << 1) +#define LPS25H_CTRL_REG4_P1_WTM (1 << 2) +#define LPS25H_CTRL_REG4_P1_EMPTY (1 << 3) +/** @} */ + +/** + * @name LPS25H_INT1_CFG register bits definitions + * @{ + */ +#define LPS25H_INT1_CFG_MASK 0x07 +#define LPS25H_INT1_CFG_PH_E (1 << 0) +#define LPS25H_INT1_CFG_PL_E (1 << 1) +#define LPS25H_INT1_CFG_LIR (1 << 2) +/** @} */ + +/** + * @name LPS25H_INT1_SRC register bits definitions + * @{ + */ +#define LPS25H_INT1_SRC_MASK 0x07 +#define LPS25H_INT1_SRC_PH (1 << 0) +#define LPS25H_INT1_SRC_PL (1 << 1) +#define LPS25H_INT1_SRC_IA (1 << 2) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief LPS25H SPI interface switch. + * @details If set to @p TRUE the support for SPI is included. + * @note The default is @p FALSE. + */ +#if !defined(LPS25H_USE_SPI) || defined(__DOXYGEN__) +#define LPS25H_USE_SPI FALSE +#endif + +/** + * @brief LPS25H I2C interface switch. + * @details If set to @p TRUE the support for I2C is included. + * @note The default is @p FALSE. + */ +#if !defined(LPS25H_USE_I2C) || defined(__DOXYGEN__) +#define LPS25H_USE_I2C TRUE +#endif + +/** + * @brief LPS25H advanced configurations switch. + * @details If set to @p TRUE more configurations are available. + * @note The default is @p FALSE. + */ +#if !defined(LPS25H_USE_ADVANCED) || defined(__DOXYGEN__) +#define LPS25H_USE_ADVANCED FALSE +#endif + +/** + * @brief LPS25H shared I2C switch. + * @details If set to @p TRUE the device acquires I2C bus ownership + * on each transaction. + * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION + */ +#if !defined(LPS25H_SHARED_SPI) || defined(__DOXYGEN__) +#define LPS25H_SHARED_I2C FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !(LPS25H_USE_SPI ^ LPS25H_USE_I2C) +#error "LPS25H_USE_SPI and LPS25H_USE_I2C cannot be both true or both false" +#endif + +#if LPS25H_USE_SPI && !HAL_USE_SPI +#error "LPS25H_USE_SPI requires HAL_USE_SPI" +#endif + +#if LPS25H_USE_SPI +#error "LPS25H over SPI still not supported" +#endif + +#if LPS25H_USE_I2C && !HAL_USE_I2C +#error "LPS25H_USE_I2C requires HAL_USE_I2C" +#endif + +#if LPS25H_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION +#error "LPS25H_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION" +#endif + +/* + * TODO: Add SPI support. + */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @name LPS25H data structures and types. + * @{ + */ +/** + * @brief LPS25H slave address + */ +typedef enum { + LPS25H_SAD_GND = 0x5C, /**< Slave Address when SA0 is to GND */ + LPS25H_SAD_VCC = 0x5D /**< Slave Address when SA0 is to VCC */ +}lps25h_sad_t; + +/** + * @brief LPS25H output data rate and bandwidth. + */ +typedef enum { + LPS25H_ODR_ONE_SHOT = 0x00, /**< One shot. */ + LPS25H_ODR_1HZ = 0x10, /**< Output data rate 1 Hz. */ + LPS25H_ODR_7HZ = 0x20, /**< Output data rate 7 Hz. */ + LPS25H_ODR_12P5HZ = 0x30, /**< Output data rate 12.5 Hz. */ + LPS25H_ODR_25HZ = 0x40 /**< Output data rate 25 Hz. */ +}lps25h_odr_t; + +/** + * @brief LPS25H pressure resolution. + */ +typedef enum { + LPS25H_AVGP_8 = 0x00, /**< Number of internal average is 8. */ + LPS25H_AVGP_32 = 0x01, /**< Number of internal average is 8. */ + LPS25H_AVGP_128 = 0x02, /**< Number of internal average is 8. */ + LPS25H_AVGP_512 = 0x03, /**< Number of internal average is 8. */ +}lps25h_avgp_t; + +/** + * @brief LPS25H temperature resolution. + */ +typedef enum { + LPS25H_AVGT_8 = 0x00, /**< Number of internal average is 8. */ + LPS25H_AVGT_32 = 0x04, /**< Number of internal average is 8. */ + LPS25H_AVGT_128 = 0x08, /**< Number of internal average is 8. */ + LPS25H_AVGT_512 = 0x0C, /**< Number of internal average is 8. */ +}lps25h_avgt_t; + +/** + * @brief LPS25H block data update. + */ +typedef enum { + LPS25H_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */ + LPS25H_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */ +}lps25h_bdu_t; + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + LPS25H_UNINIT = 0, /**< Not initialized. */ + LPS25H_STOP = 1, /**< Stopped. */ + LPS25H_READY = 2, /**< Ready. */ +} lps25h_state_t; + +/** + * @brief LPS25H configuration structure. + */ +typedef struct { + +#if LPS25H_USE_SPI || defined(__DOXYGEN__) + /** + * @brief SPI driver associated to this LPS25H. + */ + SPIDriver *spip; + /** + * @brief SPI configuration associated to this LPS25H. + */ + const SPIConfig *spicfg; +#endif /* LPS25H_USE_SPI */ +#if LPS25H_USE_I2C || defined(__DOXYGEN__) + /** + * @brief I2C driver associated to this LPS25H. + */ + I2CDriver *i2cp; + /** + * @brief I2C configuration associated to this LPS25H. + */ + const I2CConfig *i2ccfg; +#endif /* LPS25H_USE_I2C */ + /** + * @brief LPS25H initial sensitivity. + */ + float sensitivity; + /** + * @brief LPS25H initial bias. + */ + float bias; + /** + * @brief LPS25H slave address + */ + lps25h_sad_t slaveaddress; + /** + * @brief LPS25H output data rate selection. + */ + lps25h_odr_t outputdatarate; +#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__) + /** + * @brief LPS25H block data update. + */ + lps25h_bdu_t blockdataupdate; + /** + * @brief LPS25H pressure resolution. + */ + lps25h_avgp_t respressure; + /** + * @brief LPS25H temperature resolution. + */ + lps25h_avgt_t restemperature; +#endif +} LPS25HConfig; + +/** + * @brief Structure representing a LPS25H driver. + */ +typedef struct LPS25HDriver LPS25HDriver; + +/** + * @brief @p LPS25H specific methods. + */ +#define _lps25h_methods \ + _base_barometer_methods + +/** + * @extends BaseGyroscopeVMT + * + * @brief @p LPS25H virtual methods table. + */ +struct LPS25HVMT { + _lps25h_methods +}; + +/** + * @brief @p LPS25HDriver specific data. + */ +#define _lps25h_data \ + _base_barometer_data \ + /* Driver state.*/ \ + lps25h_state_t state; \ + /* Current configuration data.*/ \ + const LPS25HConfig *config; \ + /* Current sensitivity data.*/ \ + float sensitivity; \ + /* Current Bias data.*/ \ + float bias; + +/** + * @extends BaseGyroscope + * + * @brief LPS25H 3-axis barometer class. + * @details This class extends @p BaseGyroscope by adding physical + * driver implementation. + */ +struct LPS25HDriver { + /** @brief BaseSensor Virtual Methods Table. */ + const struct BaseSensorVMT *vmt_basesensor; + /** @brief BaseBarometer Virtual Methods Table. */ + const struct BaseBarometerVMT *vmt_basebarometer; + /** @brief LPS25H Virtual Methods Table. */ + const struct LPS25HVMT *vmt_lps25h; + _lps25h_data +}; +/** @} */ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void lps25hObjectInit(LPS25HDriver *devp); + void lps25hStart(LPS25HDriver *devp, const LPS25HConfig *config); + void lps25hStop(LPS25HDriver *devp); +#ifdef __cplusplus +} +#endif + +#endif /* _LPS25H_H_ */ + +/** @} */ + diff --git a/os/ex/ST/lps25h.mk b/os/ex/ST/lps25h.mk new file mode 100644 index 000000000..1d8d6ec8d --- /dev/null +++ b/os/ex/ST/lps25h.mk @@ -0,0 +1,6 @@ +# List of all the LPS25H device files. +LPS25HSRC := $(CHIBIOS)/os/ex/ST/lps25h.c + +# Required include directories +LPS25HINC := $(CHIBIOS)/os/hal/lib/peripherals/sensors \ + $(CHIBIOS)/os/ex/ST \ No newline at end of file diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/.cproject b/testhal/STM32/STM32F4xx/I2C-LPS25H/.cproject new file mode 100644 index 000000000..0012badfd --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/.cproject @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/.project b/testhal/STM32/STM32F4xx/I2C-LPS25H/.project new file mode 100644 index 000000000..ca572b406 --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/.project @@ -0,0 +1,38 @@ + + + STM32F4xx-I2C-LPS25H + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + board + 2 + CHIBIOS/os/hal/boards/ST_NUCLEO64_F401RE + + + os + 2 + CHIBIOS/os + + + diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/Makefile b/testhal/STM32/STM32F4xx/I2C-LPS25H/Makefile new file mode 100644 index 000000000..057c420fb --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/Makefile @@ -0,0 +1,223 @@ +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 +endif + +# C specific options here (added to USE_OPT). +ifeq ($(USE_COPT),) + USE_COPT = +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -fno-rtti +endif + +# Enable this if you want the linker to remove unused code and data +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# Linker extra options here. +ifeq ($(USE_LDOPT),) + USE_LDOPT = +endif + +# Enable this if you want link time optimizations (LTO) +ifeq ($(USE_LTO),) + USE_LTO = yes +endif + +# If enabled, this option allows to compile the application in THUMB mode. +ifeq ($(USE_THUMB),) + USE_THUMB = yes +endif + +# Enable this if you want to see the full log while compiling. +ifeq ($(USE_VERBOSE_COMPILE),) + USE_VERBOSE_COMPILE = no +endif + +# If enabled, this option makes the build process faster by not compiling +# modules not used in the current configuration. +ifeq ($(USE_SMART_BUILD),) + USE_SMART_BUILD = yes +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Stack size to be allocated to the Cortex-M process stack. This stack is +# the stack used by the main() thread. +ifeq ($(USE_PROCESS_STACKSIZE),) + USE_PROCESS_STACKSIZE = 0x400 +endif + +# Stack size to the allocated to the Cortex-M main/exceptions stack. This +# stack is used for processing interrupts and exceptions. +ifeq ($(USE_EXCEPTIONS_STACKSIZE),) + USE_EXCEPTIONS_STACKSIZE = 0x400 +endif + +# Enables the use of FPU (no, softfp, hard). +ifeq ($(USE_FPU),) + USE_FPU = no +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define project name here +PROJECT = ch + +# Imported source files and paths +CHIBIOS = ../../../.. +# Startup files. +include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk +# HAL-OSAL files (optional). +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk +include $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F401RE/board.mk +include $(CHIBIOS)/os/hal/osal/rt/osal.mk +# RTOS files (optional). +include $(CHIBIOS)/os/rt/rt.mk +include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk +# Other files (optional). +include $(CHIBIOS)/os/ex/ST/lps25h.mk +include $(CHIBIOS)/os/hal/lib/streams/streams.mk +include $(CHIBIOS)/os/various/shell/shell.mk + +# Define linker script file here +LDSCRIPT= $(STARTUPLD)/STM32F401xE.ld + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(STARTUPSRC) \ + $(KERNSRC) \ + $(PORTSRC) \ + $(OSALSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + $(LPS25HSRC) \ + $(STREAMSSRC) \ + $(SHELLSRC) \ + main.c + +# C++ sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CPPSRC = + +# C sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACSRC = + +# C++ sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACPPSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCPPSRC = + +# List ASM source files here +ASMSRC = +ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) + +INCDIR = $(CHIBIOS)/os/license \ + $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ + $(HALINC) $(PLATFORMINC) $(BOARDINC) $(LPS25HINC) \ + $(STREAMSINC) $(SHELLINC) + +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +MCU = cortex-m4 + +#TRGT = arm-elf- +TRGT = arm-none-eabi- +CC = $(TRGT)gcc +CPPC = $(TRGT)g++ +# Enable loading with g++ only if you need C++ runtime support. +# NOTE: You can use C++ even without C++ support if you are careful. C++ +# runtime support makes code size explode. +LD = $(TRGT)gcc +#LD = $(TRGT)g++ +CP = $(TRGT)objcopy +AS = $(TRGT)gcc -x assembler-with-cpp +AR = $(TRGT)ar +OD = $(TRGT)objdump +SZ = $(TRGT)size +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +# ARM-specific options here +AOPT = + +# THUMB-specific options here +TOPT = -mthumb -DTHUMB + +# Define C warning options here +CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra -Wundef + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = -DCHPRINTF_USE_FLOAT=1 -DSHELL_CMD_TEST_ENABLED=0 \ + -DLPS25H_USE_ADVANCED=0 + +# Define ASM defines here +UADEFS = + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = + +# +# End of user defines +############################################################################## + +RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC +include $(RULESPATH)/rules.mk diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/build/ch.elf b/testhal/STM32/STM32F4xx/I2C-LPS25H/build/ch.elf new file mode 100644 index 0000000000000000000000000000000000000000..3e24a5e23f8c197a844d2c9d96a161e59704f3df GIT binary patch literal 188386 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

XXQ| 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 KH4}5OpZGsOwDsQr literal 0 HcmV?d00001 diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/chconf.h b/testhal/STM32/STM32F4xx/I2C-LPS25H/chconf.h new file mode 100644 index 000000000..ad6b53ade --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/chconf.h @@ -0,0 +1,520 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM TRUE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/debug/STM32F4xx-I2C-LPS25H (OpenOCD, Flash and Run).launch b/testhal/STM32/STM32F4xx/I2C-LPS25H/debug/STM32F4xx-I2C-LPS25H (OpenOCD, Flash and Run).launch new file mode 100644 index 000000000..7a2096330 --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/debug/STM32F4xx-I2C-LPS25H (OpenOCD, Flash and Run).launch @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/halconf.h b/testhal/STM32/STM32F4xx/I2C-LPS25H/halconf.h new file mode 100644 index 000000000..07b0143bd --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/halconf.h @@ -0,0 +1,388 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C TRUE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the QSPI subsystem. + */ +#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__) +#define HAL_USE_QSPI FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/main.c b/testhal/STM32/STM32F4xx/I2C-LPS25H/main.c new file mode 100644 index 000000000..c31fef938 --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/main.c @@ -0,0 +1,180 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "ch.h" +#include "hal.h" + +#include "string.h" +#include "shell.h" +#include "chprintf.h" + +#include "lps25h.h" + +/*===========================================================================*/ +/* LPS25H related. */ +/*===========================================================================*/ + +/* LPS25H Driver: This object represent an LPS25H instance */ +static LPS25HDriver LPS25HD1; + +static int32_t rawdata; +static float cookeddata; + +static const I2CConfig i2ccfg = { + OPMODE_I2C, + 400000, + FAST_DUTY_CYCLE_2, +}; + +static const LPS25HConfig lps25hcfg = { + &I2CD1, + &i2ccfg, + 0, /* Use default sensitivity.*/ + 0, /* Use default bias.*/ + LPS25H_SAD_VCC, /* SA0 connected to VCC */ + LPS25H_ODR_7HZ, /* Output data rate 7 Hz.*/ +#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__) + LPS25H_BDU_CONTINUOUS, + LPS25H_AVGP_512, + LPS25H_AVGT_512 +#endif +}; + +/*===========================================================================*/ +/* Command line related. */ +/*===========================================================================*/ + +/* Enable use of special ANSI escape sequences */ +#define CHPRINTF_USE_ANSI_CODE TRUE +#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048) + +static void cmd_read(BaseSequentialStream *chp, int argc, char *argv[]) { + + if (argc != 1) { + chprintf(chp, "Usage: read [raw|cooked]\r\n"); + return; + } + + while (chnGetTimeout((BaseChannel *)chp, 150) == Q_TIMEOUT) { + if (!strcmp (argv[0], "raw")) { +#if CHPRINTF_USE_ANSI_CODE + chprintf(chp, "\033[2J\033[1;1H"); +#endif + barometerReadRaw(&LPS25HD1, &rawdata); + chprintf(chp, "LPS25H Barometer raw data...\r\n"); + chprintf(chp, "RAW: %d\r\n", rawdata); + } + else if (!strcmp (argv[0], "cooked")) { +#if CHPRINTF_USE_ANSI_CODE + chprintf(chp, "\033[2J\033[1;1H"); +#endif + barometerReadCooked(&LPS25HD1, &cookeddata); + chprintf(chp, "LPS25H Barometer cooked data...\r\n"); + chprintf(chp, "COOCKED: %.4f hPa\r\n", cookeddata); + } + else { + chprintf(chp, "Usage: read [raw|cooked]\r\n"); + return; + } + } + chprintf(chp, "Stopped\r\n"); +} + +static const ShellCommand commands[] = { + {"read", cmd_read}, + {NULL, NULL} +}; + +static const ShellConfig shell_cfg1 = { + (BaseSequentialStream *)&SD2, + commands +}; + +/*===========================================================================*/ +/* Main code. */ +/*===========================================================================*/ + +/* + * LED blinker thread, times are in milliseconds. + */ +static THD_WORKING_AREA(waThread1, 128); +static THD_FUNCTION(Thread1, arg) { + + (void)arg; + chRegSetThreadName("blinker"); + while (true) { + palClearPad(GPIOA, GPIOA_LED_GREEN); + chThdSleepMilliseconds(500); + palSetPad(GPIOA, GPIOA_LED_GREEN); + chThdSleepMilliseconds(500); + } +} + +/* + * Application entry point. + */ +int main(void) { + + /* + * System initializations. + * - HAL initialization, this also initializes the configured device drivers + * and performs the board-specific initializations. + * - Kernel initialization, the main() function becomes a thread and the + * RTOS is active. + */ + halInit(); + chSysInit(); + + palSetLineMode(LINE_ARD_D15, PAL_MODE_ALTERNATE(4) | + PAL_STM32_OSPEED_HIGHEST); + palSetLineMode(LINE_ARD_D14, PAL_MODE_ALTERNATE(4) | + PAL_STM32_OSPEED_HIGHEST); + + /* + * Activates the serial driver 2 using the driver default configuration. + */ + sdStart(&SD2, NULL); + + /* + * Creates the blinker thread. + */ + chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); + + /* + * LPS25H Object Initialization + */ + lps25hObjectInit(&LPS25HD1); + + /* + * Activates the LPS25H driver. + */ + lps25hStart(&LPS25HD1, &lps25hcfg); + + /* + * Shell manager initialization. + */ + shellInit(); + + while(TRUE) { + + thread_t *shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, + "shell", NORMALPRIO + 1, + shellThread, (void *)&shell_cfg1); + chThdWait(shelltp); /* Waiting termination. */ + chThdSleepMilliseconds(1000); + } + lps25hStop(&LPS25HD1); +} diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/mcuconf.h b/testhal/STM32/STM32F4xx/I2C-LPS25H/mcuconf.h new file mode 100644 index 000000000..166f04112 --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/mcuconf.h @@ -0,0 +1,251 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI +#define STM32_PLLM_VALUE 16 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 15 +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI22_IRQ_PRIORITY 15 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/testhal/STM32/STM32F4xx/I2C-LPS25H/readme.txt b/testhal/STM32/STM32F4xx/I2C-LPS25H/readme.txt new file mode 100644 index 000000000..aae24364d --- /dev/null +++ b/testhal/STM32/STM32F4xx/I2C-LPS25H/readme.txt @@ -0,0 +1,32 @@ +***************************************************************************** +** ChibiOS/HAL + ChibiOS/EX - SPI + L3GD20 demo for STM32F4xx. ** +***************************************************************************** + +** TARGET ** + +The demo runs on an STM32 Nucleo64-F401RE board. It has been tested with the +X-NUCLEO-IKS01A1 shield. + +** The Demo ** + +The application demonstrates the use of the STM32F4xx I2C driver in order +to acquire data from LSM6DS0 using ChibiOS/EX. + +** Board Setup ** + +None required. + +** Build Procedure ** + +The demo has been tested by using the free Codesourcery GCC-based toolchain +and YAGARTO. +Just modify the TRGT line in the makefile in order to use different GCC ports. + +** Notes ** + +Some files used by the demo are not part of ChibiOS/RT but are copyright of +ST Microelectronics and are licensed under a different license. +Also note that not all the files present in the ST library are distributed +with ChibiOS/RT, you can find the whole library on the ST web site: + + http://www.st.com