@@ -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
2426struct gpio_cfg {
2527 const char * port ;
@@ -36,6 +38,13 @@ struct led_dts_cfg {
3638struct 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
93102static 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+
120209static 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