Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | /* ST Microelectronics STTS751 temperature sensor * * Copyright (c) 2019 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 * * Datasheet: * https://www.st.com/resource/en/datasheet/stts751.pdf */ #include <kernel.h> #include <drivers/sensor.h> #include <drivers/gpio.h> #include <logging/log.h> #include "stts751.h" LOG_MODULE_DECLARE(STTS751, CONFIG_SENSOR_LOG_LEVEL); /** * stts751_enable_int - enable selected int pin to generate interrupt */ static int stts751_enable_int(struct device *dev, int enable) { struct stts751_data *stts751 = dev->driver_data; u8_t en = (enable) ? 0 : 1; return stts751_pin_event_route_set(stts751->ctx, en); } /** * stts751_trigger_set - link external trigger to event data ready */ int stts751_trigger_set(struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { struct stts751_data *stts751 = dev->driver_data; if (trig->chan == SENSOR_CHAN_ALL) { stts751->thsld_handler = handler; if (handler) { return stts751_enable_int(dev, 1); } else { return stts751_enable_int(dev, 0); } } return -ENOTSUP; } /** * stts751_handle_interrupt - handle the thsld event * read data and call handler if registered any */ static void stts751_handle_interrupt(void *arg) { struct device *dev = arg; struct stts751_data *stts751 = dev->driver_data; const struct stts751_config *cfg = dev->config->config_info; struct sensor_trigger thsld_trigger = { .type = SENSOR_TRIG_THRESHOLD, }; stts751_status_t status; stts751_status_reg_get(stts751->ctx, &status); if (stts751->thsld_handler != NULL && (status.t_high || status.t_low)) { stts751->thsld_handler(dev, &thsld_trigger); } gpio_pin_interrupt_configure(stts751->gpio, cfg->event_pin, GPIO_INT_EDGE_TO_ACTIVE); } static void stts751_gpio_callback(struct device *dev, struct gpio_callback *cb, u32_t pins) { const struct stts751_config *cfg = dev->config->config_info; struct stts751_data *stts751 = CONTAINER_OF(cb, struct stts751_data, gpio_cb); ARG_UNUSED(pins); gpio_pin_interrupt_configure(dev, cfg->event_pin, GPIO_INT_DISABLE); #if defined(CONFIG_STTS751_TRIGGER_OWN_THREAD) k_sem_give(&stts751->gpio_sem); #elif defined(CONFIG_STTS751_TRIGGER_GLOBAL_THREAD) k_work_submit(&stts751->work); #endif /* CONFIG_STTS751_TRIGGER_OWN_THREAD */ } #ifdef CONFIG_STTS751_TRIGGER_OWN_THREAD static void stts751_thread(int dev_ptr, int unused) { struct device *dev = INT_TO_POINTER(dev_ptr); struct stts751_data *stts751 = dev->driver_data; ARG_UNUSED(unused); while (1) { k_sem_take(&stts751->gpio_sem, K_FOREVER); stts751_handle_interrupt(dev); } } #endif /* CONFIG_STTS751_TRIGGER_OWN_THREAD */ #ifdef CONFIG_STTS751_TRIGGER_GLOBAL_THREAD static void stts751_work_cb(struct k_work *work) { struct stts751_data *stts751 = CONTAINER_OF(work, struct stts751_data, work); stts751_handle_interrupt(stts751->dev); } #endif /* CONFIG_STTS751_TRIGGER_GLOBAL_THREAD */ int stts751_init_interrupt(struct device *dev) { struct stts751_data *stts751 = dev->driver_data; const struct stts751_config *cfg = dev->config->config_info; int ret; /* setup data ready gpio interrupt */ stts751->gpio = device_get_binding(cfg->event_port); if (stts751->gpio == NULL) { LOG_DBG("Cannot get pointer to %s device", cfg->event_port); return -EINVAL; } #if defined(CONFIG_STTS751_TRIGGER_OWN_THREAD) k_sem_init(&stts751->gpio_sem, 0, UINT_MAX); k_thread_create(&stts751->thread, stts751->thread_stack, CONFIG_STTS751_THREAD_STACK_SIZE, (k_thread_entry_t)stts751_thread, dev, 0, NULL, K_PRIO_COOP(CONFIG_STTS751_THREAD_PRIORITY), 0, K_NO_WAIT); #elif defined(CONFIG_STTS751_TRIGGER_GLOBAL_THREAD) stts751->work.handler = stts751_work_cb; stts751->dev = dev; #endif /* CONFIG_STTS751_TRIGGER_OWN_THREAD */ ret = gpio_pin_configure(stts751->gpio, cfg->event_pin, GPIO_INPUT | cfg->int_flags); if (ret < 0) { LOG_DBG("Could not configure gpio"); return ret; } gpio_init_callback(&stts751->gpio_cb, stts751_gpio_callback, BIT(cfg->event_pin)); if (gpio_add_callback(stts751->gpio, &stts751->gpio_cb) < 0) { LOG_DBG("Could not set gpio callback"); return -EIO; } /* Enable interrupt on high temperature */ float temp_hi = (float) CONFIG_STTS751_TEMP_HI_THRESHOLD; float temp_lo = (float) CONFIG_STTS751_TEMP_LO_THRESHOLD; stts751_high_temperature_threshold_set(stts751->ctx, stts751_from_celsius_to_lsb(temp_hi)); stts751_low_temperature_threshold_set(stts751->ctx, stts751_from_celsius_to_lsb(temp_lo)); return gpio_pin_interrupt_configure(stts751->gpio, cfg->event_pin, GPIO_INT_EDGE_TO_ACTIVE); } |