@@ -56,10 +56,10 @@ input, firing events, animations, etc.
|
|||||||
There are two ways to provide this information to LVGL:
|
There are two ways to provide this information to LVGL:
|
||||||
|
|
||||||
1. Supply LVGL with a callback function to retrieve elapsed system milliseconds by
|
1. Supply LVGL with a callback function to retrieve elapsed system milliseconds by
|
||||||
calling :cpp:expr:`lv_tick_set_cb(my_get_milliseconds_function)`.
|
calling :cpp:expr:`lv_tick_set_cb(my_get_milliseconds)`.
|
||||||
:cpp:expr:`my_get_milliseconds_function()` needs to return the number of
|
:cpp:expr:`my_get_milliseconds()` needs to return the number of milliseconds
|
||||||
milliseconds elapsed since system start up. Many platforms have built-in
|
elapsed since system start up. Many platforms have built-in functions that can
|
||||||
functions that can be used as they are. For example:
|
be used as they are. For example:
|
||||||
|
|
||||||
- SDL: ``lv_tick_set_cb(SDL_GetTicks);``
|
- SDL: ``lv_tick_set_cb(SDL_GetTicks);``
|
||||||
- Arduino: ``lv_tick_set_cb(my_tick_get_cb);``, where ``my_tick_get_cb`` is:
|
- Arduino: ``lv_tick_set_cb(my_tick_get_cb);``, where ``my_tick_get_cb`` is:
|
||||||
@@ -75,12 +75,43 @@ There are two ways to provide this information to LVGL:
|
|||||||
cannot be missed when the system is under high load.
|
cannot be missed when the system is under high load.
|
||||||
|
|
||||||
.. note:: :cpp:func:`lv_tick_inc` is only one of two LVGL functions that may be
|
.. note:: :cpp:func:`lv_tick_inc` is only one of two LVGL functions that may be
|
||||||
called from an interrupt. See the :ref:`threading` section to learn more.
|
called from an interrupt if writing to a ``uint32_t`` value is atomic on your
|
||||||
|
platform. See below and the :ref:`threading` section to learn more.
|
||||||
|
|
||||||
The ticks (milliseconds) should be independent from any other activities of the MCU.
|
Either way, the writing of the ``uint32_t`` Tick value must be :ref:`atomic <atomic>`,
|
||||||
|
which is usually the case with a 32- or 64-bit platform. If you are using a 16-bit
|
||||||
|
system (causing the update of the Tick value to not be atomic) and your platform uses
|
||||||
|
the Harvard instruction set, you can set a function like this as the callback passed
|
||||||
|
to :cpp:expr:`lv_tick_set_cb(my_get_milliseconds)`:
|
||||||
|
|
||||||
For example this works, but LVGL's timing will be incorrect as the execution time of
|
.. code-block:: c
|
||||||
:c:func:`lv_timer_handler` is not considered:
|
|
||||||
|
/**
|
||||||
|
* @brief Safe read from 'elapsed_power_on_time_in_ms'
|
||||||
|
*/
|
||||||
|
uint32_t my_get_milliseconds()
|
||||||
|
{
|
||||||
|
register uint32_t u32result;
|
||||||
|
/* Disable priority 1-6 interrupts for 2 Fcys. */
|
||||||
|
__builtin_disi(2);
|
||||||
|
u32result = elapsed_power_on_time_in_ms; /* Cost: 2 Fcys */
|
||||||
|
/* Generally looks like this in assembly:
|
||||||
|
* mov elapsed_power_on_time_in_ms, W0
|
||||||
|
* mov 0x7898, W1
|
||||||
|
* requiring exactly 2 clock cycles.
|
||||||
|
* Now value is copied to register pair W0:W1
|
||||||
|
* where it can be written to any destination. */
|
||||||
|
return u32result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reliability
|
||||||
|
-----------
|
||||||
|
Advancing the tick value should be done in such a way that its timing is reliable and
|
||||||
|
not dependent on anything that consumes an unknown amount of time. For an example of
|
||||||
|
what *not* to do: this can "seem" to work, but LVGL's timing will be incorrect
|
||||||
|
because the execution time of :c:func:`lv_timer_handler` varies from call to call and
|
||||||
|
thus the delay it introduces cannot be known.
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ Thread
|
|||||||
In "bare-metal" implementations (i.e. no OS), threads include:
|
In "bare-metal" implementations (i.e. no OS), threads include:
|
||||||
|
|
||||||
- the main thread executing a while(1) loop that runs the system, and
|
- the main thread executing a while(1) loop that runs the system, and
|
||||||
- interrupts.
|
- interrupt service routines (ISRs).
|
||||||
|
|
||||||
When running under an OS, threads include:
|
When running under an OS, threads include:
|
||||||
|
|
||||||
- each task (or process),
|
- each task (or process),
|
||||||
- interrupts, and
|
- ISRs, and
|
||||||
- advanced OSes can have multiple "execution threads" within a processes.
|
- advanced OSes can have multiple "execution threads" within a processes.
|
||||||
|
|
||||||
.. _atomic operation:
|
.. _atomic operation:
|
||||||
@@ -93,8 +93,9 @@ before any other LVGL function is started.
|
|||||||
|
|
||||||
These two LVGL functions may be called from any thread:
|
These two LVGL functions may be called from any thread:
|
||||||
|
|
||||||
- :cpp:func:`lv_tick_inc` (see :ref:`tick_interface` for more information) and
|
- :cpp:func:`lv_tick_inc` (if writing to a ``uint32_t`` is atomic on your
|
||||||
- :cpp:func:`lv_display_flush_ready` (see :ref:`flush_callback` for more information)
|
platform; see :ref:`tick_interface` for more information) and
|
||||||
|
- :cpp:func:`lv_display_flush_ready` (:ref:`flush_callback` for more information)
|
||||||
|
|
||||||
The reason this is okay is that the LVGL data changed by them is :ref:`atomic <atomic>`.
|
The reason this is okay is that the LVGL data changed by them is :ref:`atomic <atomic>`.
|
||||||
|
|
||||||
@@ -105,6 +106,14 @@ before any other LVGL function is started.
|
|||||||
If you are using an OS, there are a few other options. See below.
|
If you are using an OS, there are a few other options. See below.
|
||||||
|
|
||||||
|
|
||||||
|
Ensuring Time Updates are Atomic
|
||||||
|
--------------------------------
|
||||||
|
For LVGL's time-related tasks to be reliable, the time updates via the Tick Interface
|
||||||
|
must be reliable and the Tick Value must appear :ref:`atomic <atomic>` to LVGL. See
|
||||||
|
:ref:`tick_interface` for details.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _tasks:
|
.. _tasks:
|
||||||
|
|
||||||
Tasks
|
Tasks
|
||||||
|
|||||||
Reference in New Issue
Block a user