stm32h7/linum-stm32h753bi: add touch screen support

Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
Jorge Guzman 2025-01-19 18:30:15 -03:00 committed by Xiang Xiao
parent 1fd21bbd69
commit 4857ea211f
8 changed files with 386 additions and 5 deletions

View file

@ -232,7 +232,7 @@ EEPROM memory used is the 24LC256 with 256Kb with the control bytes value 0x54.
TOUCHSCREEN SENSOR
------------------
The touchscreen sensor used is the GT928.
The touchscreen sensor used is the FT5X06.
======== =====
GPIO PINS
@ -817,7 +817,37 @@ Configures the board to use the SPI4 and enables RFID driver with MFRC522::
lvgl
----
Configures the board to use display of 7 inch with lvgl example.
Configures the board to use display of 7 inch with lvgl example. The touch screen functionality is implemented using
the FT5X06 capacitive touch controller connected to I2C3 interface, with interrupt handling configured on pin PH9 for touch event detection.
To verify if the touch controller is functioning correctly, use the **tc** command.::
nsh> tc 2
tc_main: nsamples: 2
tc_main: Opening /dev/input0
Sample :
npoints : 1
Point 1 :
id : 0
flags : 19
x : 0
y : 52
h : 0
w : 0
pressure : 0
timestamp : 0
Sample :
npoints : 1
Point 1 :
id : 0
flags : 1a
x : 0
y : 52
h : 0
w : 0
pressure : 0
timestamp : 0
Terminating!
To verify if the display is functioning correctly, use the **fb** command. You should see the display change colors.::
@ -862,11 +892,11 @@ Once the **fd** command work, run the lvgl exemple. ::
**WARNING:** This example at the moment is not working correctly yet and have a bug fix to be done.
In the lvgl file **./apps/graphics/lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c**
search the function **lv_nuttx_fbdev_set_file** and modify line 156 as follows:
search the function **lv_nuttx_fbdev_set_file** and modify line 156 as follows::
dsc->mem_off_screen = malloc(data_size);
to
dsc->mem_off_screen = (void*)0xC00000000;
dsc->mem_off_screen = (void*)0xC0000000;
tone
----

View file

@ -30,10 +30,14 @@ CONFIG_DRIVERS_VIDEO=y
CONFIG_EXAMPLES_ALARM=y
CONFIG_EXAMPLES_FB=y
CONFIG_EXAMPLES_LVGLDEMO=y
CONFIG_EXAMPLES_TOUCHSCREEN=y
CONFIG_FB_OVERLAY=y
CONFIG_FS_PROCFS=y
CONFIG_FT5X06_SINGLEPOINT=y
CONFIG_GRAPHICS_LVGL=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INPUT=y
CONFIG_INPUT_FT5X06=y
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBM=y
CONFIG_LINE_MAX=64
@ -42,6 +46,7 @@ CONFIG_LV_USE_CLIB_SPRINTF=y
CONFIG_LV_USE_CLIB_STRING=y
CONFIG_LV_USE_DEMO_WIDGETS=y
CONFIG_LV_USE_NUTTX=y
CONFIG_LV_USE_NUTTX_TOUCHSCREEN=y
CONFIG_MM_REGIONS=5
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
@ -56,11 +61,13 @@ 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_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_STM32H7_FMC=y
CONFIG_STM32H7_I2C3=y
CONFIG_STM32H7_LTDC=y
CONFIG_STM32H7_LTDC_FB_BASE=0xC0000000
CONFIG_STM32H7_LTDC_FB_SIZE=1228800

View file

@ -412,11 +412,18 @@
#define GPIO_SDMMC1_D2 (GPIO_SDMMC1_D2_0|GPIO_SPEED_100MHz) /* PC10 */
#define GPIO_SDMMC1_D3 (GPIO_SDMMC1_D3_0|GPIO_SPEED_100MHz) /* PC11 */
/* I2C3 - Used by eeprom memory */
/* I2C3 - Used by eeprom memory and touch screen */
#define GPIO_I2C3_SCL (GPIO_I2C3_SCL_2|GPIO_SPEED_100MHz) /* PH7 */
#define GPIO_I2C3_SDA (GPIO_I2C3_SDA_2|GPIO_SPEED_100MHz) /* PH8 */
/* I2C - There is a FT5336 TouchPanel on I2C3 using these pins: */
#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_100MHz))
#define GPIO_TP_INT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTH|GPIO_PIN9) /* PH9 */
#define FT5X06_I2C_ADDRESS (0x38)
/* PWM - Buzzer */
#define GPIO_TIM4_CH2OUT (GPIO_TIM4_CH2OUT_1|GPIO_SPEED_100MHz) /* PB7 */

