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: