1.. _stm32 ltdc driver:
2
3=================
4STM32 LTDC Driver
5=================
6
7Some STM32s have a specialized peripheral for driving
8displays called LTDC (LCD-TFT display controller).
9
10Usage Modes With LVGL
11*********************
12
13The driver within LVGL is designed to work with an
14already-configured LTDC peripheral. It relies on the
15HAL to detect information about the configuration.
16The color format of the created LVGL display will
17match the LTDC layer's color format. Use STM32CubeIDE
18or STM32CubeMX to generate LTDC initialization code.
19
20There are some different use cases for LVGL's driver.
21All permutations of the below options are well supported.
22
23- single or double buffered
24- direct or partial render mode
25- OS and no OS
26- parallelized flushing with DMA2D (only for partial render mode)
27
28If OS is enabled, a synchronization primitive will be used to
29give the thread a chance to yield to other threads while blocked,
30improving CPU utilization. See :c:macro:`LV_USE_OS` in your lv_conf.h
31
32LTDC Layers
33***********
34
35This driver creates an LVGL display
36which is only concerned with a specific layer of the LTDC peripheral, meaning
37two LVGL LTDC displays can be created and operate independently on the separate
38layers.
39
40Direct Render Mode
41******************
42
43For direct render mode, invoke :cpp:func:`lv_st_ltdc_create_direct` like this:
44
45.. code-block:: c
46
47    void * my_ltdc_framebuffer_address = (void *)0x20000000u;
48    uint32_t my_ltdc_layer_index = 0; /* typically 0 or 1 */
49    lv_display_t * disp = lv_st_ltdc_create_direct(my_ltdc_framebuffer_address,
50                                                   optional_other_full_size_buffer,
51                                                   my_ltdc_layer_index);
52
53``my_ltdc_framebuffer_address`` is the framebuffer configured for use by
54LTDC. ``optional_other_full_size_buffer`` can be another buffer which is the same
55size as the default framebuffer for double-buffered
56mode, or ``NULL`` otherwise. ``my_ltdc_layer_index`` is the layer index of the
57LTDC layer to create the display for.
58
59For the best visial results, ``optional_other_full_size_buffer`` should be used
60if enough memory is available. Single-buffered mode is what you should use
61if memory is very scarce. If there is almost enough memory for double-buffered
62direct mode, but not quite, then use partial render mode.
63
64Partial Render Mode
65*******************
66
67For partial render mode, invoke :cpp:func:`lv_st_ltdc_create_partial` like this:
68
69.. code-block:: c
70
71    static uint8_t partial_buf1[65536];
72    static uint8_t optional_partial_buf2[65536];
73    uint32_t my_ltdc_layer_index = 0; /* typically 0 or 1 */
74    lv_display_t * disp = lv_st_ltdc_create_partial(partial_buf1,
75                                                    optional_partial_buf2,
76                                                    65536,
77                                                    my_ltdc_layer_index);
78
79The driver will use the information in the LTDC layer configuration to find the
80layer's framebuffer and flush to it.
81
82Providing a second partial buffer can improve CPU utilization and increase
83performance compared to
84a single buffer if :c:macro:`LV_ST_LTDC_USE_DMA2D_FLUSH` is enabled.
85
86Display Rotation
87****************
88
89The driver supports display rotation with
90:cpp:expr:`lv_display_set_rotation(disp, rotation)` where rotation is one of
91:cpp:enumerator:`LV_DISP_ROTATION_90`, :cpp:enumerator:`LV_DISP_ROTATION_180`,
92or :cpp:enumerator:`LV_DISP_ROTATION_270`. The rotation is initially
93:cpp:enumerator:`LV_DISP_ROTATION_0`.
94
95The rotation is done in software and only works if the display was
96created using :cpp:func:`lv_st_ltdc_create_partial`.
97:c:macro:`LV_ST_LTDC_USE_DMA2D_FLUSH` will be have no effect if rotation
98is used.
99
100DMA2D
101*****
102
103:c:macro:`LV_ST_LTDC_USE_DMA2D_FLUSH` can be enabled to use DMA2D to flush
104partial buffers in parallel with other LVGL tasks, whether or not OS is
105enabled. If the display is not partial, then there is no need to enable this
106option.
107
108Additionally it is possible to mix layers that have color format on
109:c:macro:`LV_COLOR_FORMAT_ARGB1555` on top of :c:macro:`LV_COLOR_FORMAT_RGB565`
110layers using the DMA2D.
111
112It must not be enabled at the same time as :c:macro:`LV_USE_DRAW_DMA2D`.
113See the :ref:`DMA2D support <dma2d>`.
114
115
116.. admonition::  Further Reading
117
118    You may be interested in enabling the :ref:`Nema GFX renderer <nema_gfx>`
119    if your STM32 has a NeoChrom GPU.
120
121    `lv_port_riverdi_stm32u5 <https://github.com/lvgl/lv_port_riverdi_stm32u5>`__
122    is a way to quick way to get started with LTDC on LVGL.
123