Skip to content

Commit cd065bd

Browse files
Kamil GaworKamil Gawor
authored andcommitted
driver: gpio_led: Software LED blink
Add software LED blink feature for each defined LED. Blink funcionality uses software timer. Signed-off-by: Kamil Gawor <Kamil.Gawor@nordicsemi.no>
1 parent d30f4dc commit cd065bd

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

drivers/led/Kconfig.led_gpio

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ config LED_GPIO
1111

1212
if LED_GPIO
1313

14+
config LED_SOFTWARE_BLINK
15+
bool "Software blink"
16+
help
17+
Support for an LED software blink based on
18+
system timers
19+
1420
module = LED_GPIO
1521
module-str = LED GPIO
1622
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"

drivers/led/led_gpio.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ LOG_MODULE_REGISTER(led_gpio, CONFIG_LED_GPIO_LOG_LEVEL);
2020
DT_LABEL(node_id), \
2121
DT_PROP(node_id, id) \
2222
},
23+
#define LED_SW_BLINK BIT(0)
24+
#define LED_BLINK_DISABLE BIT(1)
2325

2426
struct gpio_cfg {
2527
const char *port;
@@ -36,6 +38,13 @@ struct led_dts_cfg {
3638
struct led_gpio_data {
3739
struct device *gpio_dev;
3840
const struct led_dts_cfg *cfg;
41+
#if defined(CONFIG_LED_SOFTWARE_BLINK)
42+
struct k_timer timer;
43+
atomic_t flags;
44+
uint32_t blink_delay_on;
45+
uint32_t blink_delay_off;
46+
bool next_state;
47+
#endif
3948
bool state;
4049
};
4150

@@ -92,6 +101,18 @@ static int gpio_led_set_no_delay(struct led_gpio_data *data, bool state)
92101

93102
static int gpio_led_set(struct led_gpio_data *data, bool state)
94103
{
104+
#if defined(CONFIG_LED_SOFTWARE_BLINK)
105+
if (atomic_test_bit(&data->flags, LED_SW_BLINK)) {
106+
data->next_state = state;
107+
108+
atomic_set_bit(&data->flags, LED_BLINK_DISABLE);
109+
k_timer_start(&data->timer, K_NO_WAIT, K_NO_WAIT);
110+
111+
return 0;
112+
113+
}
114+
#endif /* defined(CONFIG_LED_SOFTWARE_BLINK) */
115+
95116
return gpio_led_set_no_delay(data, state);
96117
}
97118

@@ -117,7 +138,78 @@ static int gpio_led_off(struct device *dev, uint32_t led)
117138
return gpio_led_set(data, false);
118139
}
119140

141+
#if defined(CONFIG_LED_SOFTWARE_BLINK)
142+
static void stop_sw_blink(struct led_gpio_data *data)
143+
{
144+
k_timer_stop(&data->timer);
145+
data->blink_delay_on = 0;
146+
data->blink_delay_off = 0;
147+
atomic_clear_bit(&data->flags, LED_SW_BLINK);
148+
}
149+
150+
static void led_timer_handler(struct k_timer *timer)
151+
{
152+
struct led_gpio_data *data;
153+
uint32_t delay;
154+
bool state;
155+
int err;
156+
157+
data = CONTAINER_OF(timer, struct led_gpio_data, timer);
158+
159+
if (atomic_test_and_clear_bit(&data->flags, LED_BLINK_DISABLE)) {
160+
stop_sw_blink(data);
161+
gpio_led_set_no_delay(data, data->next_state);
162+
163+
return;
164+
}
165+
166+
if (data->state) {
167+
delay = data->blink_delay_off;
168+
state = 0;
169+
} else {
170+
delay = data->blink_delay_on;
171+
state = 1;
172+
}
173+
174+
err = gpio_led_set_no_delay(data, state);
175+
if (err) {
176+
LOG_DBG("%s blink error: %d", data->cfg->label, err);
177+
}
178+
179+
k_timer_start(&data->timer, K_MSEC(delay), K_NO_WAIT);
180+
}
181+
182+
static int gpio_led_blink(struct device *dev, uint32_t led,
183+
uint32_t delay_on, uint32_t delay_off)
184+
{
185+
struct led_gpio_data *data = led_parameters_get(dev, led);
186+
187+
if (!delay_on) {
188+
return gpio_led_off(dev, led);
189+
}
190+
191+
if (!delay_off) {
192+
return gpio_led_on(dev, led);
193+
}
194+
195+
data->blink_delay_on = delay_on;
196+
data->blink_delay_off = delay_off;
197+
198+
atomic_set_bit(&data->flags, LED_SW_BLINK);
199+
200+
LOG_DBG("%s blink start, delay on: %d, delay off: %d",
201+
data->cfg->label, delay_on, delay_off);
202+
203+
k_timer_start(&data->timer, K_NO_WAIT, K_NO_WAIT);
204+
205+
return 0;
206+
}
207+
#endif /* defined(CONFIG_LED_SOFTWARE_BLINK) */
208+
120209
static const struct led_driver_api led_api = {
210+
#if defined(CONFIG_LED_SOFTWARE_BLINK)
211+
.blink = gpio_led_blink,
212+
#endif
121213
.on = gpio_led_on,
122214
.off = gpio_led_off,
123215
};
@@ -149,6 +241,10 @@ static int gpio_led_init(struct device *dev)
149241

150242

151243
data[i].cfg = &cfg->led[i];
244+
245+
#if defined(CONFIG_LED_SOFTWARE_BLINK)
246+
k_timer_init(&data[i].timer, led_timer_handler, NULL);
247+
#endif
152248
}
153249

154250
return 0;

0 commit comments

Comments
 (0)