|
| 1 | +/* |
| 2 | + * Copyright (c) 2024 Nordic Semiconductor ASA |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + */ |
| 5 | + |
| 6 | +#define DT_DRV_COMPAT blink_gpio_led |
| 7 | + |
| 8 | +#include <zephyr/device.h> |
| 9 | + |
| 10 | +#include <zephyr/devicetree.h> |
| 11 | +#include <zephyr/drivers/gpio.h> |
| 12 | +#include <zephyr/kernel.h> |
| 13 | +#include <zephyr/logging/log.h> |
| 14 | + |
| 15 | +#include <app/drivers/blink.h> |
| 16 | + |
| 17 | +LOG_MODULE_REGISTER(blink_gpio_led, CONFIG_BLINK_LOG_LEVEL); |
| 18 | + |
| 19 | +struct blink_gpio_led_data { |
| 20 | + struct k_timer timer; |
| 21 | +}; |
| 22 | + |
| 23 | +struct blink_gpio_led_config { |
| 24 | + struct gpio_dt_spec led; |
| 25 | + unsigned int period_ms; |
| 26 | +}; |
| 27 | + |
| 28 | +static void blink_gpio_led_on_timer_expire(struct k_timer *timer) |
| 29 | +{ |
| 30 | + const struct device *dev = k_timer_user_data_get(timer); |
| 31 | + const struct blink_gpio_led_config *config = dev->config; |
| 32 | + int ret; |
| 33 | + |
| 34 | + ret = gpio_pin_toggle_dt(&config->led); |
| 35 | + if (ret < 0) { |
| 36 | + LOG_ERR("Could not toggle LED GPIO (%d)", ret); |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +static int blink_gpio_led_set_period_ms(const struct device *dev, |
| 41 | + unsigned int period_ms) |
| 42 | +{ |
| 43 | + const struct blink_gpio_led_config *config = dev->config; |
| 44 | + struct blink_gpio_led_data *data = dev->data; |
| 45 | + |
| 46 | + if (period_ms == 0) { |
| 47 | + k_timer_stop(&data->timer); |
| 48 | + return gpio_pin_set_dt(&config->led, 0); |
| 49 | + } |
| 50 | + |
| 51 | + k_timer_start(&data->timer, K_MSEC(period_ms), K_MSEC(period_ms)); |
| 52 | + |
| 53 | + return 0; |
| 54 | +} |
| 55 | + |
| 56 | +static const struct blink_driver_api blink_gpio_led_api = { |
| 57 | + .set_period_ms = &blink_gpio_led_set_period_ms, |
| 58 | +}; |
| 59 | + |
| 60 | +static int blink_gpio_led_init(const struct device *dev) |
| 61 | +{ |
| 62 | + const struct blink_gpio_led_config *config = dev->config; |
| 63 | + struct blink_gpio_led_data *data = dev->data; |
| 64 | + int ret; |
| 65 | + |
| 66 | + if (!gpio_is_ready_dt(&config->led)) { |
| 67 | + LOG_ERR("LED GPIO not ready"); |
| 68 | + return -ENODEV; |
| 69 | + } |
| 70 | + |
| 71 | + ret = gpio_pin_configure_dt(&config->led, GPIO_OUTPUT_INACTIVE); |
| 72 | + if (ret < 0) { |
| 73 | + LOG_ERR("Could not configure LED GPIO (%d)", ret); |
| 74 | + return ret; |
| 75 | + } |
| 76 | + |
| 77 | + k_timer_init(&data->timer, blink_gpio_led_on_timer_expire, NULL); |
| 78 | + k_timer_user_data_set(&data->timer, (void *)dev); |
| 79 | + |
| 80 | + if (config->period_ms > 0) { |
| 81 | + k_timer_start(&data->timer, K_MSEC(config->period_ms), |
| 82 | + K_MSEC(config->period_ms)); |
| 83 | + } |
| 84 | + |
| 85 | + return 0; |
| 86 | +} |
| 87 | + |
| 88 | +#define BLINK_GPIO_LED_DEFINE(inst) \ |
| 89 | + static struct blink_gpio_led_data data##inst; \ |
| 90 | + \ |
| 91 | + static const struct blink_gpio_led_config config##inst = { \ |
| 92 | + .led = GPIO_DT_SPEC_INST_GET(inst, led_gpios), \ |
| 93 | + .period_ms = DT_INST_PROP_OR(inst, blink_period_ms, 0U), \ |
| 94 | + }; \ |
| 95 | + \ |
| 96 | + DEVICE_DT_INST_DEFINE(inst, blink_gpio_led_init, NULL, &data##inst, \ |
| 97 | + &config##inst, POST_KERNEL, \ |
| 98 | + CONFIG_BLINK_INIT_PRIORITY, \ |
| 99 | + &blink_gpio_led_api); |
| 100 | + |
| 101 | +DT_INST_FOREACH_STATUS_OKAY(BLINK_GPIO_LED_DEFINE) |
0 commit comments