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 | /* 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 */ #define DT_DRV_COMPAT st_stts751 #include <zephyr/kernel.h> #include <zephyr/drivers/sensor.h> #include <zephyr/drivers/gpio.h> #include <zephyr/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(const struct device *dev, int enable) { struct stts751_data *stts751 = dev->data; uint8_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(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { struct stts751_data *stts751 = dev->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(const struct device *dev) { struct stts751_data *stts751 = dev->data; const struct stts751_config *cfg = dev->config; 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(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { struct stts751_data *stts751 = CONTAINER_OF(cb, struct stts751_data, gpio_cb); const struct stts751_config *cfg = stts751->dev->config; 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(struct stts751_data *stts751) { while (1) { k_sem_take(&stts751->gpio_sem, K_FOREVER); stts751_handle_interrupt(stts751->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(const struct device *dev) { struct stts751_data *stts751 = dev->data; const struct stts751_config *cfg = dev->config; 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, K_SEM_MAX_LIMIT); k_thread_create(&stts751->thread, stts751->thread_stack, CONFIG_STTS751_THREAD_STACK_SIZE, (k_thread_entry_t)stts751_thread, stts751, NULL, 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; #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); } |