Skip to content

Commit c81e21b

Browse files
committed
drivers: led: gpio: add software blinking
Add new CONFIG_LED_GPIO_BLINK to add GPIO LEDs software blinking. Signed-off-by: Benjamin Lemouzy <blemouzy@centralp.fr>
1 parent eb447c4 commit c81e21b

File tree

2 files changed

+98
-2
lines changed

2 files changed

+98
-2
lines changed

drivers/led/Kconfig.gpio

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@ config LED_GPIO
77
depends on GPIO && DT_HAS_GPIO_LEDS_ENABLED
88
help
99
Enable driver for GPIO LEDs.
10+
11+
if LED_GPIO
12+
13+
config LED_GPIO_BLINK
14+
bool "Software LED blinking"
15+
default n
16+
help
17+
Enable software LED blinking.
18+
19+
endif # LED_GPIO

drivers/led/led_gpio.c

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,37 @@ struct led_gpio_config {
2424
const struct gpio_dt_spec *led;
2525
};
2626

27+
#ifdef CONFIG_LED_GPIO_BLINK
28+
struct led_gpio_blink_data {
29+
uint32_t delay_on;
30+
uint32_t delay_off;
31+
struct k_timer timer;
32+
};
33+
#endif /* CONFIG_LED_GPIO_BLINK */
34+
35+
struct led_gpio_led_data {
36+
bool is_on;
37+
#ifdef CONFIG_LED_GPIO_BLINK
38+
struct led_gpio_blink_data blink;
39+
#endif /* CONFIG_LED_GPIO_BLINK */
40+
};
41+
42+
struct led_gpio_data {
43+
struct led_gpio_led_data *led;
44+
};
45+
2746
static int led_gpio_set_brightness(const struct device *dev, uint32_t led, uint8_t value)
2847
{
29-
3048
const struct led_gpio_config *config = dev->config;
3149
const struct gpio_dt_spec *led_gpio;
50+
struct led_gpio_data *data = dev->data;
3251

3352
if ((led >= config->num_leds) || (value > 100)) {
3453
return -EINVAL;
3554
}
3655

3756
led_gpio = &config->led[led];
57+
data->led[led].is_on = value > 0;
3858

3959
return gpio_pin_set_dt(led_gpio, value > 0);
4060
}
@@ -49,9 +69,59 @@ static int led_gpio_off(const struct device *dev, uint32_t led)
4969
return led_gpio_set_brightness(dev, led, 0);
5070
}
5171

72+
#ifdef CONFIG_LED_GPIO_BLINK
73+
static int led_gpio_blink(const struct device *dev, uint32_t led, uint32_t delay_on,
74+
uint32_t delay_off)
75+
{
76+
const struct led_gpio_config *config = dev->config;
77+
struct led_gpio_data *data = dev->data;
78+
79+
if (led >= config->num_leds) {
80+
return -EINVAL;
81+
}
82+
83+
data->led[led].blink.delay_on = delay_on;
84+
data->led[led].blink.delay_off = delay_off;
85+
if ((delay_on != 0) && (delay_off != 0)) {
86+
k_timer_start(&data->led[led].blink.timer, K_MSEC(delay_on), K_NO_WAIT);
87+
} else {
88+
k_timer_stop(&data->led[led].blink.timer);
89+
}
90+
91+
return 0;
92+
}
93+
94+
static void blink_timeout(struct k_timer *timer)
95+
{
96+
const struct device *dev = k_timer_user_data_get(timer);
97+
const struct led_gpio_config *config = dev->config;
98+
struct led_gpio_data *data = dev->data;
99+
struct led_gpio_blink_data *blink_data =
100+
CONTAINER_OF(timer, struct led_gpio_blink_data, timer);
101+
struct led_gpio_led_data *led_data =
102+
CONTAINER_OF(blink_data, struct led_gpio_led_data, blink);
103+
uint32_t led = ARRAY_INDEX(data->led, led_data);
104+
105+
if (led >= config->num_leds) {
106+
return;
107+
}
108+
109+
if (led_data->is_on) {
110+
led_gpio_off(dev, led);
111+
k_timer_start(timer, K_MSEC(led_data->blink.delay_off), K_NO_WAIT);
112+
} else {
113+
led_gpio_on(dev, led);
114+
k_timer_start(timer, K_MSEC(led_data->blink.delay_on), K_NO_WAIT);
115+
}
116+
}
117+
#endif /* CONFIG_LED_GPIO_BLINK */
118+
52119
static int led_gpio_init(const struct device *dev)
53120
{
54121
const struct led_gpio_config *config = dev->config;
122+
#ifdef CONFIG_LED_GPIO_BLINK
123+
struct led_gpio_data *data = dev->data;
124+
#endif /* CONFIG_LED_GPIO_BLINK */
55125
int err = 0;
56126

57127
if (!config->num_leds) {
@@ -72,6 +142,11 @@ static int led_gpio_init(const struct device *dev)
72142
LOG_ERR("%s: GPIO device not ready", dev->name);
73143
err = -ENODEV;
74144
}
145+
146+
#ifdef CONFIG_LED_GPIO_BLINK
147+
k_timer_init(&data->led[i].blink.timer, blink_timeout, NULL);
148+
k_timer_user_data_set(&data->led[i].blink.timer, (void *)dev);
149+
#endif /* CONFIG_LED_GPIO_BLINK */
75150
}
76151

77152
return err;
@@ -80,6 +155,9 @@ static int led_gpio_init(const struct device *dev)
80155
static const struct led_driver_api led_gpio_api = {
81156
.on = led_gpio_on,
82157
.off = led_gpio_off,
158+
#ifdef CONFIG_LED_GPIO_BLINK
159+
.blink = led_gpio_blink,
160+
#endif /* CONFIG_LED_GPIO_BLINK */
83161
.set_brightness = led_gpio_set_brightness,
84162
};
85163

@@ -94,8 +172,16 @@ static const struct led_gpio_config led_gpio_config_##i = { \
94172
.led = gpio_dt_spec_##i, \
95173
}; \
96174
\
175+
static struct led_gpio_led_data led_gpio_led_data_##i[ARRAY_SIZE(gpio_dt_spec_##i)] = { \
176+
{.is_on = false}, \
177+
}; \
178+
\
179+
static struct led_gpio_data led_gpio_data_##i = { \
180+
.led = led_gpio_led_data_##i, \
181+
}; \
182+
\
97183
DEVICE_DT_INST_DEFINE(i, &led_gpio_init, NULL, \
98-
NULL, &led_gpio_config_##i, \
184+
&led_gpio_data_##i, &led_gpio_config_##i, \
99185
POST_KERNEL, CONFIG_LED_INIT_PRIORITY, \
100186
&led_gpio_api);
101187

0 commit comments

Comments
 (0)