View file

@ -78,6 +78,10 @@ if(CONFIG_STM32H7_LTDC)
list(APPEND SRCS stm32_lcd.c)
endif()
if(CONFIG_INPUT_FT5X06)
list(APPEND SRCS stm32_touchscreen.c)
endif()
target_sources(board PRIVATE ${SRCS})
set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld")

View file

@ -80,4 +80,8 @@ ifeq ($(CONFIG_AUDIO_TONE),y)
CSRCS += stm32_tone.c
endif
ifeq ($(CONFIG_INPUT_FT5X06),y)
CSRCS += stm32_touchscreen.c
endif
include $(TOPDIR)/boards/Board.mk

View file

@ -287,4 +287,25 @@ int stm32_mfrc522initialize(const char *devpath);
int board_tone_initialize(int devno);
#endif
/****************************************************************************
* Name: stm32_tsc_setup
*
* Description:
* This function is called by board-bringup logic to configure the
* touchscreen device. This function will register the driver as
* /dev/inputN where N is the minor device number.
*
* Input Parameters:
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
#ifdef CONFIG_INPUT_FT5X06
int stm32_tsc_setup(int minor);
#endif
#endif /* __BOARDS_ARM_STM32H7_LINUM_STM32H753BI_SRC_LINUM_STM32H753BI_H */

View file

@ -353,5 +353,15 @@ int stm32_bringup(void)
}
#endif
#ifdef CONFIG_INPUT_FT5X06
/* Initialize the touchscreen */
ret = stm32_tsc_setup(0);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: stm32_tsc_setup failed: %d\n", ret);
}
#endif
return OK;
}

View file

