前言
在LVGL使用过程中经常发现会意外死机,然后去git下载了一份LVGL 8.3的源码 然后才看到官方的有关OS的相关说明。
如果在LVGL的线程外操作LVGL对象是不安全的,很容易造成死机现象。
官方的OS.md
# Operating system and interrupts
LVGL is **not thread-safe** by default.
However, in the following conditions it's valid to call LVGL related functions:
- In *events*. Learn more in [Events](/overview/event).
- In *lv_timer*. Learn more in [Timers](/overview/timer).
## Tasks and threads
If you need to use real tasks or threads, you need a mutex which should be invoked before the call of `lv_timer_handler` and released after it.
Also, you have to use the same mutex in other tasks and threads around every LVGL (`lv_...`) related function call and code.
This way you can use LVGL in a real multitasking environment. Just make use of a mutex to avoid the concurrent calling of LVGL functions.
Here is some pseudocode to illustrate the concept:
```c
static mutex_t lvgl_mutex;
void lvgl_thread(void)
{
while(1) {
mutex_lock(&lvgl_mutex);
lv_task_handler();
mutex_unlock(&lvgl_mutex);
thread_sleep(10); /* sleep for 10 ms */
}
}
void other_thread(void)
{
/* You must always hold the mutex while using LVGL APIs */
mutex_lock(&lvgl_mutex);
lv_obj_t *img = lv_img_create(lv_scr_act());
mutex_unlock(&lvgl_mutex);
while(1) {
mutex_lock(&lvgl_mutex);
/* change to the next image */
lv_img_set_src(img, next_image);
mutex_unlock(&lvgl_mutex);
thread_sleep(2000);
}
}
```
## Interrupts
Try to avoid calling LVGL functions from interrupt handlers (except `lv_tick_inc()` and `lv_disp_flush_ready()`). But if you need to do this you have to disable the interrupt which uses LVGL functions while `lv_timer_handler` is running.
It's a better approach to simply set a flag or some value in the interrupt, and periodically check it in an LVGL timer (which is run by `lv_timer_handler`).
解读:
# Answer
这段代码是关于如何在多任务环境中使用LVGL(Light and Versatile Graphics Library)的一个说明,重点在于处理线程安全和中断的问题。
### 逐步分解与详细解释
1. **线程安全性说明:**
- 文档首先指出,LVGL默认情况下并不是线程安全的。这意味着如果多个线程或任务同时访问和修改LVGL对象,可能会导致数据竞争和不一致的问题。
- 为了解决这个问题,文档建议在特定条件下调用LVGL相关函数。这些条件包括在事件处理和LVGL定时器回调函数中使用LVGL API。
2. **多任务环境下的使用方法:**
- 如果需要在一个真正的多任务环境中使用LVGL,必须使用互斥锁(mutex)来保护对LVGL的访问。
- 在`lv_timer_handler`调用前后,需要锁定和解锁互斥锁,确保每次只有一个任务或线程可以调用`lv_timer_handler`。
- 对于其他任务或线程中调用的任何LVGL API,也需要使用相同的互斥锁进行保护,以避免多个线程同时访问LVGL导致的问题。
3. **伪代码示例:**
- 提供了一个简单的伪代码示例,以C语言来展示如何在多任务环境中使用LVGL。
- 定义了一个静态的互斥锁`lvgl_mutex`,作为保护LVGL访问的机制。
- `lvgl_thread`函数中,无限循环调用`lv_task_handler`,并在调用前后使用`mutex_lock`和`mutex_unlock`锁定和解锁互斥锁。
- `other_thread`函数中,首先锁定互斥锁以确保线程安全,然后创建一个图像对象`img`,最后解锁互斥锁。之后,该线程每2秒更新一次图像的源,同样在调用LVGL API前后使用互斥锁。
4. **中断处理:**
- 文档建议尽量避免在中断处理程序中直接使用LVGL的API函数,除了`lv_tick_inc()`和`lv_disp_flush_ready()`这两个函数。
- 如果确实需要在中断中调用LVGL函数,需要在`lv_timer_handler`运行时暂时禁用中断,以防止中断处理程序与任务处理程序同时访问LVGL。
- 更好的做法是在中断中设置一个标志或值,然后在LVGL定时器回调中检查这个标志或值。这样可以避免在中断和任务之间直接同步LVGL的调用。
### 总结代码(强调其主要功能)
这段代码的主要功能是解释如何在多任务环境中安全地使用LVGL。它提供了具体的建议和伪代码示例,展示了如何通过使用互斥锁来保护LVGL的访问,从而避免因多线程并发调用导致的线程安全问题。此外,文档还指出了在中断中使用LVGL函数时需要注意的问题,推荐的最佳做法是使用标志而不是直接在中断中调用LVGL函数。