首页 > 其他分享 >全志V3S开发(六)-TFT屏幕适配

全志V3S开发(六)-TFT屏幕适配

时间:2024-08-24 17:24:16浏览次数:16  
标签:par V3S 适配 全志 dev fbtft ret gpio size

一、环境及demo目标

1. 我使用的内核版本是5.2.y。

2. 我使用的并不是Licheepi官方给出的RGB屏,而是2.4寸ST7789V-TFTLCD屏幕,分辨率为240*320。因此需要在linux Kernel中对屏幕进行适配,这个demo最终能将终端显示在屏幕上。

二、硬件连接

licheepi开发板与TFT屏幕之间按照如下线序进行连接:

硬件线序
TFT屏幕licheepi开发板备注
3.3V3.3V必须接
GNDGND必须接
BLPWM0背光引脚,不需要调节的话直接接3V3
SCKSPI-SCK必须接
RSTU2R必须接,可以自己改
CSSPI-CS必须接
DCU2T必须接
MOSI(SDI)MOSI必须接
MISO(SDO)MISO可不接

三、配置Linux Kernel的menuconfig

 1. 进入/home/daemonchen/linux/V3S/linux_kernel/linux/linux-zero-5.2.y文件夹,在Licheepi_MY_Ethernet_defconfig的基础上进行修改。

cd /home/daemonchen/linux/V3S/linux_kernel/linux/linux-zero-5.2.y
export ARCH=arm
export CROSS_COMPILE=$CROSS_COMPILE
make Licheepi_MY_Ethernet_defconfig
make menuconfig

2. 进入menuconfig以后按照以下路径进行修改:

#使能ST7789V芯片
Device Drivers  --->
    [*] Staging drivers  --->
        <*> Support for small TFT LCD display modules  --->
            <*> FB driver for the ST7789V LCD Controller

#如有需要,使能开机企鹅logo,一般用作屏幕测试
Device Drivers  --->
    Graphics support  --->
        [*] Bootup logo  --->
            [*]   Standard black and white Linux logo (NEW)                  
            [*]   Standard 16-color Linux logo (NEW)                         
            [*]   Standard 224-color Linux logo (NEW)

3. 保存退出

4. 为了方便下次直接调用这些配置,使用下列命令将配置保存为Licheepi_MY_LCD_defconfig.

make savedefconfig
cp defconfig arch/arm/configs/Licheepi_MY_LCD_defconfig

四、更改设备树及内核文件

 1. 首先打开arch/arm/boot/dts/Makefile,注释掉sun8i-v3s-licheepi-zero-with-480x272-lcd.dtb/sun8i-v3s-licheepi-zero-with-800x480-lcd.dtb/sun8i-v3s-licheepi-zero-with-1024x600-lcd.dtb,我们只编译sun8i-v3s-licheepi-zero-dock.dtb和sun8i-v3s-licheepi-zero.dtb,注意“\”后面千万不要有空格!如下图所示:

 2. 打开arch/arm/boot/dts下的sun8i-v3s.dtsi,做如下更改:

注释掉57-64行(关闭默认视频输出):

 注释掉353-356行(关闭pwm0,与屏幕引脚冲突):

注释掉 464-473行(关闭uart2,与屏幕引脚冲突):

保存退出。

 3. 打开arch/arm/boot/dts下的sun8i-v3s-licheepi-zero-dock.dts,做如下更改:

在文件末尾加上spi0的追加节点,即st7789v的设备树节点:

&spi0{
    status = "okay";
    st7789v: st7789v@0{
        compatible = "sitronix,st7789v";
        reg = <0>;
        status = "okay";
        spi-max-frequency = <36000000>;
        spi-cpol;
        spi-cpha;
        rotate = <90>;
        fps = <30>;
        buswidth = <8>;
        rgb;
        tft-dc-gpios    = <&pio 1 0 GPIO_ACTIVE_HIGH>;  // PB0 
        tft-reset-gpios = <&pio 1 1 GPIO_ACTIVE_HIGH>;  // PB1
        tft-led-gpios   = <&pio 1 4 GPIO_ACTIVE_HIGH>;  // PB4
        width = <240>;
        height= <320>;
        debug = <0>;
    };
};

如下图所示:

4. 打开drivers/staging/fbtft/fbtft-core.c文件,修改fbtft_request_one_gpio函数,注意需要在该文件上引入下面头文件,否则编译报错。

#include <linux/of_gpio.h>
static int fbtft_request_one_gpio(struct fbtft_par *par,
				  const char *name, int index,
				  struct gpio_desc **gpiop)
{
/*
	struct device *dev = par->info->device;
	struct device_node *node = dev->of_node;
	int ret = 0;

	if (of_find_property(node, name, NULL)) {
		*gpiop = devm_gpiod_get_index(dev, dev->driver->name, index,
					      GPIOD_OUT_HIGH);
		if (IS_ERR(*gpiop)) {
			ret = PTR_ERR(*gpiop);
			dev_err(dev,
				"Failed to request %s GPIO:%d\n", name, ret);
			return ret;
		}
		fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
			      __func__, name);
	}

	return ret;
*/
	struct device *dev = par->info->device;
    struct device_node *node = dev->of_node;
    int gpio, flags, ret = 0;
    enum of_gpio_flags of_flags;
    char gpio_names[32];

