feat(docs): reorganize docs (#7136)
This commit is contained in:
57
docs/details/integration/chip/arm.rst
Normal file
57
docs/details/integration/chip/arm.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
.. _arm:
|
||||
|
||||
===
|
||||
Arm
|
||||
===
|
||||
|
||||
Arm is a leading semiconductor and software design company, renowned for creating the Cortex-M microcontroller (MCU) cores and Cortex-A/R (MPU) processor cores, which are integral to a wide range of devices. These cores are at the heart of many embedded systems, powering chips from industry giants such as STMicroelectronics, NXP, and Renesas. Arm's energy-efficient designs are used in billions of devices worldwide, from microcontrollers to smartphones and servers. By licensing their processor designs, Arm enables a broad ecosystem of partners to develop customized solutions optimized for performance, power, and size. Arm's architecture is highly compatible with various operating systems and software libraries, including LVGL, making it a versatile choice for developers creating efficient, high-performance graphical user interfaces.
|
||||
|
||||
Compile LVGL for Arm
|
||||
--------------------
|
||||
|
||||
No specific action is required. Any compiler that supports the target Arm architecture can be used to compile LVGL's source code, including GCC, LLVM, and AC6.
|
||||
|
||||
It is also possible to cross-compile LVGL for an MPU (instead of compiling it on the target hardware) or create a shared library. For more information, check out :ref:`build_cmake`.
|
||||
|
||||
Getting Started with AC6
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Since AC6 is a proprietary toolchain, it contains many specific optimizations, so you can expect the best performance when using it.
|
||||
|
||||
AC6 is not free, but it offers a community license that can be activated as follows:
|
||||
|
||||
1. Download and install the AC6 compiler from `Arm's website <https://developer.arm.com/Tools%20and%20Software/Arm%20Compiler%20for%20Embedded>`__.
|
||||
2. To register a community license, go to the ``bin`` folder of the compiler and, in a terminal, run ``armlm.exe activate -server https://mdk-preview.keil.arm.com -product KEMDK-COM0`` (On Linux, use ``./armlm``).
|
||||
|
||||
IDE Support
|
||||
-----------
|
||||
|
||||
There are no limitations on the supported IDEs. LVGL works in various vendors' IDEs, including Arm's Keil MDK, IAR, Renesas's e2 studio, NXP's MCUXpresso, ST's CubeIDE, as well as custom make or CMake projects.
|
||||
|
||||
Arm2D and the Helium instruction set
|
||||
------------------------------------
|
||||
|
||||
Arm Cortex-M55 and Cortex-M85 have the `SIMD Helium <https://www.arm.com/technologies/helium>`__ instruction set.
|
||||
Among many others, this can effectively speed up UI rendering. :ref:`Arm2D <arm2d>` is a library maintained by Arm that leverages the Helium instruction set.
|
||||
|
||||
Note that GCC has some known issues with Helium intrinsics. It is recommended to use AC6 or LLVM when dealing with Helium code.
|
||||
|
||||
|
||||
To add Arm2D to your project, follow these steps:
|
||||
|
||||
1. To utilize its power, ensure that ``mcpu`` is set to ``cortex-m85``, ``cortex-m55``, or ``cortex-m52`` and add the ``-fvectorize`` flag. To test without SIMD, use e.g. ``cortex-m85+nomve``.
|
||||
2. Arm2D can be downloaded from `https://github.com/ARM-software/Arm-2D <https://github.com/ARM-software/Arm-2D>`__. Consider using the ``developing`` branch, which contains the latest updates.
|
||||
3. Add ``Arm-2D/Library/Include`` to the include paths.
|
||||
4. Copy ``Arm-2D/Library/Include/template/arm_2d_cfg.h`` to any location you prefer to provide the default configuration for Arm2D. Ensure that the folder containing ``arm_2d_cfg.h`` is added to the include path.
|
||||
5. The Arm2D repository contains several examples and templates; however, ensure that only ``Arm-2D/Library/Source`` is compiled.
|
||||
6. The CMSIS DSP library also needs to be added to the project. You can use CMSIS-PACKS or add it manually.
|
||||
7. For better performance, enable ``LTO`` (Link Time Optimization) and use ``-Omax`` or ``-Ofast``.
|
||||
8. Arm2D tries to read/write multiple data with a single instruction. Therefore, it's important to use the fastest memory (e.g., ``BSS`` or ``TCM``) for LVGL's buffer to avoid memory bandwidth bottlenecks.
|
||||
9. Enable ``LV_USE_DRAW_ARM2D_SYNC 1`` and ``LV_USE_DRAW_SW_ASM LV_DRAW_SW_ASM_HELIUM`` in ``lv_conf.h``.
|
||||
|
||||
Neon Acceleration
|
||||
-----------------
|
||||
|
||||
Several Cortex-A microprocessors support the `Neon SIMD <https://www.arm.com/technologies/neon>`__ instruction set. LVGL has built-in support to improve the performance of software rendering by utilizing Neon instructions. To enable Neon acceleration, set ``LV_USE_DRAW_SW_ASM`` to ``LV_DRAW_SW_ASM_NEON`` in ``lv_conf.h``.
|
||||
|
||||
|
||||
198
docs/details/integration/chip/espressif.rst
Normal file
198
docs/details/integration/chip/espressif.rst
Normal file
@@ -0,0 +1,198 @@
|
||||
=============================
|
||||
Espressif (ESP32 Chip Series)
|
||||
=============================
|
||||
|
||||
LVGL can be used and configured as standard `ESP-IDF <https://github.com/espressif/esp-idf>`__ component.
|
||||
|
||||
If you are new to ESP-IDF, follow the instructions in the `ESP-IDF Programming guide <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html>`__ to install and set up ESP-IDF on your machine.
|
||||
|
||||
|
||||
LVGL Demo Projects for ESP32
|
||||
----------------------------
|
||||
|
||||
For a quick start with LVGL and ESP32, the following pre-configured demo projects are available for specific development boards:
|
||||
|
||||
- `ESP-BOX-3 <https://github.com/lvgl/lv_port_espressif_esp-box-3>`__
|
||||
- `ESP32-S3-LCD-EV-BOARD <https://github.com/lvgl/lv_port_espressif_esp32-s3-lcd-ev-board>`__
|
||||
- `M5Stack-CoreS3 <https://github.com/lvgl/lv_port_espressif_M5Stack_CoreS3>`__
|
||||
|
||||
Refer to the README.md files in these repositories for build and flash instructions.
|
||||
|
||||
These demo projects use Espressif's Board Support Packages (BSPs). Additional BSPs and examples are available in the `esp-bsp <https://github.com/espressif/esp-bsp>`__ repository.
|
||||
|
||||
|
||||
Using LVGL in Your ESP-IDF Project
|
||||
----------------------------------
|
||||
|
||||
The simplest way to integrate LVGL into your ESP-IDF project is via the `esp_lvgl_port <https://components.espressif.com/components/espressif/esp_lvgl_port>`__ component. This component, used in the demo projects mentioned above, provides helper functions for easy installation of LVGL and display drivers. Moreover, it can add support for touch, rotary encoders, button or USB HID inputs. It simplifies power savings, screen rotation and other platform specific nuances.
|
||||
|
||||
The esp_lvgl_port supports LVGL versions 8 and 9 and is compatible with ESP-IDF v4.4 and above. To add it to your project, use the following command:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
idf.py add-dependency "espressif/esp_lvgl_port^2.3.0"
|
||||
|
||||
By default, esp_lvgl_port depends on the latest stable version of LVGL, so no additional steps are needed for new projects. If a specific LVGL version is required, specify this in your project to avoid automatic updates. LVGL can also be used without esp_lvgl_port, as described below.
|
||||
|
||||
Obtaining LVGL
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
LVGL is distributed through `ESP Registry <https://components.espressif.com/>`__, where all LVGL releases are uploaded.
|
||||
In case you do not want to use esp_lvgl_port, you can add `LVGL component <https://components.espressif.com/component/lvgl/lvgl>`__ into your project with following command:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
idf.py add-dependency lvgl/lvgl^9.*
|
||||
|
||||
Adjust the ``^9.*`` part to match your LVGL version requirement. More information on version specifications can be found in the `IDF Component Manager documentation <https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/versioning.html#range-specifications>`__. During the next build, the LVGL component will be fetched from the component registry and added to the project.
|
||||
|
||||
**Advanced usage: Use LVGL as local component**
|
||||
|
||||
For LVGL development and testing, it may be useful to use LVGL as a local component instead of from the ESP Registry, which offers only released versions and does not allow local modifications. To do this, clone LVGL to your project with the following command:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
git submodule add https://github.com/lvgl/lvgl.git components/lvgl
|
||||
|
||||
.. note::
|
||||
|
||||
All components from ``${project_dir}/components`` are automatically added to build.
|
||||
|
||||
Configuration
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
To configure LVGL, launch the configuration menu with ``idf.py menuconfig`` in your project root directory. Navigate to ``Component config`` and then ``LVGL configuration``.
|
||||
|
||||
|
||||
Support for Display and Touch Drivers
|
||||
-------------------------------------
|
||||
|
||||
For successful LVGL project you will need a display driver and optionally a touch driver. Espressif provides these drivers that are built on its `esp_lcd <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/lcd/index.html>`__ component.
|
||||
|
||||
- esp_lcd natively supports for some `basic displays <https://github.com/espressif/esp-idf/tree/master/components/esp_lcd/src>`__
|
||||
- Other displays are maintained in `esp-bsp repository <https://github.com/espressif/esp-bsp/tree/master/components/lcd>`__ and are uploaded to ESP Registry
|
||||
- Touch drivers are maintained in `esp-bsp repository <https://github.com/espressif/esp-bsp/tree/master/components/lcd_touch>`__ and are uploaded to ESP Registry
|
||||
|
||||
These components share a common public API, making it easy to migrate your projects across different display and touch drivers.
|
||||
|
||||
To add a display or touch driver to your project, use a command like:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
idf.py add-dependency "espressif/esp_lcd_gc9a01^2.0.0"
|
||||
|
||||
Using the File System under ESP-IDF
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
ESP-IDF uses the standard C functions (``fopen``, ``fread``) in all storage related APIs.
|
||||
This allows seamless interoperability with LVGL when enabling the :c:macro:`LV_USE_FS_STDIO` configuration.
|
||||
The process is described in details below, using ``SPIFFS`` as demonstration.
|
||||
|
||||
- **Decide what storage system you want to use**
|
||||
|
||||
ESP-IDF has many, ready-to-use examples like
|
||||
`SPIFFS <https://github.com/espressif/esp-idf/tree/master/examples/storage/spiffsgen>`__
|
||||
,
|
||||
`SD Card <https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card/sdspi>`__
|
||||
and
|
||||
`LittleFS <https://github.com/espressif/esp-idf/tree/master/examples/storage/littlefs>`__
|
||||
.
|
||||
|
||||
- **Re-configure your own project**
|
||||
|
||||
The example project should be examined for details, but in general the changes involve:
|
||||
|
||||
- Enabling LVGL's STDIO file system in the configuration
|
||||
|
||||
You can use ``menuconfig``:
|
||||
|
||||
- ``Component config → LVGL configuration → 3rd Party Libraries``: enable ``File system on top of stdio API``
|
||||
- Then select ``Set an upper cased letter on which the drive will accessible`` and set it to ``65`` (ASCII **A**)
|
||||
- You can also set ``Default driver letter`` to 65 to skip the prefix in file paths.
|
||||
|
||||
- Modifying the partition table
|
||||
|
||||
The exact configuration depends on your flash size and existing partitions,
|
||||
but the new final result should look something like this:
|
||||
|
||||
.. csv-table:: Partition Table
|
||||
|
||||
nvs, data, nvs, 0x9000, 0x6000
|
||||
phy_init, data, phy, 0xf000, 0x1000
|
||||
factory, app, factory, 0x10000, 1400k
|
||||
storage, data, spiffs, , 400k
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
If you are not using a custom ``partition.csv`` yet, it can be added
|
||||
via ``menuconfig`` (``Partition Table → Partition Table → Custom partition table CSV``).
|
||||
|
||||
- Apply changes to the build system
|
||||
|
||||
Some ESP file systems provide automatic generation from a host folder using CMake. The proper line(s) must be copied to ``main/CMakeLists.txt``
|
||||
|
||||
.. note::
|
||||
|
||||
``LittleFS`` has extra dependencies that should be added to ``main/idf_component.yml``
|
||||
|
||||
- **Prepare the image files**
|
||||
|
||||
LVGL's ``LVGLImage.py`` Python tool can be used to convert images to binary pixel map files.
|
||||
It supports various formats and compression.
|
||||
|
||||
Meanwhile 3rd party libraries
|
||||
(like :ref:`LodePNG<lodepng_rst>` and :ref:`Tiny JPEG<tjpgd>`)
|
||||
allow using image files without conversion.
|
||||
|
||||
After preparing the files, they should be moved to the target device:
|
||||
|
||||
- If properly activated a **SPIFFS** file system based on the ``spiffs_image`` folder should be automatically generated and later flashed to the target
|
||||
- Similar mechanism for **LittleFS** uses the ``flash_data`` folder, but it's only available for Linux hosts
|
||||
- For the **SD Card**, a traditional file browser can be used
|
||||
|
||||
- **Invoke proper API calls in the application code**
|
||||
|
||||
The core functionality requires only a few lines. The following example draws the image as well.
|
||||
|
||||
.. code:: c
|
||||
|
||||
#include "esp_spiffs.h"
|
||||
|
||||
void lv_example_image_from_esp_fs(void) {
|
||||
|
||||
esp_vfs_spiffs_conf_t conf = {
|
||||
.base_path = "/spiffs",
|
||||
.partition_label = NULL,
|
||||
.max_files = 5,
|
||||
.format_if_mount_failed = false
|
||||
};
|
||||
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register SPIFF filesystem");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_t * obj = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(widget, "A:/spiffs/logo.bin");
|
||||
lv_obj_center(widget);
|
||||
}
|
||||
|
||||
- **Build and flash**
|
||||
|
||||
After calling ``idf.py build flash`` the picture should be displayed on the screen.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Changes made by ``menuconfig`` are not being tracked in the repository if the ``sdkconfig`` file is added to ``.gitignore``, which is the default for many ESP-IDF projects.
|
||||
To make your configuration permanent, add the following lines to ``sdkconfig.defaults``:
|
||||
|
||||
.. code:: c
|
||||
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_LV_USE_FS_STDIO=y
|
||||
CONFIG_LV_FS_STDIO_LETTER=65
|
||||
CONFIG_LV_LV_FS_DEFAULT_DRIVE_LETTER=65
|
||||
12
docs/details/integration/chip/index.rst
Normal file
12
docs/details/integration/chip/index.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
============
|
||||
Chip vendors
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
arm
|
||||
espressif
|
||||
nxp
|
||||
renesas
|
||||
stm32
|
||||
410
docs/details/integration/chip/nxp.rst
Normal file
410
docs/details/integration/chip/nxp.rst
Normal file
@@ -0,0 +1,410 @@
|
||||
===
|
||||
NXP
|
||||
===
|
||||
|
||||
NXP has integrated LVGL into the MCUXpresso SDK packages for several of our
|
||||
microcontrollers as an optional software component, allowing easy evaluation and
|
||||
migration into your product design. LVGL is a free and open-source embedded
|
||||
graphic library with features that enable you to create embedded GUIs with
|
||||
intuitive graphical elements, beautiful visual effects and a low memory
|
||||
footprint. The complete graphic framework includes a variety of widgets for you
|
||||
to use in the creation of your GUI, and supports more advanced functions such as
|
||||
animations and anti-aliasing.
|
||||
|
||||
LVGL enables graphics in our free GUI Guider UI tool. It's available for use
|
||||
with NXP’s general purpose and crossover microcontrollers, providing developers
|
||||
with a tool for creating complete, high quality GUI applications with LVGL.
|
||||
|
||||
Creating new project with LVGL
|
||||
------------------------------
|
||||
|
||||
`Download an SDK for a supported board <https://www.nxp.com/design/software/embedded-software/littlevgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY?&tid=vanLITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY>`__
|
||||
today and get started with your next GUI application. It comes fully configured
|
||||
with LVGL (and with PXP/VGLite support if the modules are present), no
|
||||
additional integration work is required.
|
||||
|
||||
HW acceleration for NXP iMX RT platforms
|
||||
----------------------------------------
|
||||
|
||||
Depending on the RT platform used, the acceleration can be done by NXP PXP
|
||||
(PiXel Pipeline) and/or the Verisilicon GPU through an API named VGLite. Each
|
||||
accelerator has its own context that allows them to be used individually as well
|
||||
simultaneously (in LVGL multithreading mode).
|
||||
|
||||
PXP accelerator
|
||||
~~~~~~~~~~~~~~~
|
||||
Basic configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Select NXP PXP engine in "lv_conf.h": Set :c:macro:`LV_USE_PXP` to `1`.
|
||||
- In order to use PXP as a draw unit, select in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_PXP` to `1`.
|
||||
- In order to use PXP to rotate the screen, select in "lv_conf.h": Set :c:macro:`LV_USE_ROTATE_PXP` to `1`.
|
||||
- Enable PXP asserts in "lv_conf.h": Set :c:macro: `LV_USE_PXP_ASSERT` to `1`.
|
||||
There are few PXP assertions that can stop the program execution in case the
|
||||
c:macro:`LV_ASSERT_HANDLER` is set to `while(1);` (Halt by default). Else,
|
||||
there will be logged just an error message via `LV_LOG_ERROR`.
|
||||
- If :c:macro:`SDK_OS_FREE_RTOS` symbol is defined, FreeRTOS implementation
|
||||
will be used, otherwise bare metal code will be included.
|
||||
|
||||
Basic initialization:
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
PXP draw initialization is done automatically in :cpp:func:`lv_init()` once the
|
||||
PXP is enabled as a draw unit or to rotate the screen, no user code is required:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if LV_USE_DRAW_PXP || LV_USE_ROTATE_PXP
|
||||
lv_draw_pxp_init();
|
||||
#endif
|
||||
|
||||
During PXP initialization, a new draw unit `lv_draw_pxp_unit_t` will be created
|
||||
with the additional callbacks, if :c:macro:`LV_USE_DRAW_PXP` is set to `1`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t));
|
||||
draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate;
|
||||
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
|
||||
draw_pxp_unit->base_unit.delete_cb = _pxp_delete;
|
||||
|
||||
|
||||
and an addition thread `_pxp_render_thread_cb()` will be spawned in order to
|
||||
handle the supported draw tasks.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if LV_USE_PXP_DRAW_THREAD
|
||||
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit);
|
||||
#endif
|
||||
|
||||
If `LV_USE_PXP_DRAW_THREAD` is not defined, then no additional draw thread will be created
|
||||
and the PXP drawing task will get executed on the same LVGL main thread.
|
||||
|
||||
`_pxp_evaluate()` will get called after each task is being created and will
|
||||
analyze if the task is supported by PXP or not. If it is supported, then an
|
||||
preferred score and the draw unit id will be set to the task. An `score` equal
|
||||
to `100` is the default CPU score. Smaller score means that PXP is capable of
|
||||
drawing it faster.
|
||||
|
||||
`_pxp_dispatch()` is the PXP dispatcher callback, it will take a ready to draw
|
||||
task (having the `DRAW_UNIT_ID_PXP` set) and will pass the task to the PXP draw
|
||||
unit for processing.
|
||||
|
||||
`_pxp_delete()` will cleanup the PXP draw unit.
|
||||
|
||||
|
||||
Features supported:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Several drawing features in LVGL can be offloaded to the PXP engine. The CPU is
|
||||
available for other operations while the PXP is running. RTOS is required to
|
||||
block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||
power savings.
|
||||
|
||||
Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_pxp.c":
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_pxp_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Additional, the screen rotation can be handled by the PXP:
|
||||
|
||||
.. code-block::c
|
||||
|
||||
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
|
||||
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
|
||||
lv_color_format_t cf);
|
||||
|
||||
- Fill area with color (w/o radius, w/o gradient) + optional opacity.
|
||||
- Blit source image RGB565/ARGB888/XRGB8888 over destination.
|
||||
RGB565/RGB888/ARGB888/XRGB8888 + optional opacity.
|
||||
- Recolor source image RGB565.
|
||||
- Scale and rotate (90, 180, 270 degree) source image RGB565.
|
||||
- Blending layers (w/ same supported formats as blitting).
|
||||
- Rotate screen (90, 180, 270 degree).
|
||||
|
||||
|
||||
Known limitations:
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- PXP can only rotate at 90x angles.
|
||||
- Rotation is not supported for images unaligned to blocks of 16x16 pixels. PXP
|
||||
is set to process 16x16 blocks to optimize the system for memory bandwidth and
|
||||
image processing time. The output engine essentially truncates any output
|
||||
pixels after the desired number of pixels has been written. When rotating a
|
||||
source image and the output is not divisible by the block size, the incorrect
|
||||
pixels could be truncated and the final output image can look shifted.
|
||||
- Recolor or transformation for images w/ opacity or alpha channel can't be
|
||||
obtained in a single PXP pipeline configuration. Two or multiple steps would
|
||||
be required.
|
||||
- Buffer address must be aligned to 64 bytes: set :c:macro:`LV_DRAW_BUF_ALIGN`
|
||||
to `64` in "lv_conf.h".
|
||||
No stride alignment is required: set :c:macro:`LV_DRAW_BUF_STRIDE_ALIGN` to
|
||||
`1` in "lv_conf.h".
|
||||
|
||||
Project setup:
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
- Add PXP related source files (and corresponding headers if available) to
|
||||
project:
|
||||
|
||||
- "src/draw/nxp/pxp/lv_draw_buf_pxp.c": draw buffer callbacks
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp_fill.c": fill area
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp_img.c": blit image (w/ optional recolor or
|
||||
transformation)
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp_layer.c": layer blending
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp.c": draw unit initialization
|
||||
- "src/draw/nxp/pxp/lv_pxp_cfg.c": init, deinit, run/wait PXP device
|
||||
- "src/draw/nxp/pxp/lv_pxp_osa.c": OS abstraction (FreeRTOS or bare metal)
|
||||
- "src/draw/nxp/pxp/lv_pxp_utils.c": function helpers
|
||||
|
||||
- PXP related code depends on two drivers provided by MCU SDK. These drivers
|
||||
need to be added to project:
|
||||
|
||||
- fsl_pxp.c: PXP driver
|
||||
- fsl_cache.c: CPU cache handling functions
|
||||
|
||||
|
||||
PXP default configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Implementation depends on multiple OS-specific functions. The struct
|
||||
:cpp:struct:`pxp_cfg_t` with callback pointers is used as a parameter for the
|
||||
:cpp:func:`lv_pxp_init()` function. Default implementation for FreeRTOS and
|
||||
bare metal is provided in lv_pxp_osa.c.
|
||||
|
||||
- :cpp:func:`pxp_interrupt_init()`: Initialize PXP interrupt (HW setup,
|
||||
OS setup)
|
||||
- :cpp:func:`pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup,
|
||||
OS setup)
|
||||
- :cpp:func:`pxp_run()`: Start PXP job. Use OS-specific mechanism to block
|
||||
drawing thread.
|
||||
- :cpp:func:`pxp_wait()`: Wait for PXP completion.
|
||||
|
||||
|
||||
VGLite accelerator
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Extra drawing features in LVGL can be handled by the VGLite engine. The
|
||||
CPU is available for other operations while the VGLite is running. An
|
||||
RTOS is required to block the LVGL drawing thread and switch to another
|
||||
task or suspend the CPU for power savings.
|
||||
|
||||
|
||||
Basic configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Select NXP VGLite engine in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_VGLITE` to
|
||||
`1`. :c:macro:`SDK_OS_FREE_RTOS` symbol needs to be defined so that FreeRTOS
|
||||
driver osal implementation will be enabled.
|
||||
- Enable VGLite asserts in "lv_conf.h": Set :c:macro: `LV_USE_VGLITE_ASSERT` to
|
||||
`1`.
|
||||
VGLite assertions will verify the driver API status code and in any error, it
|
||||
can stop the program execution in case the c:macro: `LV_ASSERT_HANDLER` is set
|
||||
to `while(1);` (Halt by default). Else, there will be logged just an error
|
||||
message via `LV_LOG_ERROR`.
|
||||
|
||||
Basic initialization:
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Initialize VGLite GPU before calling :cpp:func:`lv_init()` by specifying the
|
||||
width/height of tessellation window. The default values for tesselation width
|
||||
and height, and command buffer size are in the SDK file "vglite_support.h".
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "vg_lite.h"
|
||||
#include "vglite_support.h"
|
||||
#endif
|
||||
...
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
if(vg_lite_init(DEFAULT_VG_LITE_TW_WIDTH, DEFAULT_VG_LITE_TW_HEIGHT) != VG_LITE_SUCCESS)
|
||||
{
|
||||
PRINTF("VGLite init error. STOP.");
|
||||
vg_lite_close();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
if (vg_lite_set_command_buffer_size(VG_LITE_COMMAND_BUFFER_SIZE) != VG_LITE_SUCCESS)
|
||||
{
|
||||
PRINTF("VGLite set command buffer. STOP.");
|
||||
vg_lite_close();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
VGLite draw initialization is done automatically in :cpp:func:`lv_init()` once
|
||||
the VGLite is enabled, no user code is required:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
lv_draw_vglite_init();
|
||||
#endif
|
||||
|
||||
During VGLite initialization, a new draw unit `lv_draw_vglite_unit_t` will be
|
||||
created with the additional callbacks:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t));
|
||||
draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate;
|
||||
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
|
||||
draw_vglite_unit->base_unit.delete_cb = _vglite_delete;
|
||||
|
||||
and an addition thread `_vglite_render_thread_cb()` will be spawned in order to
|
||||
handle the supported draw tasks.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if LV_USE_VGLITE_DRAW_THREAD
|
||||
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit);
|
||||
#endif
|
||||
|
||||
If `LV_USE_VGLITE_DRAW_THREAD` is not defined, then no additional draw thread will be created
|
||||
and the VGLite drawing task will get executed on the same LVGL main thread.
|
||||
|
||||
`_vglite_evaluate()` will get called after each task is being created and will
|
||||
analyze if the task is supported by VGLite or not. If it is supported, then an
|
||||
preferred score and the draw unit id will be set to the task. An `score` equal
|
||||
to `100` is the default CPU score. Smaller score means that VGLite is capable of
|
||||
drawing it faster.
|
||||
|
||||
`_vglite_dispatch()` is the VGLite dispatcher callback, it will take a ready to
|
||||
draw task (having the `DRAW_UNIT_ID_VGLITE` set) and will pass the task to the
|
||||
VGLite draw unit for processing.
|
||||
|
||||
`_vglite_delete()` will cleanup the VGLite draw unit.
|
||||
|
||||
|
||||
Advanced configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Enable VGLite blit split in "lv_conf.h":
|
||||
Set :c:macro: `LV_USE_VGLITE_BLIT_SPLIT` to `1`.
|
||||
Enabling the blit split workaround will mitigate any quality degradation issue
|
||||
on screen's dimension > 352 pixels.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define VGLITE_BLIT_SPLIT_THR 352
|
||||
|
||||
- By default, the blit split threshold is set to 352. Blits with width or height
|
||||
higher than this value will be done in multiple steps. Value must be multiple
|
||||
of stride alignment in px. For most color formats, the alignment is 16px
|
||||
(except the index formats). Transformation will not be supported once with
|
||||
the blit split.
|
||||
|
||||
- Enable VGLite draw task synchronously in "lv_conf.h":
|
||||
Set :c:macro: `LV_USE_VGLITE_DRAW_ASYNC` to `1`.
|
||||
Multiple draw tasks can be queued and flushed them once to the GPU based on
|
||||
the GPU idle status. If GPU is busy, the task will be queued, and the VGLite
|
||||
dispatcher will ask for a new available task. If GPU is idle, the queue with
|
||||
any pending tasks will be flushed to the GPU. The completion status of draw
|
||||
task will be sent to the main LVGL thread asynchronously.
|
||||
|
||||
Features supported:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Several drawing features in LVGL can be offloaded to the VGLite engine. The CPU
|
||||
is available for other operations while the GPU is running. RTOS is required to
|
||||
block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||
power savings.
|
||||
|
||||
Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_vglite.c":
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
lv_draw_vglite_label(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_vglite_fill(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BORDER:
|
||||
lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
lv_draw_vglite_arc(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_vglite_line(draw_unit, t->draw_dsc);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||
lv_draw_vglite_triangle(draw_unit, t->draw_dsc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
All the below operation can be done in addition with optional opacity.
|
||||
|
||||
- Fill area with color (w/ radius or gradient).
|
||||
- Blit source image (any format from ``_vglite_src_cf_supported()``) over
|
||||
destination (any format from ``_vglite_dest_cf_supported()``).
|
||||
- Recolor source image.
|
||||
- Scale and rotate (any decimal degree) source image.
|
||||
- Blending layers (w/ same supported formats as blitting).
|
||||
- Draw letters (blit bitmap letters / raster font).
|
||||
- Draw full borders (LV_BORDER_SIDE_FULL).
|
||||
- Draw arcs (w/ rounded edges).
|
||||
- Draw lines (w/ dash or rounded edges).
|
||||
- Draw triangles with color (w/ gradient).
|
||||
|
||||
|
||||
Known limitations:
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Source image alignment: The byte alignment requirement for a pixel depends on
|
||||
the specific pixel format. Both buffer address and buffer stride must be
|
||||
aligned. As general rule, the alignment is set to 16 pixels. This makes the
|
||||
buffer address alignment to be 32 bytes for RGB565 and 64 bytes for ARGB8888.
|
||||
- For pixel engine (PE) destination, the alignment should be 64 bytes for all
|
||||
tiled (4x4) buffer layouts. The pixel engine has no additional alignment
|
||||
requirement for linear buffer layouts (:c:macro:`VG_LITE_LINEAR`).
|
||||
|
||||
|
||||
Project setup:
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
- Add VGLite related source files (and corresponding headers if available) to
|
||||
project:
|
||||
|
||||
- "src/draw/nxp/vglite/lv_draw_buf_vglite.c": draw buffer callbacks
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_arc.c": draw arc
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_border.c": draw border
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_fill.c": fill area
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_img.c": blit image (w/ optional recolor or transformation)
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_label.c": draw label
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_layer.c": layer blending
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_line.c": draw line
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_triangle.c": draw triangle
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite.c": draw unit initialization
|
||||
- "src/draw/nxp/vglite/lv_vglite_buf.c": init/get vglite buffer
|
||||
- "src/draw/nxp/vglite/lv_vglite_matrix.c": set vglite matrix
|
||||
- "src/draw/nxp/vglite/lv_vglite_path.c": create vglite path data
|
||||
- "src/draw/nxp/vglite/lv_vglite_utils.c": function helpers
|
||||
224
docs/details/integration/chip/renesas.rst
Normal file
224
docs/details/integration/chip/renesas.rst
Normal file
@@ -0,0 +1,224 @@
|
||||
.. _renesas:
|
||||
|
||||
=======
|
||||
Renesas
|
||||
=======
|
||||
|
||||
`Renesas <https://renesas.com/>`__ is an official partner of LVGL. Therefore, LVGL contains built-in support for
|
||||
`Dave2D <https://www.renesas.com/document/mas/tes-dave2d-driver-documentation>`__ (the GPU of Renesas) and we also maintain
|
||||
ready-to-use Renesas projects.
|
||||
|
||||
|
||||
Dave2D
|
||||
------
|
||||
|
||||
Dave2D is capable of accelerating most of the drawing operations of LVGL:
|
||||
|
||||
- Rectangle drawing, even with gradients
|
||||
- Image drawing, scaling, and rotation
|
||||
- Letter drawing
|
||||
- Triangle drawing
|
||||
- Line drawing
|
||||
|
||||
|
||||
As Dave2D works in the background, the CPU is free for other tasks. In practice, during rendering, Dave2D can reduce the CPU usage by
|
||||
half or to one-third, depending on the application.
|
||||
|
||||
|
||||
GLCDC
|
||||
-----
|
||||
|
||||
GLCDC is a multi-stage graphics output peripheral available in several Renesas MCUs. It is able to drive LCD panels via a highly
|
||||
configurable RGB interface.
|
||||
|
||||
More info can be found at the :ref:`driver's page<renesas_glcdc>`.
|
||||
|
||||
|
||||
Supported boards
|
||||
----------------
|
||||
|
||||
.. list-table::
|
||||
:widths: 10 30 30 30
|
||||
|
||||
* -
|
||||
- **EK-RA8D1**
|
||||
- **EK-RA6M3G**
|
||||
- **RX72N Envision Kit**
|
||||
* - CPU
|
||||
- 480MHz, Arm Cortex-M85 core
|
||||
- 120MHz, Arm Cortex-M4 core
|
||||
- 240MHz, Renesas RXv3 core
|
||||
* - Memory
|
||||
-
|
||||
| 1MB internal, 64MB external SDRAM
|
||||
| 2MB internal, 64MB External Octo-SPI Flash
|
||||
-
|
||||
| 640kB internal SRAM
|
||||
| 2MB internal, 32MB external QSPI Flash
|
||||
-
|
||||
| 1MB internal SRAM
|
||||
| 4MB internal, 32MB external QSPI Flash
|
||||
* - Display
|
||||
-
|
||||
| 4.5”
|
||||
| 480x854
|
||||
| 2-lane MIPI
|
||||
-
|
||||
| 4.3”
|
||||
| 480x272
|
||||
| Parallel RGB565
|
||||
-
|
||||
| 4.3”
|
||||
| 480x272
|
||||
| Parallel RGB565
|
||||
* - `Board <https://lvgl.io/boards>`__ video
|
||||
- .. raw:: html
|
||||
|
||||
<iframe width="320" height="180" src="https://www.youtube.com/embed/WkJPB8wto_U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
- .. raw:: html
|
||||
|
||||
<iframe width="320" height="180" src="https://www.youtube.com/embed/0kar4Ee3Qic" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
- .. raw:: html
|
||||
|
||||
<iframe width="320" height="180" src="https://www.youtube.com/embed/__56v8DsfH0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
* - Links
|
||||
- `Demo repository for EK-RA8D1 <https://github.com/lvgl/lv_port_renesas_ek-ra8d1>`__
|
||||
- `Demo repository for EK-RA6M3G <https://github.com/lvgl/lv_port_renesas_ek-ra6m3g>`__
|
||||
- `Demo repository for RX72N Envision Kit <https://github.com/lvgl/lv_port_renesas_rx72n-envision-kit>`__
|
||||
|
||||
|
||||
Get started with the Renesas ecosystem
|
||||
--------------------------------------
|
||||
|
||||
.. |img_debug_btn| image:: /misc/renesas/debug_btn.png
|
||||
:alt: Debug button
|
||||
|
||||
.. dropdown:: RA Family
|
||||
|
||||
- The official IDE of Renesas is called e² studio. As it's Eclipse-based, it runs on Windows, Linux, and Mac as well.
|
||||
The RA family requires the latest version with FSP 5.3. It can be downloaded `here <https://www.renesas.com/us/en/software-tool/flexible-software-package-fsp>`__.
|
||||
- JLink is used for debugging, it can be downloaded `here <https://www.segger.com/downloads/jlink/>`__.
|
||||
- Clone the ready-to-use repository for your selected board:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git clone https://github.com/lvgl/lv_port_renesas_ek-ra8d1.git --recurse-submodules
|
||||
|
||||
|
||||
Downloading the `.zip` from GitHub doesn't work as it doesn't download the submodules.
|
||||
- Open e² studio, go to ``File`` -> ``Import project`` and select ``General`` / ``Existing projects into workspace``
|
||||
- Browse the cloned folder and press ``Finish``.
|
||||
- Double click on ``configuration.xml``. This will activate the `Configuration Window`.
|
||||
|
||||
Renesas' Flexible Software Package (FSP) incudes BSP and HAL layer support extended with multiple RTOS variants and other middleware stacks.
|
||||
The components will be available via code generation, including the entry point of *"main.c"*.
|
||||
|
||||
Press ``Generate Project Content`` in the top right corner.
|
||||
|
||||
.. image:: /misc/renesas/generate.png
|
||||
:alt: Code generation with FSP
|
||||
|
||||
- Build the project by pressing ``Ctrl`` + ``Alt`` + ``B``
|
||||
- Click the Debug button (|img_debug_btn|). If prompted with `Debug Configurations`, on the `Debugger` tab select the ``J-Link ARM`` as `Debug hardware` and the proper IC as `Target Device`:
|
||||
|
||||
- ``R7FA8D1BH`` for EK-RA8D1
|
||||
|
||||
.. image:: /misc/renesas/debug_ra8.png
|
||||
:alt: Debugger parameters for RA8
|
||||
|
||||
- ``R7FA6M3AH`` for EK-RA6M3G
|
||||
|
||||
.. image:: /misc/renesas/debug_ra6.png
|
||||
:alt: Debugger parameters for RA6
|
||||
|
||||
.. note::
|
||||
On EK-RA8D1 boards, the ``SW1`` DIP switch (middle of the board) 7 should be ON, all others are OFF.
|
||||
|
||||
.. dropdown:: RX Family
|
||||
|
||||
- The official IDE of Renesas is called e² studio. As it's Eclipse-based, it runs on Windows, Linux, and Mac as well.
|
||||
It can be downloaded `here <https://www.renesas.com/us/en/software-tool/e-studio>`__.
|
||||
- Download and install the required driver for the debugger
|
||||
|
||||
- for Windows: `64 bit here <https://www.renesas.com/us/en/document/uid/usb-driver-renesas-mcu-tools-v27700-64-bit-version-windows-os?r=488806>`__
|
||||
and `32 bit here <https://www.renesas.com/us/en/document/uid/usb-driver-renesas-mcu-toolse2e2-liteie850ie850apg-fp5-v27700for-32-bit-version-windows-os?r=488806>`__
|
||||
- for Linux: `here <https://www.renesas.com/us/en/document/swo/e2-emulator-e2-emulator-lite-linux-driver?r=488806>`__
|
||||
|
||||
- RX72 requires an external compiler for the RXv3 core. A free and open-source version is available
|
||||
`here <https://llvm-gcc-renesas.com/rx-download-toolchains/>`__ after a registration.
|
||||
|
||||
The compiler must be activated in e² studio:
|
||||
|
||||
- Go to go to ``Help`` -> ``Add Renesas Toolchains``
|
||||
- Press the ``Add...`` button
|
||||
- Browse the installation folder of the toolchain
|
||||
|
||||
<br/>
|
||||
|
||||
.. image:: /misc/renesas/toolchains.png
|
||||
:alt: Toolchains
|
||||
|
||||
- Clone the ready-to-use `lv_port_renesas_rx72n-envision-kit <https://github.com/lvgl/lv_port_renesas_rx72n-envision-kit.git>`__ repository:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git clone https://github.com/lvgl/lv_port_renesas_rx72n-envision-kit.git --recurse-submodules
|
||||
|
||||
|
||||
Downloading the `.zip` from GitHub doesn't work as it doesn't download the submodules.
|
||||
|
||||
- Open e² studio, go to ``File`` -> ``Import project`` and select ``General`` / ``Existing projects into workspace``
|
||||
- Select the cloned folder and press ``Finish``.
|
||||
- Double click on ``RX72N_EnVision_LVGL.scfg``. This will activate the `Configuration Window`.
|
||||
|
||||
Renesas' Smart Configurator (SMC) incudes BSP and HAL layer support extended with multiple RTOS variants and other middleware stacks.
|
||||
The components will be available via code generation, including the entry point of the application.
|
||||
|
||||
Press ``Generate Code`` in the top right corner.
|
||||
|
||||
.. image:: /misc/renesas/generate_smc.png
|
||||
:alt: Code generation with SMC
|
||||
|
||||
- Build the project by pressing ``Ctrl`` + ``Alt`` + ``B``
|
||||
- Click the Debug button (|img_debug_btn|). If prompted with `Debug Configurations`, on the `Debugger` tab select the ``E2 Lite``
|
||||
as `Debug hardware` and ``R5F572NN`` as `Target Device`:
|
||||
|
||||
.. image:: /misc/renesas/debug_rx72.png
|
||||
:alt: Debugger parameters for RX72
|
||||
|
||||
.. note::
|
||||
Make sure that both channels of ``SW1`` DIP switch (next to ``ECN1``) are OFF.
|
||||
|
||||
|
||||
Modify the project
|
||||
------------------
|
||||
|
||||
|
||||
Open a demo
|
||||
~~~~~~~~~~~
|
||||
|
||||
The entry point of the main task is contained in ``src/LVGL_thread_entry.c`` in all 3 projects.
|
||||
|
||||
You can disable the LVGL demos (or just comment them out) and call some ``lv_example_...()`` functions, or add your custom code.
|
||||
|
||||
|
||||
Configuration
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
``src/lv_conf.h`` contains the most important settings for LVGL. Namely:
|
||||
|
||||
- :c:macro:`LV_COLOR_DEPTH` to set LVGL's default color depth
|
||||
- :c:macro:`LV_MEM_SIZE` to set the maximum RAM available for LVGL
|
||||
- :c:macro:`LV_USE_DAVE2D` to enable the GPU
|
||||
|
||||
|
||||
Hardware and software components can be modified in a visual way using the `Configuration Window`.
|
||||
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
In case of any problems or questions open an issue in the corresponding repository.
|
||||
295
docs/details/integration/chip/stm32.rst
Normal file
295
docs/details/integration/chip/stm32.rst
Normal file
@@ -0,0 +1,295 @@
|
||||
=====
|
||||
STM32
|
||||
=====
|
||||
|
||||
LVGL Can be added to `STM32CubeIDE <https://www.st.com/en/development-tools/stm32cubeide.html>`__
|
||||
in a similar fashion to any other Eclipse-based IDE.
|
||||
|
||||
|
||||
Including LVGL in a Project
|
||||
---------------------------
|
||||
|
||||
- Create or open a project in STM32CubeIDE.
|
||||
- Copy the entire LVGL folder to *[project_folder]/Drivers/lvgl*.
|
||||
- In the STM32CubeIDE **Project Explorer** pane: right click on the
|
||||
LVGL folder that you copied (you may need to refresh the view first
|
||||
before it will appear), and select **Add/remove include path…**. If
|
||||
this doesn't appear, or doesn't work, you can review your project
|
||||
include paths under the **Project** -> **Properties** menu, and then
|
||||
navigating to **C/C++ Build** -> **Settings** -> **Include paths**, and
|
||||
ensuring that the LVGL directory is listed.
|
||||
|
||||
Now that the source files are included in your project, follow the instructions to
|
||||
:ref:`add_lvgl_to_your_project` and to create the ``lv_conf.h`` file, and
|
||||
initialise the display.
|
||||
|
||||
|
||||
Bare Metal Example
|
||||
------------------
|
||||
|
||||
A minimal example using STM32CubeIDE, and HAL. \* When setting up
|
||||
**Pinout and Configuration** using the **Device Configuration Tool**,
|
||||
select **System Core** -> **SYS** and ensure that **Timebase Source** is
|
||||
set to **SysTick**. \* Configure any other peripherals (including the
|
||||
LCD panel), and initialise them in *main.c*. \* ``#include "lvgl.h"`` in
|
||||
the *main.c* file. \* Create some frame buffer(s) as global variables:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Frame buffers
|
||||
* Static or global buffer(s). The second buffer is optional
|
||||
* TODO: Adjust color format and choose buffer size. DISPLAY_WIDTH * 10 is one suggestion. */
|
||||
#define BYTES_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565)) /* will be 2 for RGB565 */
|
||||
#define BUFF_SIZE (DISPLAY_WIDTH * 10 * BYTES_PER_PIXEL)
|
||||
static uint8_t buf_1[BUFF_SIZE];
|
||||
static uint8_t buf_2[BUFF_SIZE];
|
||||
|
||||
- In your ``main()`` function, after initialising your CPU,
|
||||
peripherals, and LCD panel, call :cpp:func:`lv_init` to initialise LVGL.
|
||||
You can then create the display driver using
|
||||
:cpp:func:`lv_display_create`, and register the frame buffers using
|
||||
:cpp:func:`lv_display_set_buffers`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
//Initialise LVGL UI library
|
||||
lv_init();
|
||||
|
||||
lv_display_t * disp = lv_display_create(WIDTH, HEIGHT); /* Basic initialization with horizontal and vertical resolution in pixels */
|
||||
lv_display_set_flush_cb(disp, my_flush_cb); /* Set a flush callback to draw to the display */
|
||||
lv_display_set_buffers(disp, buf_1, buf_2, sizeof(buf_1), LV_DISPLAY_RENDER_MODE_PARTIAL); /* Set an initialized buffer */
|
||||
|
||||
- Create some dummy Widgets to test the output:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Change Active Screen's background color */
|
||||
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);
|
||||
lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
|
||||
|
||||
/* Create a spinner */
|
||||
lv_obj_t * spinner = lv_spinner_create(lv_screen_active(), 1000, 60);
|
||||
lv_obj_set_size(spinner, 64, 64);
|
||||
lv_obj_align(spinner, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
|
||||
|
||||
- Add a call to :cpp:func:`lv_timer_handler` inside your ``while(1)`` loop:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Infinite loop */
|
||||
while (1)
|
||||
{
|
||||
lv_timer_handler();
|
||||
HAL_Delay(5);
|
||||
}
|
||||
|
||||
|
||||
- Add a call to :cpp:func:`lv_tick_inc` inside the :cpp:func:`SysTick_Handler` function. Open the *stm32xxxx_it.c*
|
||||
file (the name will depend on your specific MCU), and update the :cpp:func:`SysTick_Handler` function:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SysTick_IRQn 0 */
|
||||
|
||||
HAL_SYSTICK_IRQHandler();
|
||||
lv_tick_inc(1);
|
||||
#ifdef USE_RTOS_SYSTICK
|
||||
osSystickHandler();
|
||||
#endif
|
||||
|
||||
/* USER CODE END SysTick_IRQn 0 */
|
||||
HAL_IncTick();
|
||||
/* USER CODE BEGIN SysTick_IRQn 1 */
|
||||
|
||||
/* USER CODE END SysTick_IRQn 1 */
|
||||
}
|
||||
|
||||
|
||||
- Finally, write the callback function, ``my_flush_cb``, which will send the display buffer to your LCD panel. Below is
|
||||
one example, but it will vary depending on your setup.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void my_flush_cb(lv_display_t * disp, const lv_area_t * area, lv_color_t * color_p)
|
||||
{
|
||||
//Set the drawing region
|
||||
set_draw_window(area->x1, area->y1, area->x2, area->y2);
|
||||
|
||||
int height = area->y2 - area->y1 + 1;
|
||||
int width = area->x2 - area->x1 + 1;
|
||||
|
||||
//We will do the SPI write manually here for speed
|
||||
HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
|
||||
//CS low to begin data
|
||||
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
|
||||
|
||||
//Write colour to each pixel
|
||||
for (int i = 0; i < width * height; i++) {
|
||||
uint16_t color_full = (color_p->red << 11) | (color_p->green << 5) | (color_p->blue);
|
||||
parallel_write(color_full);
|
||||
|
||||
color_p++;
|
||||
}
|
||||
|
||||
//Return CS to high
|
||||
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
|
||||
|
||||
/* IMPORTANT!!!
|
||||
* Inform the graphics library that you are ready with the flushing */
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
|
||||
|
||||
FreeRTOS Example
|
||||
----------------
|
||||
|
||||
A minimal example using STM32CubeIDE, HAL, and CMSISv1 (FreeRTOS).
|
||||
*Note that we have not used Mutexes in this example, however LVGL is* **NOT**
|
||||
*thread safe and so Mutexes should be used*. See: :ref:`threading`
|
||||
\* ``#include "lvgl.h"`` \* Create your frame buffer(s) as global variables:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Frame buffers
|
||||
* Static or global buffer(s). The second buffer is optional */
|
||||
#define BYTES_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565)) /* will be 2 for RGB565 */
|
||||
/* TODO: Declare your own BUFF_SIZE appropriate to your system. */
|
||||
static lv_color_t buf_1[BUFF_SIZE];
|
||||
#define BUFF_SIZE (DISPLAY_WIDTH * 10 * BYTES_PER_PIXEL)
|
||||
static uint8_t buf_1[BUFF_SIZE];
|
||||
static lv_color_t buf_2[BUFF_SIZE];
|
||||
|
||||
- In your ``main`` function, after your peripherals (SPI, GPIOs, LCD
|
||||
etc) have been initialised, initialise LVGL using :cpp:func:`lv_init`,
|
||||
create a new display driver using :cpp:func:`lv_display_create`, and
|
||||
register the frame buffers using :cpp:func:`lv_display_set_buffers`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Initialise LVGL UI library */
|
||||
lv_init();
|
||||
lv_display_t *display = lv_display_create(WIDTH, HEIGHT); /* Create the display */
|
||||
lv_display_set_flush_cb(display, my_flush_cb); /* Set a flush callback to draw to the display */
|
||||
lv_display_set_buffers(disp, buf_1, buf_2, sizeof(buf_1), LV_DISPLAY_RENDER_MODE_PARTIAL); /* Set an initialized buffer */
|
||||
|
||||
/* Register the touch controller with LVGL - Not included here for brevity. */
|
||||
|
||||
|
||||
- Create some dummy Widgets to test the output:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Change Active Screen's background color */
|
||||
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);
|
||||
lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
|
||||
|
||||
/* Create a spinner */
|
||||
lv_obj_t * spinner = lv_spinner_create(lv_screen_active(), 1000, 60);
|
||||
lv_obj_set_size(spinner, 64, 64);
|
||||
lv_obj_align(spinner, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
|
||||
- Create two threads to call :cpp:func:`lv_timer_handler`, and
|
||||
:cpp:func:`lv_tick_inc`.You will need two ``osThreadId`` handles for
|
||||
CMSISv1. These don't strictly have to be globally accessible in this
|
||||
case, however STM32Cube code generation does by default. If you are
|
||||
using CMSIS and STM32Cube code generation it should look something
|
||||
like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
//Thread Handles
|
||||
osThreadId lvgl_tickHandle;
|
||||
osThreadId lvgl_timerHandle;
|
||||
|
||||
/* definition and creation of lvgl_tick */
|
||||
osThreadDef(lvgl_tick, LVGLTick, osPriorityNormal, 0, 1024);
|
||||
lvgl_tickHandle = osThreadCreate(osThread(lvgl_tick), NULL);
|
||||
|
||||
//LVGL update timer
|
||||
osThreadDef(lvgl_timer, LVGLTimer, osPriorityNormal, 0, 1024);
|
||||
lvgl_timerHandle = osThreadCreate(osThread(lvgl_timer), NULL);
|
||||
|
||||
- And create the thread functions:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* LVGL timer for tasks. */
|
||||
void LVGLTimer(void const * argument)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
lv_timer_handler();
|
||||
osDelay(20);
|
||||
}
|
||||
}
|
||||
/* LVGL tick source */
|
||||
void LVGLTick(void const * argument)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
lv_tick_inc(10);
|
||||
osDelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
- Finally, create the ``my_flush_cb`` function to output the frame
|
||||
buffer to your LCD. The specifics of this function will vary
|
||||
depending on which MCU features you are using. Below is an example
|
||||
for a typical MCU interface.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void my_flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map);
|
||||
{
|
||||
uint16_t * color_p = (uint16_t *)px_map;
|
||||
|
||||
//Set the drawing region
|
||||
set_draw_window(area->x1, area->y1, area->x2, area->y2);
|
||||
|
||||
int height = area->y2 - area->y1 + 1;
|
||||
int width = area->x2 - area->x1 + 1;
|
||||
|
||||
//Begin SPI Write for DATA
|
||||
HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
|
||||
|
||||
//Write colour to each pixel
|
||||
for (int i = 0; i < width * height; i++) {
|
||||
parallel_write(color_p);
|
||||
color_p++;
|
||||
}
|
||||
|
||||
//Return CS to high
|
||||
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
|
||||
|
||||
/* IMPORTANT!!!
|
||||
* Inform the graphics library that you are ready with the flushing */
|
||||
lv_display_flush_ready(display);
|
||||
}
|
||||
|
||||
.. _dma2d:
|
||||
|
||||
DMA2D Support
|
||||
-------------
|
||||
|
||||
LVGL supports DMA2D - a feature of some STM32 MCUs which can improve performance
|
||||
when blending fills and images. Some STM32 product lines such as STM32F4 STM32F7, STM32L4,
|
||||
STM32U5, and STM32H7 include models with DMA2D support.
|
||||
|
||||
LVGL's integration with DMA2D can be enabled by setting ``LV_USE_DRAW_DMA2D``
|
||||
to ``1`` in ``lv_conf.h``
|
||||
|
||||
With ``LV_USE_DRAW_DMA2D_INTERRUPT`` set to ``0`` and ``LV_USE_OS`` set to ``LV_OS_NONE``,
|
||||
DMA2D will draw some fills and images concurrently with the software render where
|
||||
possible. If ``LV_USE_DRAW_DMA2D_INTERRUPT`` is set to ``1`` and ``LV_USE_OS`` set to
|
||||
``LV_OS_FREERTOS`` (or another OS) the main difference will be that the core will idle
|
||||
instead of "busywait" while waiting for a DMA2D transfer to complete.
|
||||
|
||||
If ``LV_USE_DRAW_DMA2D_INTERRUPT`` is enabled then you are required to call
|
||||
:cpp:expr:`lv_draw_dma2d_transfer_complete_interrupt_handler` whenever the DMA2D
|
||||
"transfer complete" global interrupt is received.
|
||||
|
||||
If your STM device has a Nema GPU, you can use the :ref:`Nema GFX renderer <stm32_nema_gfx>` instead.
|
||||
Reference in New Issue
Block a user