Frame Buffer Drivers
A framebuffer is a memory-mapped buffer that represents all the pixels necessary to drive a video display.
The Frame Buffer driver is intended to be used in the following scenarios:
Whenever it is necessary to hold all the pixels that would be used to drive a video display. This includes:
Graphics libraries that directly access the underlying framebuffer;
Advanced UIs (e.g. alpha blending) that need to read back the image data;
Applications that expect the framebuffer to exist;
Binding
LCD and frame buffer drivers usually are not directly accessed by user code, but are usually bound to another, higher-level device driver. In general, the binding sequence is:
Get an instance of
struct fb_vtable_s
from the hardware-specific frame buffer device driver, andProvide that instance to the initialization method of the higher-level device driver.
Generic LCD Frame Buffer
This example will walk through the path from userspace to hardware-specific details on how an LCD screen is bound to a framebuffer.
include/nuttx/video/fb.h
provides all structures and APIs needed to work with frame buffer drivers:drivers/video/fb.c
is the higher-level device driver. An instance ofstruct fb_vtable_s
will be provided to it;fb_register
registers the framebuffer character device at/dev/fbN
where N is the display number;It also provides the prototype of
up_fbinitialize
, which may be defined by:An specific device into
arch/<arch>/src/<chip>
directory;By the LCD framebuffer adapter in
drivers/lcd/lcd_framebuffer.c
, which provides an intermediary interface between the Frame Buffer Driver and the LCD screen drivers;
Let’s consider we are using the LCD framebuffer (
CONFIG_LCD_FRAMEBUFFER = y
):This interface implements the
up_fbinitialize
which:Provides the instance of
struct fb_vtable_s
(a member ofstruct lcdfb_dev_s
);Calls
board_lcd_initialize
andboard_lcd_getdev
LCD-specific functions. These functions are defined inboards/<arch>/<chip>/<board>/src
and prototyped ininclude/nuttx/board.h
;
Finally, the LCD screen drivers are usually available at
drivers/lcd/
and implement the callbacks defined atinclude/nuttx/lcd/lcd.h
:include/nuttx/lcd/lcd.h
provides structures and APIs needed to work with LCD screens, whereas using the framebuffer adapter or the LCD Character Drivers;
Examples
Examples apply to specific cases of the Generic LCD Frame Buffer:
TTGO T-Display ESP32 board
This board contains an ST7789 TFT Display (135x240).
By selecting the ttgo_t_display_esp32:lvgl_fb
config, the lvgldemo
example will be built with the framebuffer interface.
boards/xtensa/esp32/ttgo_t_display_esp32/src/esp32_bringup.c
registers the framebuffer driver:
#ifdef CONFIG_VIDEO_FB
ret = fb_register(0, 0);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: Failed to initialize Frame Buffer Driver.\n");
}
#endif
up_fbinitialize
from the frame buffer adapter will then be called asCONFIG_LCD_FRAMEBUFFER = y
:board_lcd_initialize
andboard_lcd_getdev
are defined atboards/xtensa/esp32/common/src/esp32_st7789.c
:board_lcd_initialize
initializes the LCD hardware on the board by defining the SPI interface which is connected to the display controller;board_lcd_getdev
calls thest7789_lcdinitialize
and returns a reference to the LCD object for the specified LCD;st7789_lcdinitialize
is part of the LCD screen driver atdrivers/lcd/st7789.c
;
The LVGL demo application (
lvgldemo
) makes use of theioctl
system call to trigger aFBIO_UPDATE
request to the higher-level device driver to refresh the LCD screen with framebuffer data:
ioctl(state.fd, FBIO_UPDATE, (unsigned long)((uintptr_t)&fb_area));
NuttX Simulator
NuttX Simulator provides a X11-based framebuffer driver to simulate the framebuffer usage into a X11-compatible host.
By selecting the sim:lvgl_fb
config, the lvgldemo
example will be built with the framebuffer driver.
boards/sim/sim/sim/src/sim_bringup.c
registers the framebuffer driver the same way TTGO T-Display ESP32 board;arch/sim/src/sim/up_framebuffer.c
andarch/sim/src/sim/up_x11framebuffer.c
will be built asCONFIG_SIM_FRAMEBUFFER = y
andCONFIG_SIM_X11FB = y
are set, respectively;up_framebuffer.c
providesup_fbinitialize
and,calls
up_x11initialize
fromup_x11framebuffer.c
that initializes a X11-based window as a framebuffer. This is the underlying “driver”.
The LVGL demo application (
lvgldemo
) makes use of theioctl
system call to trigger aFBIO_UPDATE
request to the higher-level device driver in order to refresh the LCD screen with framebuffer data as usual;
Warning
One must consider that framebuffer requires that the entire display’s pixels to be represented. Considering a 320x480 @RGB565 LCD screen, that would be 300KiB, which it’d be too much for a memory-constrained device.
However, when memory is not a constraint, framebuffer may offer applications a faster way to update display contents once writing to the RAM-mapped buffer is faster than doing multiple SPI transfers.
For memory-constrained devices, consider using LCD Character Drivers.