mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-26 19:23:46 +08:00
feat(demos): add demo for the OSAL (#6182)
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
4ab68c5dc1
commit
70ed004ef3
@ -7,8 +7,10 @@ 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 :ref:`events`. -
|
||||
In *lv_timer*. Learn more in :ref:`timer`.
|
||||
functions:
|
||||
|
||||
- In *events*. Learn more in :ref:`events`.
|
||||
- In *lv_timer*. Learn more in :ref:`timer`.
|
||||
|
||||
Tasks and threads
|
||||
-----------------
|
||||
@ -20,19 +22,26 @@ 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.
|
||||
|
||||
LVGL has a built-in mutex which can be used with:
|
||||
- :cpp:func:`lv_lock()` and :cpp:func:`lv_lock_isr()`
|
||||
- :cpp:func:`lv_unlock()`
|
||||
|
||||
These functions are called internally in :cpp:func:`lv_timer_handler`
|
||||
and the users need to call them only from their own therads.
|
||||
|
||||
To enable ``lv_lock/lv_unlock`` ``LV_USE_OS`` needs to be set to other
|
||||
than ``LV_OS_NONE``.
|
||||
|
||||
|
||||
Here is some pseudocode to illustrate the concept:
|
||||
|
||||
.. code:: c
|
||||
|
||||
static mutex_t lvgl_mutex;
|
||||
|
||||
void lvgl_thread(void)
|
||||
{
|
||||
while(1) {
|
||||
uint32_t time_till_next;
|
||||
mutex_lock(&lvgl_mutex);
|
||||
time_till_next = lv_timer_handler();
|
||||
mutex_unlock(&lvgl_mutex);
|
||||
time_till_next = lv_timer_handler(); /*lv_lock/lv_unlock is called internally*/
|
||||
thread_sleep(time_till_next); /* sleep for a while */
|
||||
}
|
||||
}
|
||||
@ -40,15 +49,15 @@ Here is some pseudocode to illustrate the concept:
|
||||
void other_thread(void)
|
||||
{
|
||||
/* You must always hold the mutex while using LVGL APIs */
|
||||
mutex_lock(&lvgl_mutex);
|
||||
lv_lock();
|
||||
lv_obj_t *img = lv_image_create(lv_screen_active());
|
||||
mutex_unlock(&lvgl_mutex);
|
||||
lv_unlock();
|
||||
|
||||
while(1) {
|
||||
mutex_lock(&lvgl_mutex);
|
||||
lv_lock();
|
||||
/* change to the next image */
|
||||
lv_image_set_src(img, next_image);
|
||||
mutex_unlock(&lvgl_mutex);
|
||||
lv_unlock();
|
||||
thread_sleep(2000);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ extern "C" {
|
||||
#include "layouts/lv_example_layout.h"
|
||||
#include "libs/lv_example_libs.h"
|
||||
#include "others/lv_example_others.h"
|
||||
#include "porting/osal/lv_example_osal.h"
|
||||
#include "scroll/lv_example_scroll.h"
|
||||
#include "styles/lv_example_style.h"
|
||||
#include "widgets/lv_example_widgets.h"
|
||||
|
95
examples/porting/osal/lv_example_osal.c
Normal file
95
examples/porting/osal/lv_example_osal.c
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @file lv_example_osal.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_examples.h"
|
||||
|
||||
#if LV_BUILD_EXAMPLES
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void counter_button_event_cb(lv_event_t * e);
|
||||
static void increment_thread_entry(void * user_data);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_thread_sync_t press_sync;
|
||||
static lv_thread_t increment_thread;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_example_osal(void)
|
||||
{
|
||||
lv_obj_t * counter_button;
|
||||
|
||||
counter_button = lv_button_create(lv_screen_active());
|
||||
lv_obj_align(counter_button, LV_ALIGN_CENTER, 0, -15);
|
||||
lv_obj_add_event_cb(counter_button, counter_button_event_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
if(lv_thread_sync_init(&press_sync) != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Error initializing thread sync");
|
||||
}
|
||||
|
||||
if(lv_thread_init(&increment_thread, LV_THREAD_PRIO_MID, increment_thread_entry, 2048, NULL) != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Error initializing thread");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void counter_button_event_cb(lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(e);
|
||||
if(lv_thread_sync_signal(&press_sync) != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Error signaling thread sync");
|
||||
}
|
||||
}
|
||||
|
||||
static void increment_thread_entry(void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
lv_obj_t * counter_label;
|
||||
uint32_t press_count = 0;
|
||||
|
||||
lv_lock();
|
||||
counter_label = lv_label_create(lv_scr_act());
|
||||
lv_obj_align(counter_label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_label_set_text_fmt(counter_label, "Pressed %u times", press_count);
|
||||
lv_unlock();
|
||||
|
||||
while(true) {
|
||||
if(lv_thread_sync_wait(&press_sync) != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Error awaiting thread sync");
|
||||
}
|
||||
press_count += 1;
|
||||
|
||||
lv_lock();
|
||||
lv_label_set_text_fmt(counter_label, "Pressed %u times", press_count);
|
||||
lv_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
38
examples/porting/osal/lv_example_osal.h
Normal file
38
examples/porting/osal/lv_example_osal.h
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file lv_example_osal.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_EXAMPLE_OSAL_H
|
||||
#define LV_EXAMPLE_OSAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void lv_example_osal(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_EXAMPLE_OSAL_H*/
|
@ -1028,6 +1028,7 @@
|
||||
|
||||
/*Vector graphic demo*/
|
||||
#define LV_USE_DEMO_VECTOR_GRAPHIC 0
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
@ -27,6 +27,7 @@ extern "C" {
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../osal/lv_os.h"
|
||||
#include "../others/sysmon/lv_sysmon.h"
|
||||
#include "../stdlib/builtin/lv_tlsf.h"
|
||||
|
||||
@ -210,6 +211,10 @@ typedef struct _lv_global_t {
|
||||
struct _lv_nuttx_ctx_t * nuttx_ctx;
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
lv_mutex_t lv_general_mutex;
|
||||
#endif
|
||||
|
||||
void * user_data;
|
||||
} lv_global_t;
|
||||
|
||||
|
@ -3349,6 +3349,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*----------------------------------
|
||||
* End of parsing lv_conf_template.h
|
||||
-----------------------------------*/
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "draw/lv_draw.h"
|
||||
#include "misc/lv_async.h"
|
||||
#include "misc/lv_fs.h"
|
||||
#include "osal/lv_os_private.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "draw/nxp/vglite/lv_draw_vglite.h"
|
||||
#endif
|
||||
@ -160,6 +162,8 @@ void lv_init(void)
|
||||
lv_profiler_builtin_init(&profiler_config);
|
||||
#endif
|
||||
|
||||
lv_os_init();
|
||||
|
||||
_lv_timer_core_init();
|
||||
|
||||
_lv_fs_init();
|
||||
|
@ -78,6 +78,8 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
|
||||
}
|
||||
|
||||
LV_PROFILER_BEGIN;
|
||||
lv_lock();
|
||||
|
||||
uint32_t handler_start = lv_tick_get();
|
||||
|
||||
if(handler_start == 0) {
|
||||
@ -139,7 +141,10 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
|
||||
state_p->already_running = false; /*Release the mutex*/
|
||||
|
||||
LV_TRACE_TIMER("finished (%" LV_PRIu32 " ms until the next timer call)", time_until_next);
|
||||
lv_unlock();
|
||||
|
||||
LV_PROFILER_END;
|
||||
|
||||
return time_until_next;
|
||||
}
|
||||
|
||||
|
71
src/osal/lv_os.c
Normal file
71
src/osal/lv_os.c
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file lv_os.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_os.h"
|
||||
#include "lv_os_private.h"
|
||||
#include "../core/lv_global.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define lv_general_mutex LV_GLOBAL_DEFAULT()->lv_general_mutex
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_os_init(void)
|
||||
{
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
lv_mutex_init(&lv_general_mutex);
|
||||
#endif /*LV_USE_OS != LV_OS_NONE*/
|
||||
}
|
||||
|
||||
void lv_lock(void)
|
||||
{
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
lv_mutex_lock(&lv_general_mutex);
|
||||
#endif /*LV_USE_OS != LV_OS_NONE*/
|
||||
}
|
||||
|
||||
lv_result_t lv_lock_isr(void)
|
||||
{
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
return lv_mutex_lock_isr(&lv_general_mutex);
|
||||
#else /*LV_USE_OS != LV_OS_NONE*/
|
||||
return LV_RESULT_OK;
|
||||
#endif /*LV_USE_OS != LV_OS_NONE*/
|
||||
}
|
||||
|
||||
void lv_unlock(void)
|
||||
{
|
||||
#if LV_USE_OS != LV_OS_NONE
|
||||
lv_mutex_unlock(&lv_general_mutex);
|
||||
#endif /*LV_USE_OS != LV_OS_NONE*/
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
@ -145,6 +145,29 @@ lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync);
|
||||
*/
|
||||
lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync);
|
||||
|
||||
/**
|
||||
* Lock LVGL's general mutex.
|
||||
* LVGL is not thread safe, so a mutex is used to avoid executing multiple LVGL functions at the same time
|
||||
* from different threads. It shall be called when calling LVGL functions from threads
|
||||
* different than lv_timer_handler's thread. It doesn't need to be called in LVGL events because
|
||||
* they are called from lv_timer_handler().
|
||||
* It is called internally in lv_timer_handler().
|
||||
*/
|
||||
void lv_lock(void);
|
||||
|
||||
/**
|
||||
* Same as `lv_lock()` but can be called from an interrupt.
|
||||
* @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure
|
||||
*/
|
||||
lv_result_t lv_lock_isr(void);
|
||||
|
||||
/**
|
||||
* The pair of `lv_lock()` and `lv_lock_isr()`.
|
||||
* It unlocks LVGL general mutex.
|
||||
* It is called internally in lv_timer_handler().
|
||||
*/
|
||||
void lv_unlock(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
47
src/osal/lv_os_private.h
Normal file
47
src/osal/lv_os_private.h
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file lv_os_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OS_PRIVATE_H
|
||||
#define LV_OS_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* OS OPTIONS
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the OS layer
|
||||
*/
|
||||
void lv_os_init(void);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OS_PRIVATE_H*/
|
Loading…
Reference in New Issue
Block a user