@ -0,0 +1,298 @@
/****************************************************************************
* boards/arm/stm32h7/linum-stm32h753bi/src/stm32_touchscreen.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/input/ft5x06.h>
#include "stm32_gpio.h"
#include "stm32_i2c.h"
#include <arch/board/board.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define FT5X06_FREQUENCY 100000 /* For now, will boost later */
#ifdef CONFIG_INPUT_FT5X06
#ifndef CONFIG_INPUT
# error "FT5x06 support requires CONFIG_INPUT"
#endif
#ifndef CONFIG_STM32H7_I2C3
# error "FT5x06 support requires CONFIG_STM32H7_I2C3"
#endif
#ifndef CONFIG_FT5X06_I2CDEV
# define CONFIG_FT5X06_I2CDEV 3
#endif
#if CONFIG_FT5X06_I2CDEV != 3
# error "CONFIG_FT5X06_I2CDEV must be three"
#endif
#ifndef CONFIG_FT5X06_DEVMINOR
# define CONFIG_FT5X06_DEVMINOR 0
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct stm32_ft5x06_config_s
{
xcpt_t handler; /* The FT5x06 interrupt handler */
void *arg; /* Interrupt handler argument */
};
/****************************************************************************
* Private Function Ptototypes
****************************************************************************/
#ifndef CONFIG_FT5X06_POLLMODE
static int stm32_ft5x06_attach(const struct ft5x06_config_s *config,
xcpt_t isr, void *arg);
static void stm32_ft5x06_enable(const struct ft5x06_config_s *config,
bool enable);
static void stm32_ft5x06_clear(const struct ft5x06_config_s *config);
#endif
static void stm32_ft5x06_wakeup(const struct ft5x06_config_s *config);
static void stm32_ft5x06_nreset(const struct ft5x06_config_s *config,
bool state);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct ft5x06_config_s g_ft5x06_config =
{
.address = FT5X06_I2C_ADDRESS,
.frequency = FT5X06_FREQUENCY,
#ifndef CONFIG_FT5X06_POLLMODE
.attach = stm32_ft5x06_attach,
.enable = stm32_ft5x06_enable,
.clear = stm32_ft5x06_clear,
#endif
.wakeup = stm32_ft5x06_wakeup,
.nreset = stm32_ft5x06_nreset
};
static struct stm32_ft5x06_config_s g_priv_config =
{
.handler = NULL,
.arg = NULL,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_ft5x06_attach
*
* Description:
* Attach an FT5x06 interrupt handler to a GPIO interrupt
*
****************************************************************************/
#ifndef CONFIG_FT5X06_POLLMODE
static int stm32_ft5x06_attach(const struct ft5x06_config_s *config,
xcpt_t isr, void *arg)
{
iinfo("Saving handler %p\n", isr);
/* Just save the handler. We will use it when EXTI interruptsare enabled */
if (isr)
{
/* Just save the address of the handler for now. The new handler will
* be attached when the interrupt is next enabled.
*/
iinfo("Attaching %p\n", isr);
g_priv_config.handler = isr;
g_priv_config.arg = arg;
}
else
{
iinfo("Detaching %p\n", g_priv_config.handler);
stm32_ft5x06_enable(config, false);
g_priv_config.handler = NULL;
g_priv_config.arg = NULL;
}
return OK;
}
#endif
/****************************************************************************
* Name: stm32_ft5x06_enable
*
* Description:
* Enable or disable a GPIO interrupt
*
****************************************************************************/
#ifndef CONFIG_FT5X06_POLLMODE
static void stm32_ft5x06_enable(const struct ft5x06_config_s *config,
bool enable)
{
irqstate_t flags;
/* Attach and enable, or detach and disable. Enabling and disabling GPIO
* interrupts is a multi-step process so the safest thing is to keep
* interrupts disabled during the reconfiguration.
*/
flags = enter_critical_section();
if (enable)
{
/* Configure the EXTI interrupt using the SAVED handler */
stm32_gpiosetevent(GPIO_TP_INT, true, false, true,
g_priv_config.handler, g_priv_config.arg);
}
else
{
/* Configure the EXTI interrupt with a NULL handler to disable it */
stm32_gpiosetevent(GPIO_TP_INT, false, false, false,
NULL, NULL);
}
leave_critical_section(flags);
}
#endif
/****************************************************************************
* Name: stm32_ft5x06_clear
*
* Description:
* Acknowledge/clear any pending GPIO interrupt
*
****************************************************************************/
#ifndef CONFIG_FT5X06_POLLMODE
static void stm32_ft5x06_clear(const struct ft5x06_config_s *config)
{
/* Does nothing */
}
#endif
/****************************************************************************
* Name: stm32_ft5x06_wakeup
*
* Description:
* Issue WAKE interrupt to FT5x06 to change the FT5x06 from Hibernate to
* Active mode.
*
****************************************************************************/
static void stm32_ft5x06_wakeup(const struct ft5x06_config_s *config)
{
/* We do not have access to the WAKE pin in the implementation */
}
/****************************************************************************
* Name: stm32_ft5x06_nreset
*
* Description:
* Control the chip reset pin
*
****************************************************************************/
static void stm32_ft5x06_nreset(const struct ft5x06_config_s *config,
bool nstate)
{
/* We do not have access to the RESET pin in the implementation */
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_tsc_setup
*
* Description:
* This function is called by board-bringup logic to configure the
* touchscreen device. This function will register the driver as
* /dev/inputN where N is the minor device number.
*
* Input Parameters:
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int stm32_tsc_setup(int minor)
{
struct i2c_master_s *dev;
int ret;
iinfo("minor %d\n", minor);
DEBUGASSERT(minor == CONFIG_FT5X06_DEVMINOR);
/* Check if we are already initialized */
iinfo("Initializing\n");
/* Configure the FT5X06 interrupt pin as an input */
stm32_configgpio(GPIO_TP_INT);
/* Get an instance of the I2C interface */
dev = stm32_i2cbus_initialize(CONFIG_FT5X06_I2CDEV);
if (!dev)
{
ierr("ERROR: Failed to initialize I2C bus %d\n", CONFIG_FT5X06_I2CDEV);
return -ENODEV;
}
/* Initialize and register the I2C touchscreen device */
ret = ft5x06_register(dev, &g_ft5x06_config, CONFIG_FT5X06_DEVMINOR);
if (ret < 0)
{
ierr("ERROR: Failed to register FT5x06 driver: %d\n", ret);
stm32_i2cbus_uninitialize(dev);
return ret;
}
return OK;
}
#endif /* CONFIG_INPUT_FT5X06 */