    //sprintf(gpio_names, "%s-gpios", name);
    sprintf(gpio_names, "%s", name);
    printk("@ gpio_names = %s\n", gpio_names);
    if (of_find_property(node, gpio_names, NULL)) {
        gpio = of_get_named_gpio_flags(node, gpio_names, index, &of_flags);
        printk ("@ gpio = %d | ENOENT = %d | EPROBE_DEFER = %d  \n", gpio, ENOENT, EPROBE_DEFER);
        if (gpio == -ENOENT)
            return 0;
        if (gpio == -EPROBE_DEFER)
            return gpio;
        if (gpio < 0) {
            dev_err(dev,
                "failed to get '%s' from DT\n", gpio_names);
            return gpio;
        }

         //active low translates to initially low 
        flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW :
                            GPIOF_OUT_INIT_HIGH;
        ret = devm_gpio_request_one(dev, gpio, flags,
                        dev->driver->name);
        if (ret) {
            dev_err(dev,
                "gpio_request_one('%s'=%d) failed with %d\n",
                gpio_names, gpio, ret);
            return ret;
        }

        *gpiop = gpio_to_desc(gpio);
        fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n",
                            __func__, gpio_names, gpio);
    }
    return ret;
}

5. 打开drivers/staging/fbtft/fbtft-core.c文件,修改fbtft_reset函数

static void fbtft_reset(struct fbtft_par *par)
{
	/*
	if (!par->gpio.reset)
		return;
	fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
	gpiod_set_value_cansleep(par->gpio.reset, 0);
	usleep_range(20, 40);
	gpiod_set_value_cansleep(par->gpio.reset, 1);
	msleep(120);
	*/

	if (!par->gpio.reset)
        return;
    fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
    gpiod_set_value_cansleep(par->gpio.reset, 1);
    usleep_range(20, 40);
    gpiod_set_value_cansleep(par->gpio.reset, 0);
    msleep(120);
    gpiod_set_value_cansleep(par->gpio.reset, 1);
    msleep(10);
}

6. 打开drivers/staging/fbtft/fbtft-core.c文件,修改fbtft_request_gpios_dt函数里面,reset和dc引脚名称,从reset-gpios、dc-gpios和 led-gpios 改为tft-reset-gpios 、 tft-dc-gpios 和tft-led-gpios。

7. 打开drivers/staging/fbtft/fbtft-bus.c文件,修改fbtft_write_vmem16_bus8函数,直接替换

int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
{
	u16 *vmem16;
	__be16 *txbuf16 = par->txbuf.buf;
	size_t remain;
	size_t to_copy;
	size_t tx_array_size;
	int i;
	int ret = 0;
	size_t startbyte_size = 0;
 
	fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n",
		      __func__, offset, len);
 
	remain = len / 2;
	vmem16 = (u16 *)(par->info->screen_buffer + offset);
 
	if (par->gpio.dc)
	{
		//printk("dc拉高!\n");
		gpiod_set_value(par->gpio.dc, 1);
	}
	/* non buffered write */
	if (!par->txbuf.buf)
		return par->fbtftops.write(par, vmem16, len);
 
	/* buffered write */
	tx_array_size = par->txbuf.len / 2;
 
	if (par->startbyte) {
		txbuf16 = par->txbuf.buf + 1;
		tx_array_size -= 2;
		*(u8 *)(par->txbuf.buf) = par->startbyte | 0x2;
		startbyte_size = 1;
	}
 
	while (remain) {
		to_copy = min(tx_array_size, remain);
		dev_dbg(par->info->device, "to_copy=%zu, remain=%zu\n",
			to_copy, remain - to_copy);
 
		for (i = 0; i < to_copy; i++)
			txbuf16[i] = cpu_to_be16(vmem16[i]);
 
		vmem16 = vmem16 + to_copy;
		ret = par->fbtftops.write(par, par->txbuf.buf,
						startbyte_size + to_copy * 2);
		if (ret < 0)
			return ret;
		remain -= to_copy;
	}
 
	return ret;
}

五、编译内核和设备树

 1. 输入以下命令进行编译:

make -j16
make  -j16 modules
sudo make -j16 modules_install
make dtbs

2. 将zImage和sun8i-v3s-licheepi-zero-dock.dtb复制到nfs目录下:

cp arch/arm/boot/zImage /home/daemonchen/linux/tftpboot -f
cp arch/arm/boot/dts/sun8i-v3s-licheepi-zero-dock.dtb /home/daemonchen/linux/tftpboot -f

六、启动测试

1.  使用SecureCRT查看串口0输出的log,在uboot界面配置网络相关变量为:

setenv ipaddr 192.168.147.132
setenv gatewayip 192.168.147.2
setenv netmask 255.255.255.0
setenv serverip 192.168.147.130
saveenv

2. 将终端投射在屏幕上(即在bootargs中加入console=tty0):

