boards/stm32h7/linum-stm32h753bi: enable USB FS host, add lvglterm_kbda

Enable the OTG FS host on the Linum board so an external USB HID keyboard
can be used: configure the USB VBUS, power-switch and over-current GPIOs
at board bring-up (the power switch on PI12 is active low) and start the
USB host from stm32_bringup() through stm32_usbhost_initialize().

Add the lvglterm_kbda configuration - the LVGL terminal driven by a USB
HID keyboard on /dev/kbda - with the microSD card enabled alongside the
USB host.  They coexist once CONFIG_MMCSD_MMCSUPPORT is left disabled, so
an SD card is not probed as an MMC device.

Also switch esp32s3-m5-cardputer:lvglterm to the renamed matrix-keyboard
input option (EXAMPLES_LVGLTERM_INPUT_KBD_MATRIX) to match the reworked
lvglterm example Kconfig.

Update the documentation accordingly: the LVGL Terminal example page for
the three-way input choice (touch, matrix, USB HID) with cursor-key
scrolling and per-variant configuration plus a photo of the USB variant
running on the Linum, the lvglterm_kbda entry on the Linum board page,
and the matrix-keyboard variant name on the M5Stack Cardputer board page.

Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
Jorge Guzman 2026-07-06 18:07:49 -03:00 committed by Matteo Golin
parent 1fc6f2bac8
commit 2e7910fef6
11 changed files with 239 additions and 23 deletions

View file

@ -4,18 +4,20 @@
LVGL application that runs an interactive NuttShell (NSH) on the display. NSH
is started with its standard streams redirected through pipes, its output is
rendered in an LVGL text area, and the input comes from one of two sources
rendered in an LVGL text area, and the input comes from one of three sources
selected at build time.
The shared code lives in ``lvglterm.c`` (NSH startup, output rendering, main
loop); ``lvglterm_touch.c`` and ``lvglterm_kbd.c`` implement the two input
loop); ``lvglterm_touch.c`` and ``lvglterm_kbd.c`` implement the input
variants.
Input variants
==============
The input source is chosen with the *LVGL Terminal input source* Kconfig
choice (only one is built at a time):
choice (only one is built at a time). The physical-keyboard options differ in
the data the keyboard device returns on ``read()``, so the one that matches the
hardware must be selected.
On-screen keyboard (touch)
``CONFIG_EXAMPLES_LVGLTERM_INPUT_TOUCH`` (default). An LVGL keyboard
@ -29,23 +31,39 @@ On-screen keyboard (touch)
On-screen keyboard (touch) variant
Physical keyboard
``CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD``. Key events are read from a
``/dev/kbdN`` keyboard device and streamed to the shell; the output fills
the whole screen. Requires ``CONFIG_INPUT_KEYBOARD``.
The device defaults to ``CONFIG_EXAMPLES_LVGLTERM_KBD_DEV``
(``/dev/kbd0``) and can be overridden at run time by passing the path as
the first argument (``lvglterm /dev/kbd1``) when more than one keyboard is
present. Keyboards that report the Fn navigation cluster as cursor keys
can scroll the output with Up/Down.
Matrix / upper-half keyboard
``CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_MATRIX``. ``struct
keyboard_event_s`` events are read from a keyboard registered through the
``CONFIG_INPUT_KEYBOARD`` upper half (for example the M5Stack Cardputer
matrix keyboard on ``/dev/kbd0``) and streamed to the shell; the output
fills the whole screen. The Fn Up/Down cursor keys scroll the output.
.. figure:: lvglterm-kbd.png
:align: center
:width: 500px
:alt: LVGL Terminal driven by a physical keyboard
:alt: LVGL Terminal driven by a matrix keyboard
Physical keyboard variant
Matrix / upper-half keyboard variant
USB HID keyboard
``CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_USB``. A USB HID keyboard (for
example on ``/dev/kbda`` with ``CONFIG_USBHOST_HIDKBD``) delivers a byte
stream that is decoded with the keyboard codec and streamed to the shell.
When the driver is built with ``CONFIG_HIDKBD_ENCODED`` the Up/Down cursor
keys scroll the terminal.
.. figure:: lvglterm-usb.png
:align: center
:width: 500px
:alt: LVGL Terminal driven by a USB HID keyboard
USB HID keyboard variant
Both keyboard variants default the device to
``CONFIG_EXAMPLES_LVGLTERM_KBD_DEV`` (``/dev/kbd0`` for the matrix keyboard,
``/dev/kbda`` for USB) and can be overridden at run time by passing the path
as the first argument (``lvglterm /dev/kbd1``) when more than one keyboard is
present.
Font
====
@ -63,9 +81,13 @@ Configuration
- ``CONFIG_SYSTEM_NSH=y`` -- the NSH library must be enabled.
- ``CONFIG_GRAPHICS_LVGL=y`` and ``CONFIG_LV_USE_NUTTX=y`` -- LVGL with its
NuttX integration.
- A display (``CONFIG_LV_USE_NUTTX_LCD`` or a framebuffer). The touch variant
also needs a touchscreen input (``CONFIG_LV_USE_NUTTX_TOUCHSCREEN``); the
keyboard variant needs a keyboard driver (``CONFIG_INPUT_KEYBOARD``).
- A display (``CONFIG_LV_USE_NUTTX_LCD`` or a framebuffer). Each input variant
also needs its own driver: a touchscreen
(``CONFIG_LV_USE_NUTTX_TOUCHSCREEN``) for the touch variant,
``CONFIG_INPUT_KEYBOARD`` for the matrix variant, or
``CONFIG_USBHOST_HIDKBD`` for the USB variant. The USB variant selects
``CONFIG_LIBC_KBDCODEC`` automatically and, for the cursor keys, the driver
should be built with ``CONFIG_HIDKBD_ENCODED``.
- The selected font (``CONFIG_LV_FONT_UNSCII_8`` or
``CONFIG_LV_FONT_UNSCII_16``) is enabled automatically by the font choice.

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

