FPGAを使ったRISC-V SoC(第2回)タッチスクリーンを動かす
はじめに
今回は、TFTディスプレイとタッチスクリーンを動かすにあたりArty A7のArduinoシールド互換コネクタにそのまま接続できるAdafruit 2.8 TFT Touch Shieldを使うことにしました。
全体の流れ
- FPAG(Litex SoC) H/W(Pin)構成を、Adafruit 2.8 TFT Touch Shieldに合わせて変更する
- Linux KernelにFrame Buffer、TFTディスプレイとタッチスクリーンのドライバを追加する
- DTS(Device Tree Source)にTFTディスプレイ(SPI)とタッチスクリーン(I2C)を追加する
- デモに必要なパッケージを追加する
使用機材
- 第1回で使用した機材
- Adafruit 2.8 TFT Touch Shield
スペック
画面 : 2.8インチ、240 x 320、18ビットカラー
TFTコントローラ : ILI9341 SPI I/F
タッチスクリーンコントローラ : FT6206 I2C接続
Litex SoCのPin構成
FPAG(Litex SoC) H/W(Pin)構成を、Adafruit 2.8 TFT Touch Shieldに合わせて変更
TFTディスプレイ
TFTコントローラ(ILI9341)のDC/RS(LCD register / data selection)をGPIOで制御できるように以下のようにFPGAの構成を変更。
litex-boards/litex_boards/platforms/digilent_arty.py
@@ -22,6 +22,7 @@
("user_led", 1, Pins("J5"), IOStandard("LVCMOS33")),
("user_led", 2, Pins("T9"), IOStandard("LVCMOS33")),
("user_led", 3, Pins("T10"), IOStandard("LVCMOS33")),
+ ("user_led", 4, Pins("M16"), IOStandard("LVCMOS33")),
("rgb_led", 0,
Subsignal("r", Pins("G6")),
タッチスクリーン
タッチスクリーンコントローラ (FT6206)のINT(Interrupt output)をGPIOで制御できるように以下のようにFPGAの構成を変更。
litex-boards/litex_boards/platforms/digilent_arty.py
@@ -52,7 +53,7 @@
("user_sw", 0, Pins("A8"), IOStandard("LVCMOS33")),
("user_sw", 1, Pins("C11"), IOStandard("LVCMOS33")),
("user_sw", 2, Pins("C10"), IOStandard("LVCMOS33")),
- ("user_sw", 3, Pins("A10"), IOStandard("LVCMOS33")),
+ ("user_sw", 3, Pins("T16"), IOStandard("LVCMOS33")),
# Buttons
("user_btn", 0, Pins("D9"), IOStandard("LVCMOS33")),
Adafruit 2.8 TFT Touch Shield のPIN配置は以下の様になる。
Linux Kernelの変更
TFTディスプレイ
TFTコントローラ(ILI9341)をLinuxフレームバッファとして機能されるため、LinuxカーネルコンフィグレーションとDTS(Device Tree Source)に以下の変更を加える。
Linuxカーネルコンフィグレーションの以下を有効とする
$ cd ˜/buildroot/
$ make linux-menuconfig
-> Device Drivers
-> Graphics support
-> Frame buffer Devices
-> Support for frame buffer devices
-> Display Panels
-> Ilitek ILI9341 240x320 QVGA panels
-> Staging drivers
-> Support for small TFT LCD display modules
-> FB driver for the ILI9341 LCD Controller
タッチスクリーン
以下のサイトからダウンロードしたドライバをLinuxカーネルに組み込み変更を行う。
t6236.cのダウンロード
$ cd ~/buildroot/output/build/linux-ae80e67c6b48bbedcd13db753237a25b3dec8301/drivers/input/touchscreen
$ wget https://raw.githubusercontent.com/ipts-linux-org/ipts-linux/master/drivers/input/touchscreen/ft6236.c
drivers/input/ft6236.cの変更
@@ -22,6 +22,9 @@
#include <linux/module.h>
#include <linux/property.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+
#define FT6236_MAX_TOUCH_POINTS 2
#define FT6236_REG_TH_GROUP 0x80
@@ -278,10 +281,24 @@
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error)
return error;
-
+#if 0
error = devm_request_threaded_irq(dev, client->irq, NULL,
ft6236_interrupt, IRQF_ONESHOT,
client->name, ft6236);
+#else
+{
+ int ft5x06_gpio_irq = 505;
+ error = gpio_request(ft5x06_gpio_irq, "edt_ft6236 irq");
+ printk ( " gpio_request=%d (%d:%d)\n", error, ft5x06_gpio_irq, gpio_to_irq(ft5x06_gpio_irq) );
+ if (!error) {
+ gpio_direction_input(ft5x06_gpio_irq);
+
+ error = request_irq(gpio_to_irq(ft5x06_gpio_irq),
+ ft6236_interrupt, IRQF_ONESHOT,
+ client->name, ft6236);
+ }
+}
+#endif
if (error) {
dev_err(dev, "request irq %d failed: %d¥n", client->irq, error);
return error;
drivers/input/Makefileの変更
@@ -44,6 +44,7 @@
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
+obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_ts.o+
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
drivers/input/Kconfigの変更
@@ -372,6 +372,18 @@
To compile this driver as a module, choose M here: the
module will be called exc3000.
+config TOUCHSCREEN_FT6236
+ tristate "FT6236 I2C touchscreen"
+ depends on I2C
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ Say Y here to enable support for the I2C connected FT6x06 and
+ FT6x36 family of capacitive touchscreen drivers.
+
+ If unsure, say N.
+
+ To compile this driver as a module
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
Linuxカーネルコンフィグレーションの変更
$ make linux-menuconfig
-> Device Drivers
-> Input device support
-> Generic input layer (needed for keyboard, mouse, ...)
-> Event interface
-> Touchscreens
-> FT6236 I2C touchscreen
DTS(Device Tree Source)の変更
TFTディスプレイ
TFTディスプレイをLinuxフレームバッファとして機能させるため、DTSに以下の変更を行う
˜/litex-vexriscv/linux-on-litex-vexriscv/build/arty_a7/arty_a7_mmc.dts
@@ -237,10 +237,12 @@
#address-cells = <1>;
#size-cells = <0>;
- spidev0: spidev@0 {
- compatible = "linux,spidev";
- reg = <0>;
- spi-max-frequency = <1000000>;
+ display@0 {
+ compatible = "adafruit,yx240qv29", "ilitek,ili9341";
+ reg = <0x00>;
+ spi-max-frequency = <3000000>;
+ rotation = <90>;
+ dc-gpios = <&leds 4 0>;
status = "okay";
};
};
@@ -330,7 +351,7 @@
};
&leds {
- litex,ngpio = <4>;
+ litex,ngpio = <5>;
status = "okay";
};
タッチスクリーン
FT6206をタッチスクリーンとして機能させるため、DTSに以下の変更を行う。
˜/litex-vexriscv/linux-on-litex-vexriscv/build/arty_a7/arty_a7_mmc.dts
@@ -251,6 +253,14 @@
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
+ touchscreen@38 {
+ compatible = "focaltech,ft6236";
+ interrupt-parent = <&switches>;
+ interrupts = <0 2>; /* TOUCH_INT# */
+ reg = <0x38>;
+ touchscreen-size-x = <240>;
+ touchscreen-size-y = <320>;
+ };
};
hwmon0: xadc@f000b800 {
@@ -336,7 +357,7 @@
&switches {
- litex,ngpio = <4>;
+ litex,ngpio = <5>;
status = "okay";
};
タッチイベント不具合対応
input_event構造体の問題で、タッチイベントをアプリでうまく取得することが出来なかった為、input.hに以下の修正を加えました。
「~/buildroot/output/build/linux-ae80e67c6b48bbedcd13db753237a25b3dec8301/include/uapi/linux/input.h」
#define input_event_usec time.tv_usec
#else
- __kernel_ulong_t __sec;
+ __u64 __sec;
#if defined(__sparc__) && defined(__arch64__)
unsigned int __usec;
unsigned int __pad;
#else
- __kernel_ulong_t __usec;
+ __u64 __usec;
#endif
QTアプリ(お絵描きソフト)
QTアプリを動かすために事前準備として、LinuxカーネルコンフィグレーションでUnix domain Socketを有効する。
Unix domain Socketを有効
$ cd buildroot/
$ make linux-menuconfig
-> Networking support
-> Networking options
-> Unix domain sockets
QTアプリを動かす為には、Buildrootのコンフィグレーションでライブラリの追加とQTの追加が必要です。
タッチスクリーン系のライブラリとフォントを有効
$ cd buildroot/
$ make menuconfig
-> Toolchain
-> Enable C++ support
-> Target packages
-> Fonts, cursors, icons, sounds and themes
-> Liberation (Free fonts)
-> Libraries
-> Hardware handling
-> tslib
-> Other
-> libevdev
QTアプリの有効化
$ make menuconfig
-> Target packages
-> Graphic libraries and applications (graphic/text)
-> Qt5
-> qt5base
-> Compile and install examples (with code)
-> concurrent module
-> gui module
-> widgets module
-> fontconfig support
-> harfbuzz support
-> GIF support
-> JPEG support
-> PNG support
-> DBus module
-> Enable ICU support
-> Enable Tslib support
変更後ビルドを実行し、SDカードに書き込む。
ターゲット起動後、タッチスクリーンのキャリブレーションを実行する。
# ts_calibrate
※実行後タッチスクリーンにキャリブレーション用の画面が表示されるので指示に従い実行。
環境変数を設定し、QTのお絵描きアプリ「scribble」を実行する。
# export QT_QPA_FB_NO_LIBINPUT='1'
# export QT_QPA_FB_TSLIB='1'
# export QT_QPA_PLATFORM='linuxfb'
# /usr/lib/qt/examples/widgets/widgets/scribble/scribble
おわり
タッチスクリーンと描画、両方の制御ができるので、今回はQTをチョイスしました。
QTには他にもサンプルアプリがあるので動かしてみてください。
課題として残ったことを以下に記載します。
- 画面タッチ後の反応と描画が遅い
- linux kernelのinput_event構造体を変更した