1. 添加LCD驱动

如果使用我们提供的系统,默认情况下开启了LCD驱动。LCD跑起来还需要添加相应的设备节点。如何添加设备树插件以及如何修改LCD常用配置参数。

设备树插件源文件位置“/linux_driver/add_lcd_device_tree”。

1.1. LCD常用参数介绍

LCD配置参数主要包括LCD引脚相关配置和LCD显示参数配置。其中背光控制引脚是独立出来的,修改背光引脚的同时也要修改对应的PWM设备信息。

1.1.1. LCD引脚

设备树插件中使用到的引脚。

lcd引脚
 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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
fragment@3 {
    target=<&pinctrl>;
    __overlay__{
        lcd_backlight_pins_a: lcd-backlight {
            pins {
                pinmux = <STM32_PINMUX('A', 15, AF1)>; /* TIM2_CH1 */
                bias-pull-down;
                drive-push-pull;
                slew-rate = <0>;
            };
        };

        lcd_backlight_sleep_pins_a: lcd-backlight-sleep {
            pins {
                pinmux = <STM32_PINMUX('A', 15, ANALOG)>; /* TIM2_CH1 */
            };
        };

        ltdc_pins_a: ltdc-a-0 {
            pins {
                pinmux = <STM32_PINMUX('G',  7, AF14)>, /* LCD_CLK */
                        <STM32_PINMUX('I', 10, AF14)>, /* LCD_HSYNC */
                        <STM32_PINMUX('I',  9, AF14)>, /* LCD_VSYNC */
                        <STM32_PINMUX('E', 13, AF14)>, /* LCD_DE */
                        <STM32_PINMUX('H',  2, AF14)>, /* LCD_R0 */
                        <STM32_PINMUX('H',  3, AF14)>, /* LCD_R1 */
                        <STM32_PINMUX('H',  8, AF14)>, /* LCD_R2 */
                        <STM32_PINMUX('B',  0, AF9)>, /* LCD_R3 */
                        <STM32_PINMUX('A', 5, AF14)>, /* LCD_R4 */
                        <STM32_PINMUX('C',  0, AF14)>, /* LCD_R5 */
                        <STM32_PINMUX('H', 12, AF14)>, /* LCD_R6 */
                        <STM32_PINMUX('E', 15, AF14)>, /* LCD_R7 */
                        <STM32_PINMUX('E', 14, AF13)>, /* LCD_G0 */
                        <STM32_PINMUX('E',  6, AF14)>, /* LCD_G1 */
                        <STM32_PINMUX('H', 13, AF14)>, /* LCD_G2 */
                        <STM32_PINMUX('H', 14, AF14)>, /* LCD_G3 */
                        <STM32_PINMUX('H', 15, AF14)>, /* LCD_G4 */
                        <STM32_PINMUX('I',  0, AF14)>, /* LCD_G5 */
                        <STM32_PINMUX('I',  1, AF14)>, /* LCD_G6 */
                        <STM32_PINMUX('I',  2, AF14)>, /* LCD_G7 */
                        <STM32_PINMUX('D',  9, AF14)>, /* LCD_B0 */
                        <STM32_PINMUX('G', 12, AF14)>, /* LCD_B1 */
                        <STM32_PINMUX('G', 10, AF14)>, /* LCD_B2 */
                        <STM32_PINMUX('D', 10, AF14)>, /* LCD_B3 */
                        <STM32_PINMUX('I',  4, AF14)>, /* LCD_B4 */
                        <STM32_PINMUX('A',  3, AF14)>, /* LCD_B5 */
                        <STM32_PINMUX('B',  8, AF14)>, /* LCD_B6 */
                        <STM32_PINMUX('D',  8, AF14)>; /* LCD_B7 */
                bias-disable;
                drive-push-pull;
                slew-rate = <1>;
            };
        };

        ltdc_pins_sleep_a: ltdc-a-1 {
            pins {
                pinmux = <STM32_PINMUX('G',  7, ANALOG)>, /* LCD_CLK */
                        <STM32_PINMUX('I', 10, ANALOG)>, /* LCD_HSYNC */
                        <STM32_PINMUX('I',  9, ANALOG)>, /* LCD_VSYNC */
                        <STM32_PINMUX('E', 13, ANALOG)>, /* LCD_DE */
                        <STM32_PINMUX('H',  2, ANALOG)>, /* LCD_R0 */
                        <STM32_PINMUX('H',  3, ANALOG)>, /* LCD_R1 */
                        <STM32_PINMUX('H',  8, ANALOG)>, /* LCD_R2 */
                        <STM32_PINMUX('B',  0, ANALOG)>, /* LCD_R3 */
                        <STM32_PINMUX('A',  5, ANALOG)>, /* LCD_R4 */
                        <STM32_PINMUX('C',  0, ANALOG)>, /* LCD_R5 */
                        <STM32_PINMUX('H', 12, ANALOG)>, /* LCD_R6 */
                        <STM32_PINMUX('E', 15, ANALOG)>, /* LCD_R7 */
                        <STM32_PINMUX('E', 14, ANALOG)>, /* LCD_G0 */
                        <STM32_PINMUX('E',  6, ANALOG)>, /* LCD_G1 */
                        <STM32_PINMUX('H', 13, ANALOG)>, /* LCD_G2 */
                        <STM32_PINMUX('H', 14, ANALOG)>, /* LCD_G3 */
                        <STM32_PINMUX('H', 15, ANALOG)>, /* LCD_G4 */
                        <STM32_PINMUX('I',  0, ANALOG)>, /* LCD_G5 */
                        <STM32_PINMUX('I',  1, ANALOG)>, /* LCD_G6 */
                        <STM32_PINMUX('I',  2, ANALOG)>, /* LCD_G7 */
                        <STM32_PINMUX('D',  9, ANALOG)>, /* LCD_B0 */
                        <STM32_PINMUX('G', 12, ANALOG)>, /* LCD_B1 */
                        <STM32_PINMUX('G', 10, ANALOG)>, /* LCD_B2 */
                        <STM32_PINMUX('D', 10, ANALOG)>, /* LCD_B3 */
                        <STM32_PINMUX('I',  4, ANALOG)>, /* LCD_B4 */
                        <STM32_PINMUX('A',  3, ANALOG)>, /* LCD_B5 */
                        <STM32_PINMUX('B',  8, ANALOG)>, /* LCD_B6 */
                        <STM32_PINMUX('D',  8, ANALOG)>; /* LCD_B7 */
            };
        };
    };
};

如果修改了LCD显示屏的引脚,需要在这里修改对应的引脚。

lcd背光pwm设置
 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
fragment@1 {
    target-path="/";
    __overlay__{
        lcd-backlight {
            compatible = "pwm-backlight";
            pwms = <&pwm2 0 1000000>;
            brightness-levels = <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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
            default-brightness-level = <90>;
            status = "okay";
        };
    };
};

fragment@2 {
    target=<&timers2>;
    __overlay__{
        /* spare dmas for other usage */
        /delete-property/dmas;
        /delete-property/dma-names;
        status = "okay";
        pwm2: pwm {
            pinctrl-0 = <&lcd_backlight_pins_a>;
            pinctrl-1 = <&lcd_backlight_sleep_pins_a>;
            pinctrl-names = "default", "sleep";
            #pwm-cells = <2>;
            status = "okay";
        };
        timer@1 {
            status = "okay";
        };
    };
};

背光引脚被复用为PWM的输出,如果修改了背光引脚也要在这里修改使用的pwm。

1.1.2. LCD属性设置

通常情况我们参考官方开发板设计硬件LCD使用的引脚和官方一致即可。我们经常要修改的是LCD一些配置参数,例如分辨率、时钟、无效行数。

lcd配置参数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/*-------第一组---------*/
clock-frequency = <27000000>;
hactive = <800>;
vactive = <480>;

/*-------第二组---------*/
hfront-porch = <23>;
hback-porch = <46>;
vback-porch = <22>;
vfront-porch = <22>;

/*-------第三组---------*/
hsync-len = <1>;
vsync-len = <1>;

/*-------第四组---------*/
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;

配置参数可分为四组,第一组是设置分辨率和时钟。第二组设置“可视区域”,它们的缩写就是我们常说的HFP、hbp、vbp、vfp、行同步信号到第一个像素点的延时时间,单位(像素),一行的最后一个像素点到下一个行同步信号的延时时间(单位像素),帧同步信号到第一个有效行之间的时间,最后一行到下一个帧同步信号 之间的时间。第三组,设置行同步信号和帧同步信号的脉宽。第四组,设置行同步信号、帧同步信号、数据信号、像素时钟信号的极性。以上内容要根据自己使用的显示屏说明文档配置。

由于野火的LCD设备树以设备树插件的形式提供,我们可以使用file-config软件配置屏幕参数。参考 《fire-config修改液晶参数》

1.2. 测试程序

驱动已经编译进内核中,设备树插件加载成功后,驱动会生成“/dev/fb0”文件,这个文件就是显示屏的设备节点文件。

测试程序通过读、写这个文件测试显示是否正常。

源码位于“linux_driver/add_lcd_device_tree/test_app”。

测试程序仅针对5寸800*480分辨率的显示屏,其他分辨率会出现显示异常及程序异常结束的情况。

进入源码目录,执行“make”命令可编译出测试代码,上传到开发板,使用chmod添加执行权限后执行即可。