View file

@ -909,6 +909,54 @@ Type a command on the on-screen keyboard and press Enter; the command line
``nsh> <command>`` and its output appear in the terminal area above the
keyboard.
lvglterm_kbda
-------------
**Purpose:** runs the ``lvglterm`` example -- an interactive NuttShell (NSH)
terminal rendered on the display -- driven by an external **USB HID keyboard**,
demonstrating that the OTG FS USB host and the microSD card can be used at the
same time on this board.
The board's OTG FS port is enabled as a USB host (VBUS power switch on PI12),
so a USB HID keyboard plugged into the service connector is enumerated as
``/dev/kbda`` and its keys are streamed to NSH. The microSD card is enabled as
well and, because ``CONFIG_MMCSD_MMCSUPPORT`` is disabled, an SD card is probed
correctly (not as an MMC device) and registered as ``/dev/mmcsd0``.
**Build and flash:**
.. code-block:: console
$ ./tools/configure.sh linum-stm32h753bi:lvglterm_kbda
$ make -j
Flash the resulting ``nuttx.bin`` to the board.
**How to test:** plug a USB HID keyboard and an SD card, reset the board and
check that both devices are present::
nsh> ls /dev
/dev:
console
fb0
kbda
mmcsd0
null
rtc0
ttyS0
zero
Start the terminal and type on the USB keyboard; the command line and its
output appear on the display, and the Up/Down cursor keys scroll it::
nsh> lvglterm
The SD card can be mounted and read while the keyboard is in use, confirming
that the USB host and the SDMMC peripheral coexist::
nsh> mount -t vfat /dev/mmcsd0 /data
nsh> ls /data
tone
----

View file

@ -60,7 +60,7 @@ turns it on).
The key-position-to-character table follows the M5Cardputer layout; verify
it against the printed legends on first bring-up. Applications read
``/dev/kbd0`` for key events (for example the ``lvglterm`` example, built
with its physical-keyboard input variant, feeds it into an on-screen
with its matrix-keyboard input variant, feeds it into an on-screen
shell).
Pin Mapping
@ -141,7 +141,7 @@ lvgl
lvglterm
On-screen NuttShell terminal with LVGL and the physical keyboard. Runs
the ``lvglterm`` example built with its physical-keyboard input variant:
the ``lvglterm`` example built with its matrix-keyboard input variant:
NSH output is rendered in an LVGL text area and the keyboard
(``/dev/kbd0``) feeds the input. Wi-Fi is included, so the on-screen
shell can associate with an access point using ``wapi``. ``Fn`` + ``;`` /

View file

@ -0,0 +1,93 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set
# CONFIG_MMCSD_MMCSUPPORT is not set
# CONFIG_STANDARD_SERIAL is not set
# CONFIG_STM32_FB_CMAP is not set
# CONFIG_STM32_LTDC_L1_CHROMAKEYEN is not set
# CONFIG_STM32_LTDC_L2 is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="linum-stm32h753bi"
CONFIG_ARCH_BOARD_LINUM_STM32H753BI=y
CONFIG_ARCH_CHIP="stm32h7"
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_CHIP_STM32H753BI=y
CONFIG_ARCH_CHIP_STM32H7=y
CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARMV7M_DCACHE=y
CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y
CONFIG_ARMV7M_DTCM=y
CONFIG_ARMV7M_ICACHE=y
CONFIG_BOARD_LOOPSPERMSEC=43103
CONFIG_BUILTIN=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DRIVERS_VIDEO=y
CONFIG_EXAMPLES_LVGLTERM=y
CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_USB=y
CONFIG_FAT_DMAMEMORY=y
CONFIG_FAT_LCNAMES=y
CONFIG_FAT_LFN=y
CONFIG_FB_OVERLAY=y
CONFIG_FS_FAT=y
CONFIG_FS_PROCFS=y
CONFIG_GRAN=y
CONFIG_GRAN_INTR=y
CONFIG_GRAPHICS_LVGL=y
CONFIG_HIDKBD_ENCODED=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INPUT=y
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBM=y
CONFIG_LINE_MAX=64
CONFIG_LV_MEM_SIZE_KILOBYTES=128
CONFIG_LV_USE_NUTTX=y
CONFIG_MMCSD=y
CONFIG_MMCSD_SDIO=y
CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE=y
CONFIG_MM_REGIONS=5
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_IFUPDOWN=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PIPES=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_RTC_ALARM=y
CONFIG_RTC_DATETIME=y
CONFIG_RTC_DRIVER=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SDMMC1_SDIO_MODE=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_STM32_FMC=y
CONFIG_STM32_HSI48=y
CONFIG_STM32_I2C3=y
CONFIG_STM32_LTDC=y
CONFIG_STM32_LTDC_FB_BASE=0xC0600000
CONFIG_STM32_LTDC_FB_SIZE=2097152
CONFIG_STM32_OTGFS=y
CONFIG_STM32_PWR=y
CONFIG_STM32_RTC=y
CONFIG_STM32_SDMMC1=y
CONFIG_STM32_USART1=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_TESTING_RAMTEST=y
CONFIG_USART1_SERIAL_CONSOLE=y
CONFIG_USBHOST=y
CONFIG_USBHOST_HIDKBD=y
CONFIG_USEC_PER_TICK=1000
CONFIG_VIDEO_FB=y

