You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by vi...@apache.org on 2019/08/09 23:53:36 UTC
[mynewt-core] branch master updated: hw/drivers/lps33hw:Added
support to FIFO (#1946)
This is an automated email from the ASF dual-hosted git repository.
vipulrahane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new b1c482f hw/drivers/lps33hw:Added support to FIFO (#1946)
b1c482f is described below
commit b1c482f0e946ec0baa4b8b4de16157b332eb93d2
Author: Mario Tesi <31...@users.noreply.github.com>
AuthorDate: Sat Aug 10 01:53:31 2019 +0200
hw/drivers/lps33hw:Added support to FIFO (#1946)
Add support to FIFO on LPS33HW/LPS22HB driver
FIFO supports the following features:
- configurable FIFO watermark
- interrupt on FIFO watermark
- reading mode [polling, stream]
Driver tested on STM32F4-Discovery board as "off board" device
connected to I2C master interface.
Signed-off-by: tesimari <ma...@st.com>
---
.../sensors/lps33hw/include/lps33hw/lps33hw.h | 23 ++
hw/drivers/sensors/lps33hw/src/lps33hw.c | 290 ++++++++++++++++++++-
hw/drivers/sensors/lps33hw/src/lps33hw_priv.h | 14 +
hw/drivers/sensors/lps33hw/syscfg.yml | 8 +
4 files changed, 322 insertions(+), 13 deletions(-)
diff --git a/hw/drivers/sensors/lps33hw/include/lps33hw/lps33hw.h b/hw/drivers/sensors/lps33hw/include/lps33hw/lps33hw.h
index 9c42eae..37ac9f1 100644
--- a/hw/drivers/sensors/lps33hw/include/lps33hw/lps33hw.h
+++ b/hw/drivers/sensors/lps33hw/include/lps33hw/lps33hw.h
@@ -55,6 +55,22 @@ enum lps33hw_low_pass_config {
LPS33HW_LPF_ENABLED_HIGH_BW = 0x03 /* Bandwidth = data rate / 20 */
};
+/*
+ * Sensor read mode
+ *
+ * LPS33HW_READ_POLL enable polling mode
+ * LPS33HW_READ_STREAM enable FIFO read mode
+ */
+enum lps33hw_read_mode {
+ LPS33HW_READ_POLL = 0,
+ LPS33HW_READ_STREAM = 1,
+};
+
+struct lps33hw_int {
+ /* Sleep waiting for an interrupt to occur */
+ struct os_sem wait;
+};
+
struct lps33hw_int_cfg {
uint8_t pin;
unsigned int data_rdy : 1;
@@ -63,6 +79,7 @@ struct lps33hw_int_cfg {
unsigned int active_low : 1;
unsigned int open_drain : 1;
unsigned int latched : 1;
+ unsigned int fifo_wtm_rdy : 1;
};
struct lps33hw_cfg {
@@ -72,10 +89,15 @@ struct lps33hw_cfg {
enum lps33hw_low_pass_config lpf;
unsigned int autozero : 1;
unsigned int autorifp : 1;
+ uint8_t fifo_wtm;
+ enum lps33hw_read_mode read_mode;
};
struct lps33hw_private_driver_data {
struct sensor_read_ctx user_ctx;
+
+ /* Inetrrupt state */
+ struct lps33hw_int *interrupt;
};
struct lps33hw {
@@ -91,6 +113,7 @@ struct lps33hw {
struct lps33hw_cfg cfg;
os_time_t last_read_time;
struct lps33hw_private_driver_data pdd;
+ struct lps33hw_int interrupt;
#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
bool node_is_spi;
#endif
diff --git a/hw/drivers/sensors/lps33hw/src/lps33hw.c b/hw/drivers/sensors/lps33hw/src/lps33hw.c
index 3225ca1..d8c4c86 100644
--- a/hw/drivers/sensors/lps33hw/src/lps33hw.c
+++ b/hw/drivers/sensors/lps33hw/src/lps33hw.c
@@ -670,6 +670,7 @@ lps33hw_enable_interrupt(struct sensor *sensor, hal_gpio_irq_handler_t handler,
return rc;
}
(void)press;
+ lps33hw->pdd.interrupt = &lps33hw->interrupt;
rc = lps33hw_get_regs(itf, LPS33HW_INT_SOURCE, 1, &int_source);
if (rc) {
@@ -688,7 +689,7 @@ lps33hw_disable_interrupt(struct sensor *sensor)
lps33hw = (struct lps33hw *)SENSOR_GET_DEVICE(sensor);
int_cfg = &lps33hw->cfg.int_cfg;
-
+ lps33hw->pdd.interrupt = NULL;
hal_gpio_irq_release(int_cfg->pin);
}
@@ -828,6 +829,10 @@ lps33hw_config_interrupt(struct sensor *sensor, struct lps33hw_int_cfg cfg)
if (rc) {
return rc;
}
+ rc = lps33hw_set_value(itf, LPS33HW_CTRL_REG3_F_FTH, cfg.fifo_wtm_rdy);
+ if (rc) {
+ return rc;
+ }
rc = lps33hw_set_value(itf, LPS33HW_CTRL_REG3_INT_H_L, cfg.active_low);
if (rc) {
return rc;
@@ -926,24 +931,25 @@ lps33hw_sensor_set_trigger_thresh(struct sensor *sensor,
return 0;
}
-int
-lps33hw_init(struct os_dev *dev, void *arg)
+int lps33hw_init(struct os_dev *dev, void *arg)
{
- struct lps33hw *lps;
+ struct lps33hw *lps33hw;
struct sensor *sensor;
int rc;
+ os_error_t error;
if (!arg || !dev) {
return SYS_ENODEV;
}
- lps = (struct lps33hw *) dev;
+ lps33hw = (struct lps33hw *)dev;
#if MYNEWT_VAL(LPS33HW_ONE_SHOT_MODE)
- os_callout_init(&lps->lps33hw_one_shot_read, sensor_mgr_evq_get(), lps33hw_one_shot_read_cb, dev);
+ os_callout_init(&lps->lps33hw_one_shot_read, sensor_mgr_evq_get(),
+ lps33hw_one_shot_read_cb, dev);
#endif
- sensor = &lps->sensor;
- lps->cfg.mask = SENSOR_TYPE_ALL;
+ sensor = &lps33hw->sensor;
+ lps33hw->cfg.mask = SENSOR_TYPE_ALL;
/* Initialise the stats entry */
rc = stats_init(
@@ -951,6 +957,7 @@ lps33hw_init(struct os_dev *dev, void *arg)
STATS_SIZE_INIT_PARMS(g_lps33hwstats, STATS_SIZE_32),
STATS_NAME_INIT_PARMS(lps33hw_stat_section));
SYSINIT_PANIC_ASSERT(rc == 0);
+
/* Register the entry with the stats registry */
rc = stats_register(dev->od_name, STATS_HDR(g_lps33hwstats));
SYSINIT_PANIC_ASSERT(rc == 0);
@@ -978,6 +985,10 @@ lps33hw_init(struct os_dev *dev, void *arg)
return rc;
}
+ /* Init semaphore for task to wait on when irq asleep */
+ error = os_sem_init(&(lps33hw->interrupt.wait), 0);
+ assert(error == OS_OK);
+
#if !MYNEWT_VAL(BUS_DRIVER_PRESENT)
if (sensor->s_itf.si_type == SENSOR_ITF_SPI) {
rc = hal_spi_config(sensor->s_itf.si_num, &spi_lps33hw_settings);
@@ -1008,10 +1019,9 @@ lps33hw_config(struct lps33hw *lps, struct lps33hw_cfg *cfg)
{
int rc;
struct sensor_itf *itf;
+ uint8_t val;
itf = SENSOR_GET_ITF(&(lps->sensor));
-
- uint8_t val;
rc = lps33hw_get_regs(itf, LPS33HW_WHO_AM_I, 1, &val);
if (rc) {
return rc;
@@ -1020,30 +1030,54 @@ lps33hw_config(struct lps33hw *lps, struct lps33hw_cfg *cfg)
return SYS_EINVAL;
}
+ /* Reset device */
+ rc = lps33hw_set_value(itf, LPS33HW_CTRL_REG2_SWRESET, 1);
+ if (rc) {
+ return rc;
+ }
+
+ /* Enable block data update flag */
+ rc = lps33hw_set_value(itf, LPS33HW_CTRL_REG1_BDU, 1);
+ if (rc) {
+ return rc;
+ }
+
rc = lps33hw_set_value(itf, LPS33HW_INTERRUPT_CFG_AUTORIFP, cfg->autorifp);
if (rc) {
return rc;
}
+ lps->cfg.autorifp = cfg->autorifp;
rc = lps33hw_set_value(itf, LPS33HW_INTERRUPT_CFG_AUTOZERO, cfg->autozero);
if (rc) {
return rc;
}
+ lps->cfg.autozero = cfg->autozero;
rc = lps33hw_set_data_rate(itf, cfg->data_rate);
if (rc) {
return rc;
}
+ lps->cfg.data_rate = cfg->data_rate;
rc = lps33hw_set_lpf(itf, cfg->lpf);
if (rc) {
return rc;
}
+ lps->cfg.lpf = cfg->lpf;
- rc = lps33hw_config_interrupt(&(lps->sensor), cfg->int_cfg);
+ /* Configure FIFO watermark */
+ rc = lps33hw_set_value(itf, LPS33HW_FIFO_WTM_THR, cfg->fifo_wtm);
if (rc) {
+ return rc;
+ }
+ lps->cfg.fifo_wtm = cfg->fifo_wtm;
+ rc = lps33hw_config_interrupt(&(lps->sensor), cfg->int_cfg);
+ if (rc) {
+ return rc;
}
+ lps->cfg.int_cfg = cfg->int_cfg;
rc = sensor_set_type_mask(&(lps->sensor), cfg->mask);
if (rc) {
@@ -1051,6 +1085,7 @@ lps33hw_config(struct lps33hw *lps, struct lps33hw_cfg *cfg)
}
lps->cfg.mask = cfg->mask;
+ lps->cfg.read_mode = cfg->read_mode;
return 0;
}
@@ -1082,7 +1117,7 @@ lps33hw_read_interrupt_handler(void *arg)
}
static int
-lps33hw_sensor_read(struct sensor *sensor, sensor_type_t type,
+lps33hw_sensor_read_poll(struct sensor *sensor, sensor_type_t type,
sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
{
int rc = SYS_EINVAL;
@@ -1160,6 +1195,232 @@ lps33hw_sensor_read(struct sensor *sensor, sensor_type_t type,
return rc;
}
+static int lps33hw_read_fifo(struct sensor_itf *itf,
+ struct sensor_temp_data *std,
+ struct sensor_press_data *spd)
+{
+ int rc;
+ uint8_t fifo_data[5];
+ int32_t int_press;
+ int16_t int_temp;
+
+ rc = lps33hw_get_regs(itf, LPS33HW_PRESS_OUT, 5, fifo_data);
+ if (rc) {
+ return rc;
+ }
+
+ int_press = ((int8_t)fifo_data[2] << 16) |
+ fifo_data[1] << 8 |
+ fifo_data[0];
+ spd->spd_press_is_valid = 1;
+ spd->spd_press = lps33hw_reg_to_pa(int_press);
+
+ int_temp = ((int8_t)fifo_data[4] << 8) | fifo_data[3];
+ std->std_temp_is_valid = 1;
+ std->std_temp = lps33hw_reg_to_degc(int_temp);
+
+ return 0;
+}
+
+static int lps33hw_wait_interrupt(struct lps33hw_int *interrupt)
+{
+ os_error_t error;
+
+ error = os_sem_pend(&interrupt->wait, LPS33HW_MAX_INT_WAIT);
+ if (error == OS_TIMEOUT) {
+ return error;
+ }
+ assert(error == OS_OK);
+
+ return OS_OK;
+}
+
+/**
+ * Wake tasks waiting on interrupt->wait lock
+ *
+ * This call resume task waiting on lps33hw_wake_interrupt lock
+ *
+ * @param the interrupt structure
+ *
+ * @return 0 on success, non-zero on failure
+ */
+static void lps33hw_wake_interrupt(struct lps33hw_int *interrupt)
+{
+ os_error_t error;
+
+ /* Release semaphore to wait_interrupt routine */
+ error = os_sem_release(&interrupt->wait);
+ assert(error == OS_OK);
+}
+
+/**
+ * Wake tasks waiting on interrupt->wait lock
+ *
+ * This call resume task waiting on lps33hw_wake_interrupt lock
+ *
+ * @param the interrupt structure
+ *
+ * @return 0 on success, non-zero on failure
+ */
+static void lps33hw_int_irq_handler(void *arg)
+{
+ struct sensor *sensor = arg;
+ struct lps33hw *lps33hw;
+
+ lps33hw = (struct lps33hw *)SENSOR_GET_DEVICE(sensor);
+ if(lps33hw->pdd.interrupt) {
+ lps33hw_wake_interrupt(lps33hw->pdd.interrupt);
+ }
+}
+
+/**
+ * Read data samples from FIFO
+ *
+ * FIFO store both SENSOR_TYPE_TEMPERATURE
+ * and SENSOR_TYPE_PRESSURE sample data
+ *
+ * @param sensor The sensor object
+ * @param type sensor type bitmask
+ * @param data_func callback register data function
+ * @param data_arg function arguments
+ * @param time_ms
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int lps33hw_stream_read(struct sensor *sensor, sensor_type_t sensor_type,
+ sensor_data_func_t read_func, void *data_arg,
+ uint32_t time_ms)
+{
+ struct lps33hw *lps33hw;
+ struct lps33hw_private_driver_data *pdd;
+ struct sensor_itf *itf;
+ uint8_t fifo_samples;
+ os_time_t time_ticks;
+ os_time_t stop_ticks = 0;
+ int rc;
+ struct sensor_temp_data std;
+ struct sensor_press_data spd;
+
+ /* Temperature/Pressure only */
+ if (!(sensor_type & SENSOR_TYPE_TEMPERATURE) &&
+ !(sensor_type & SENSOR_TYPE_PRESSURE)) {
+ return SYS_EINVAL;
+ }
+
+ lps33hw = (struct lps33hw *)SENSOR_GET_DEVICE(sensor);
+ if (lps33hw->cfg.read_mode != LPS33HW_READ_STREAM) {
+ return SYS_EINVAL;
+ }
+
+ pdd = &lps33hw->pdd;
+ if (pdd->interrupt) {
+ return SYS_EBUSY;
+ }
+
+ itf = SENSOR_GET_ITF(sensor);
+
+ /* Enable FIFO */
+ rc = lps33hw_set_value(itf, LPS33HW_FIFO_CTRL_MODE,
+ LPS33HW_FIFO_CONTINUOUS);
+ if (rc) {
+ goto err;
+ }
+
+ rc = lps33hw_set_value(itf, LPS33HW_CTRL_REG2_FIFO_EN, 1);
+ if (rc) {
+ goto err;
+ }
+
+ rc = lps33hw_enable_interrupt(sensor, lps33hw_int_irq_handler, sensor);
+ if (rc) {
+ goto err;
+ }
+
+ /* Calculate timeout */
+ if (time_ms > 0) {
+ rc = os_time_ms_to_ticks(time_ms, &time_ticks);
+ if (rc) {
+ goto err;
+ }
+ stop_ticks = os_time_get() + time_ticks;
+ }
+
+ for (;;) {
+ /* Force at least one read for cases when fifo is disabled */
+ rc = lps33hw_wait_interrupt(lps33hw->pdd.interrupt);
+ if (rc) {
+ goto err;
+ }
+
+ rc = lps33hw_get_value(itf, LPS33HW_FIFO_FSS, &fifo_samples);
+ if (rc) {
+ goto err;
+ }
+
+ if (fifo_samples == 0) {
+ continue;
+ }
+
+ do {
+ /* Read fifo samples */
+ rc = lps33hw_read_fifo(itf, &std, &spd);
+ if (rc) {
+ goto err;
+ }
+
+ if (sensor_type & SENSOR_TYPE_PRESSURE) {
+ rc = read_func(sensor, data_arg, &spd, SENSOR_TYPE_PRESSURE);
+ if (rc) {
+ goto err;
+ }
+ }
+ if (sensor_type & SENSOR_TYPE_TEMPERATURE) {
+ rc = read_func(sensor, data_arg, &std, SENSOR_TYPE_TEMPERATURE);
+ if (rc) {
+ goto err;
+ }
+ }
+ //fifo_samples--;
+ } while (--fifo_samples > 0);
+
+ if (time_ms > 0 && OS_TIME_TICK_GT(os_time_get(), stop_ticks)) {
+ break;
+ }
+ }
+
+err:
+ /* Disable FIFO */
+ rc |= lps33hw_set_value(itf, LPS33HW_FIFO_CTRL_MODE,
+ LPS33HW_FIFO_BYPASS);
+
+ lps33hw_disable_interrupt(sensor);
+
+ return rc;
+}
+
+/**
+ * Sensor data read
+ *
+ * @param sensor The sensor object
+ * @param type sensor type bitmask
+ * @param data_func callback register data function
+ * @param data_arg function arguments
+ * @param timeout in ms
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+static int
+lps33hw_sensor_read(struct sensor *sensor, sensor_type_t type,
+ sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
+{
+ struct lps33hw *lps33hw = (struct lps33hw *)SENSOR_GET_DEVICE(sensor);
+
+ if (lps33hw->cfg.read_mode == LPS33HW_READ_POLL) {
+ return lps33hw_sensor_read_poll(sensor, type, data_func, data_arg, timeout);
+ }
+
+ return lps33hw_stream_read(sensor, type, data_func, data_arg, timeout);
+}
static int
lps33hw_sensor_set_config(struct sensor *sensor, void *cfg)
@@ -1173,7 +1434,10 @@ static int
lps33hw_sensor_get_config(struct sensor *sensor, sensor_type_t type,
struct sensor_cfg *cfg)
{
- /* If the read isn't looking for pressure, don't do anything. */
+ /*
+ * If the read isn't looking for pressure or temperature
+ * don't do anything.
+ */
if (!(type & (SENSOR_TYPE_PRESSURE | SENSOR_TYPE_TEMPERATURE))) {
return SYS_EINVAL;
}
diff --git a/hw/drivers/sensors/lps33hw/src/lps33hw_priv.h b/hw/drivers/sensors/lps33hw/src/lps33hw_priv.h
index 0644ff0..77ed04e 100644
--- a/hw/drivers/sensors/lps33hw/src/lps33hw_priv.h
+++ b/hw/drivers/sensors/lps33hw/src/lps33hw_priv.h
@@ -24,9 +24,13 @@
extern "C" {
#endif
+/* Max time to wait for interrupt */
+#define LPS33HW_MAX_INT_WAIT (4 * OS_TICKS_PER_SEC)
+
enum lps33hw_registers {
LPS33HW_INTERRUPT_CFG = 0x0b,
LPS33HW_THS_P = 0x0c,
+ LPS33HW_IF_CTRL = 0x0e,
LPS33HW_WHO_AM_I = 0x0f,
LPS33HW_CTRL_REG1 = 0x10,
LPS33HW_CTRL_REG2 = 0x11,
@@ -43,6 +47,11 @@ enum lps33hw_registers {
LPS33HW_LPFP_RES = 0x33
};
+enum lps33hw_fifo_mode {
+ LPS33HW_FIFO_BYPASS = 0x00,
+ LPS33HW_FIFO_CONTINUOUS = 0x02,
+};
+
/* registers */
struct lps33hw_register_value {
uint8_t reg;
@@ -85,8 +94,13 @@ LPS33HW_REGISTER_VALUE(LPS33HW_CTRL_REG3, LPS33HW_CTRL_REG3_F_FSS5, 5, 0x20);
LPS33HW_REGISTER_VALUE(LPS33HW_CTRL_REG3, LPS33HW_CTRL_REG3_F_FTH, 4, 0x10);
LPS33HW_REGISTER_VALUE(LPS33HW_CTRL_REG3, LPS33HW_CTRL_REG3_F_OVR, 3, 0x08);
LPS33HW_REGISTER_VALUE(LPS33HW_CTRL_REG3, LPS33HW_CTRL_REG3_DRDY, 2, 0x04);
+LPS33HW_REGISTER_VALUE(LPS33HW_CTRL_REG3, LPS33HW_CTRL_REG3_FIFO_WTM, 4, 0x10);
LPS33HW_REGISTER_VALUE(LPS33HW_CTRL_REG3, LPS33HW_CTRL_REG3_INT_S, 0, 0x03);
+LPS33HW_REGISTER_VALUE(LPS33HW_FIFO_CTRL, LPS33HW_FIFO_CTRL_MODE, 5, 0xe0);
+LPS33HW_REGISTER_VALUE(LPS33HW_FIFO_CTRL, LPS33HW_FIFO_WTM_THR, 0, 0x1f);
+LPS33HW_REGISTER_VALUE(LPS33HW_FIFO_STATUS, LPS33HW_FIFO_FSS, 0, 0x3f);
+
LPS33HW_REGISTER_VALUE(LPS33HW_RES_CONF, LPS33HW_CTRL_RES_CONF_LC_EN, 0, 0x01);
LPS33HW_REGISTER_VALUE(LPS33HW_INT_SOURCE, LPS33HW_INT_SOURCE_BOOT_STATUS, 7, 0x80);
diff --git a/hw/drivers/sensors/lps33hw/syscfg.yml b/hw/drivers/sensors/lps33hw/syscfg.yml
index 69349a8..05a6736 100644
--- a/hw/drivers/sensors/lps33hw/syscfg.yml
+++ b/hw/drivers/sensors/lps33hw/syscfg.yml
@@ -48,6 +48,14 @@ syscfg.defs:
description: 'Enables one shot mode on the sensor'
value: 0
+ LPS33HW_INT_CFG_ACTIVE:
+ description: 'Set 0 for active-low, 1 for active-high'
+ value: 1
+
+ LPS33HW_INT_PIN_HOST:
+ description: 'Interrupt pin number on host device connected to INT_DRDY on device'
+ value: -1
+
### Log settings.
LPS33HW_LOG_MODULE: