当前位置:   article > 正文

【全志T113-S3_100ask】15-1 内核5.4驱动spi屏幕——ILI9341_t113 mipi

t113 mipi

背景

  • 本来想直接驱动mipi屏幕的,但是发现有一点点难度,所以想先研究一下小屏幕如何驱动。
  • 本文章使用的芯片为全志T113-s3,目前使用的核心板是100ask的,但是官方开发板上面的spi接口不齐全,所以自制了一块板子进一步学习。

(一)spi设备树

1、修改设备树

在原本的设备树中,配置是错误的,引脚都对不上,应该是参考D1-H的文档,然后拷贝过来的。
然后看了芯片的手册,引脚配置如下:
在这里插入图片描述
在 Function4 中有spi1相关的配置,从PD10到PD15
修改设备树 spi1 的引脚,如下:

	spi1_pins_a: spi1@0 {
		pins = "PD11", "PD12", "PD13","PD14", "PD15"; /*clk mosi miso hold wp*/
		function = "spi1";
		drive-strength = <10>;
	};

	spi1_pins_b: spi1@1 {
		pins = "PD10";
		function = "spi1";
		drive-strength = <10>;
		bias-pull-up;   // only CS should be pulled up
	};

	spi1_pins_c: spi1@2 {
		allwinner,pins = "PD10", "PD11", "PD12", "PD13","PD14", "PD15";
		allwinner,function = "gpio_in";
		allwinner,muxsel = <0>;
		drive-strength = <10>;
	};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在这里插入图片描述
此时spi总线已经配置好了

2、完善设备树

因为我们本次驱动的屏幕为ili9341,改屏幕的驱动已经在内核里,直接使能使用即可,但是我们要修改设备树,参考修改手册:
在这里插入图片描述
手册上说明,一定要配置
- compatible: "adafruit,yx240qv29", "ilitek,ili9341"
- dc-gpios: D/C pin
- reset-gpios: Reset pin
但是可以参考一下配置进行设置:
在 spi1 节点下:

ili9341@0{
		#address-cells = <1>;
		#size-cells = <1>;
        compatible = "ilitek,ili9341";
        reg = <0>;
        spi-max-frequency = <32000000>;
        dc-gpios = <&pio PD 16 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&pio PD 17 GPIO_ACTIVE_HIGH>;
		rotate = <90>;
		spi-cpol;  //SPI引脚模式
		spi-cpha; //SPI引脚模式
		bgr;//颜色格式为RGB
        fps = <30>;
        buswidth = <8>;
        // backlight = <&backlight>;
		status = "okay";
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如下所示:
在这里插入图片描述
我们还用到了dc和rst引脚,这两个引脚可以随便找个io,但是不能和其他引脚冲突。
需要在pio节点下配置

	lcd_dc: lcd_dc{
				allwinner,pins = "PD16"; 
			};
	lcd_rst: lcd_rst{
				allwinner,pins = "PD17"; 
			};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如下所示:
在这里插入图片描述

此时已经将设备树修改完毕。

(二)使能内核

1、在内核目录下如 linux-origin_master ,输入make menuconfig 进入内核菜单设置页面
在这里插入图片描述
2、然后左斜杠 / 进入搜索,输入 ili9341,回车即可找到相关的驱动

在这里插入图片描述
在这里插入图片描述
然后使能该项(别问我怎么使能)

或者一步步找到该驱动

 Location:                                                                                                                             │
  │     -> Device Drivers                                                                                                                   │
  │       -> Staging drivers (STAGING [=y])                                                                                                 │
  │         -> Support for small TFT LCD display modules (FB_TFT [=y])  
  • 1
  • 2
  • 3
  • 4

(三)兼容性修改

  • 对于比较高版本的内核比如我现在的5.4,如果直接编译的话,是使用不了屏幕的,因为内核在不断更新,但是对于屏幕的驱动,并没有及时更新,甚至这个驱动代码可能是八年前的代码。
  • 主要修改的文件为 fbtft-core.c
  • 参考路径:build/linux-origin_master/drivers/staging/fbtft/fbtft-core.c

1- 在 fbtft-core.c 添加头文件

#include "linux/gpio.h"
#include "linux/of_gpio.h"
  • 1
  • 2

2- 找到里面的 fbtft_request_one_gpio()函数,替换该函数的内容,修改后如下:

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 gpio, flags, ret = 0;
    enum of_gpio_flags of_flags;
    if (of_find_property(node, name, NULL)) {
        gpio = of_get_named_gpio_flags(node, name, index, &of_flags);
        if (gpio == -ENOENT)
            return 0;
        if (gpio == -EPROBE_DEFER)
            return gpio;
        if (gpio < 0) {
            dev_err(dev,
                "failed to get '%s' from DT\n", name);
            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",
                name, gpio, ret);
            return ret;
        }

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

    return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

3- 找到里面的 fbtft_request_gpios_dt()函数,替换该函数的内容,修改后如下:

static int fbtft_request_gpios_dt(struct fbtft_par *par)
{
    int i;
    int ret;

    ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs);
    if (ret)
        return ret;
    ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch);
    if (ret)
        return ret;
    for (i = 0; i < 16; i++) {
        ret = fbtft_request_one_gpio(par, "db-gpios", i,
                         &par->gpio.db[i]);
        if (ret)
            return ret;
        ret = fbtft_request_one_gpio(par, "led-gpios", i,
                         &par->gpio.led[i]);
        if (ret)
            return ret;
        ret = fbtft_request_one_gpio(par, "aux-gpios", i,
                         &par->gpio.aux[i]);
        if (ret)
            return ret;
    }

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

4- 找到里面的 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, 1);
    msleep(10);
    gpiod_set_value_cansleep(par->gpio.reset, 0);
    msleep(200);
    gpiod_set_value_cansleep(par->gpio.reset, 1);
    msleep(10);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

修改完以上三个函数,就可以编译内核和buildroot。后续步骤省略。

(四)测试

1、接线
按照屏幕的接线方案进行接线,一一对应就好没啥好说的。
2、上电
上电之后屏幕由白到黑,应该是驱动加载成功了。
3、查看启动时的内核信息

# dmesg | grep "fb"
[    4.470009] fbtft_of_value: buswidth = 8
[    4.474498] fbtft_of_value: rotate = 90
[    4.478946] fbtft_of_value: fps = 30
[    4.950907] graphics fb0: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=33, spi1.0 at 32 MHz
  • 1
  • 2
  • 3
  • 4
  • 5

4、花点测试(随机填充)

 cat /dev/urandom > /dev/fb0
  • 1

在这里插入图片描述

5、自带工具测试

# fb-test
fb-test 1.1.1 (rosetta)
fb res 320x240 virtual 320x240, line_len 640, bpp 16
  • 1
  • 2
  • 3

现象如下:

在这里插入图片描述

# fb-test-rect
rect 1.1.1 (rosetta)
  • 1
  • 2

现象如下:
在这里插入图片描述

至此,屏幕驱动完毕。可以进一步研究c语言驱动屏幕,或者lvgl驱动。

END.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/762265
推荐阅读
相关标签
  

闽ICP备14008679号