setenv bootcmd 'tftp 0x41000000 zImage; tftp 0x41800000 sun8i-v3s-licheepi-zero-dock.dtb; bootz 0x41000000 - 0x41800000'
setenv bootargs 'console=tty0 console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.147.130:/home/daemonchen/linux/nfs/rootfs ip=192.168.147.132:192.168.147.130:192.168.147.2:255.255.255.0::eth0::off init=/linuxrc'
saveenv

3. 启动测试:

boot

启动成功后Linux内核输出以下log:

 屏幕端显示企鹅logo和终端信息:

至此TFT屏幕适配linux内核完成!

标签:par,V3S,适配,全志,dev,fbtft,ret,gpio,size
From: https://blog.csdn.net/Jlinkneeder/article/details/141435866

相关文章

  • 全志V3S开发(五)-Kernel适配以太网以及nfs、tftp服务开启
    一、Kernel适配Ethernet我使用的linux_kernel版本是5.2.y<1> 配置menuconfig进入linuxkernel目录下/home/daemonchen/linux/V3S/linux_kernel/linux/linux-zero-5.2.y,首先配置menuconfig。makeARCH=armmenuconfig按照如下路径进行配置:#配置以太网DeviceDrivers---......
  • 全志V3S开发(一)-主线uboot移植及适配以太网
    一、安装交叉编译器1.新建一个交叉编译器的工具目录,我的目录是/home/daemonchen/linux/tool,并在该目录下打开终端。2.安装arm-linux交叉编译器gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf-develop-11.0.zip(注意必须必须必须是这个版本,否则后面设置完网络环境会报......
  • Android开发 - (适配器)Adapter类中(蓝牙适配器)BluetoothAdapter实现类解析
    什么是BluetoothAdapterBluetoothAdapter是一个重要的类,用于管理和操作蓝牙功能。它提供了与蓝牙设备进行交互的能力,它代表了本地蓝牙适配器的功能。简单来说,它是你与设备上的蓝牙硬件进行交互的接口。通过BluetoothAdapter,你可以控制蓝牙的开启和关闭,发现附近的蓝牙设备,管理......
  • 京东小程序折叠屏适配探索
    前言随着近年来手机行业的飞速发展,手机从功能机进入到智能机,手机屏幕占比也随着技术和系统的进步越来越大,特别是Android10推出以后,折叠屏逐渐成为Android手机发展的趋势。图1Android手机屏幕发展趋势京东小程序近年来也支持了越来越多的业务和应用,做好小程序的折叠屏的适配......
  • 国产化适配——银河麒麟V10(1)
    前言为响应国家“信创”建设,公司最近在搞国产化适配,我刚好负责这搞一部分,做个记录吧。主要包括三块:国产服务器操作系统银河麒麟V10,国产数据库人大金仓kingbase,中间件Tongweb。 这一期记录银河麒麟适配中遇到的一些问题。系统版本:KylinLinuxAdvancedServerV10(Sword)......
  • Apache SeaTunnel数据处理引擎适配的演进和规划
    作者|ChaoTian(tyrantlucifer),ApacheSeaTunnelPMCMember摘要ApacheSeaTunnel作为一个高性能数据同步工具,以其高效的数据处理能力,为数据集成领域带来了创新。在引擎上,ApacheSeaTunnel除了支持自身的Zeta引擎外,还支持Spark和Flink。在2024年的CommunityOverCodeAsia,Apa......
  • RISC-V全志D1sCVBS套件文章汇总
    RISC-V全志D1sCVBS套件提示此开发板的任何问题都可以在我们的论坛交流讨论 https://forums.100ask.net/c/10-category/75-category/75文章目录汇总 文章共计4章,下面是章节汇总:第0章_RISC-V全志D1sCVBS套件第1章_快速启动第2章_安装并配置开发环境第3章_Tina-SDK开......
  • VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS 标准版和厂商定制版,已适配主流品牌服务
    VMwareESXi8.0U3macOSUnlocker&OEMBIOS标准版和厂商定制版ESXi8.0U3标准版,Dell(戴尔)、HPE(慧与)、Lenovo(联想)、Inspur(浪潮)、Cisco(思科)、Hitachi(日立)、Fujitsu(富士通)、NEC(日电)定制版、Huawei(华为)OEM定制版请访问原文链接:https://sysi......
  • Android 11.0 通过系统属性适配多种分辨率开机动画功能实现
    1.前言 在11.0的系统ROM定制化开发中,在关于开机动画这部分由于产品需要适配多种分辨率,所以就需要在出rom固件的时候,就需要根据系统属性来适配显示哪种分辨率开机动画,所以接下来就来看怎么设置系统属性,然后在开机动画阶段怎么实现这个功能2.通过系统属性适配多种分辨率开......
  • RISC-V全志D1多媒体套件文章汇总
    提示此开发板的任何问题都可以在我们的论坛交流讨论 https://forums.100ask.net/c/aw/d1/57文章目录汇总教程共计14章,下面是章节汇总:第0章_RISC-V全志D1多媒体套件第1章_快速启动1_1快速开始使用1_2学习路线第2章_安装并配置开发环境第3章_Tina-SDK开发......