Skip to content

Commit b5883d3

Browse files
pdgendtjhedberg
authored andcommitted
modules: lvgl: Provide API mutex (un)locking
Add helper functions that can be used to lock/unlock the LVGL's internal mutex before calling API funcions. Signed-off-by: Pieter De Gendt <[email protected]>
1 parent af529f4 commit b5883d3

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

modules/lvgl/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,15 @@ config LV_Z_INIT_PRIORITY
158158
help
159159
Priority used for the automatic initialization of LVGL.
160160

161+
config LV_Z_LVGL_MUTEX
162+
bool "Provide LVGL API mutex (un)locking functions"
163+
help
164+
LVGL API functions are not thread-safe, provide functions for locking and unlocking.
165+
161166
config LV_Z_RUN_LVGL_ON_WORKQUEUE
162167
bool "Use a dedicated workqueue to run LVGL core"
163168
imply LV_Z_AUTO_INIT
169+
imply LV_Z_LVGL_MUTEX
164170
help
165171
Runs the LVGL in a separate workqueue automatically
166172
without requiring user to add a timed loop for that. User can

modules/lvgl/include/lvgl_zephyr.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,58 @@ struct k_work_q *lvgl_get_workqueue(void);
4646

4747
#endif /* CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE */
4848

49+
50+
#if (defined(CONFIG_LV_Z_LVGL_MUTEX) && !defined(CONFIG_LV_Z_USE_OSAL)) || defined(__DOXYGEN__)
51+
/**
52+
* @brief Lock internal mutex before accessing LVGL API.
53+
*
54+
* @details LVGL API is not thread-safe. Therefore, before accessing any
55+
* API function, you need to lock the internal mutex, to prevent the
56+
* LVGL thread from pre-empting the API call.
57+
*/
58+
void lvgl_lock(void);
59+
60+
/**
61+
* @brief Try to lock internal mutex before accessing LVGL API.
62+
*
63+
* @details This function behaves like lvgl_lock(), provided that
64+
* the internal mutex is unlocked. Otherwise, it returns false without
65+
* waiting.
66+
*/
67+
bool lvgl_trylock(void);
68+
69+
/**
70+
* @brief Unlock internal mutex after accessing LVGL API.
71+
*/
72+
void lvgl_unlock(void);
73+
74+
#elif defined(CONFIG_LV_Z_LVGL_MUTEX) && defined(CONFIG_LV_Z_USE_OSAL)
75+
76+
#include <osal/lv_os.h>
77+
78+
static inline void lvgl_lock(void)
79+
{
80+
lv_lock();
81+
}
82+
83+
static inline bool lvgl_trylock(void)
84+
{
85+
return lv_lock_isr() == LV_RESULT_OK;
86+
}
87+
88+
static inline void lvgl_unlock(void)
89+
{
90+
lv_unlock();
91+
}
92+
93+
#else /* CONFIG_LV_Z_LVGL_MUTEX */
94+
95+
#define lvgl_lock(...) (void)0
96+
#define lvgl_trylock(...) true
97+
#define lvgl_unlock(...) (void)0
98+
99+
#endif /* CONFIG_LV_Z_LVGL_MUTEX */
100+
49101
#ifdef __cplusplus
50102
}
51103
#endif

modules/lvgl/lvgl.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ static struct k_work_q lvgl_workqueue;
227227
static void lvgl_timer_handler_work(struct k_work *work)
228228
{
229229
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
230-
uint32_t wait_time = lv_timer_handler();
230+
uint32_t wait_time;
231+
232+
lvgl_lock();
233+
wait_time = lv_timer_handler();
234+
lvgl_unlock();
231235

232236
/* schedule next timer verification */
233237
if (wait_time == LV_NO_TIMER_READY) {
@@ -244,6 +248,27 @@ struct k_work_q *lvgl_get_workqueue(void)
244248
}
245249
#endif /* CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE */
246250

251+
#if defined(CONFIG_LV_Z_LVGL_MUTEX) && !defined(CONFIG_LV_Z_USE_OSAL)
252+
253+
static K_MUTEX_DEFINE(lvgl_mutex);
254+
255+
void lvgl_lock(void)
256+
{
257+
(void)k_mutex_lock(&lvgl_mutex, K_FOREVER);
258+
}
259+
260+
bool lvgl_trylock(void)
261+
{
262+
return k_mutex_lock(&lvgl_mutex, K_NO_WAIT) == 0;
263+
}
264+
265+
void lvgl_unlock(void)
266+
{
267+
(void)k_mutex_unlock(&lvgl_mutex);
268+
}
269+
270+
#endif /* CONFIG_LV_Z_LVGL_MUTEX */
271+
247272
void lv_mem_init(void)
248273
{
249274
#ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP

0 commit comments

Comments
 (0)