View file

@ -391,6 +391,15 @@
#define GPIO_OTGFS_DM (GPIO_OTGFS_DM_0|GPIO_SPEED_100MHz) /* PA11 */
#define GPIO_OTGFS_DP (GPIO_OTGFS_DP_0|GPIO_SPEED_100MHz) /* PA12 */
/* The Linum board wires the USB connector for host/device use without an
* OTG_FS_ID pin (mode is forced by the driver), so PA10 is NOT used as
* OTG_FS_ID. The OTG host driver still configures GPIO_OTGFS_ID
* unconditionally, so map it to a harmless floating input instead of the
* OTG_FS_ID alternate function to keep PA10 free.
*/
#define GPIO_OTGFS_ID (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10)
/* SDMMC1 - Used SD Card memory */
/* Init 400 kHz, PLL1Q/(2*300) = 240 MHz / (2*300) = 400 Khz */
@ -502,7 +511,10 @@
* this value will need to be doubled.
*/
#ifdef CONFIG_STM32_LTDC
#if defined(CONFIG_STM32_LTDC) && defined(CONFIG_STM32_LTDC_L1_ARGB8888)
/* A 32-bpp ARGB8888 framebuffer (1024x600x4 = 2.4M) needs the last 3M */
# define BOARD_SDRAM1_SIZE (5*1024*1024)
#elif defined(CONFIG_STM32_LTDC)
# define BOARD_SDRAM1_SIZE (6*1024*1024)
#else
# define BOARD_SDRAM1_SIZE (8*1024*1024)

View file

@ -305,4 +305,22 @@ int board_tone_initialize(int devno);
int stm32_tsc_setup(int minor);
#endif
/****************************************************************************
* Name: stm32_usbhost_initialize
*
* Description:
* Called at application startup time to initialize the USB host
* functionality. This function will start a thread that will monitor for
* device connection/disconnection events.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
#ifdef CONFIG_USBHOST
int stm32_usbhost_initialize(void);
#endif
#endif /* __BOARDS_ARM_STM32H7_LINUM_STM32H753BI_SRC_LINUM_STM32H753BI_H */

View file

@ -55,6 +55,14 @@ void stm32_boardinitialize(void)
board_autoled_initialize();
#endif
#ifdef CONFIG_STM32_OTGFS
/* Initialize USB-related GPIOs (VBUS sensing, power switch enable and
* over-current) so the OTG FS port can drive VBUS in host mode.
*/
stm32_usbinitialize();
#endif
}
/****************************************************************************

View file

@ -359,5 +359,17 @@ int stm32_bringup(void)
}
#endif
#ifdef CONFIG_USBHOST
/* Initialize USB host to support an external HID keyboard (e.g. as the
* NXDoom game controller) plugged into the OTG FS service port.
*/
ret = stm32_usbhost_initialize();
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: stm32_usbhost_initialize() failed: %d\n", ret);
}
#endif
return OK;
}

View file

@ -271,9 +271,11 @@ void stm32_usbhost_vbusdrive(int iface, bool enable)
{
DEBUGASSERT(iface == 0);
/* Set the Power Switch by driving the active high enable pin */
/* Set the Power Switch by driving the enable pin. On the Linum board the
* USB power switch enable (PI12) is active low, so invert the request.
*/
stm32_gpiowrite(GPIO_OTGFS_PWRON, enable);
stm32_gpiowrite(GPIO_OTGFS_PWRON, !enable);
}
#endif

View file

@ -47,6 +47,7 @@ CONFIG_ESP32S3_USBSERIAL=y
CONFIG_ESPRESSIF_WIFI=y
CONFIG_EXAMPLES_LVGLTERM=y
CONFIG_EXAMPLES_LVGLTERM_FONT_UNSCII_8=y
CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_MATRIX=y
CONFIG_FAT_LCNAMES=y
CONFIG_FAT_LFN=y
CONFIG_FS_FAT=y