STM32MP157 Linux系統(tǒng)移植開發(fā)篇14:Linux內(nèi)核RGB LCD驅(qū)動(dòng)移植
?本文章為《STM32MP157 Linux系統(tǒng)移植開發(fā)篇》系列中的一篇,筆者使用的開發(fā)平臺(tái)為華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157開發(fā)板)。stm32mp157是ARM雙核,2個(gè)A7核,1個(gè)M4核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實(shí)時(shí)操作系統(tǒng),STM32MP157開發(fā)板所以既可以學(xué)嵌入式linux,也可以學(xué)stm32單片機(jī)。
針對(duì)FS-MP1A開發(fā)板,除了Linux系統(tǒng)移植篇外,還包括其他多系列教程,包括Cortex-A7開發(fā)篇、Cortex-M4開發(fā)篇、擴(kuò)展板驅(qū)動(dòng)移植篇、Linux應(yīng)用開發(fā)篇、FreeRTOS系統(tǒng)移植篇、Linux驅(qū)動(dòng)開發(fā)篇、硬件設(shè)計(jì)篇、人工智能機(jī)器視覺篇、Qt應(yīng)用編程篇、Qt綜合項(xiàng)目實(shí)戰(zhàn)篇等。歡迎關(guān)注,更多stm32mp157開發(fā)教程及視頻,可加技術(shù)交流Q群459754978,感謝關(guān)注。
關(guān)于FS-MP1A開發(fā)板:
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?
鏈接:
1.實(shí)驗(yàn)原理
前文介紹過LTDC的內(nèi)容,本節(jié)只需為LTDC添加一個(gè)面板即可。內(nèi)核中包含一個(gè)通用的面板驅(qū)動(dòng),驅(qū)動(dòng)之包含大量各種各樣的面板。
驅(qū)動(dòng)修改
驅(qū)動(dòng)路徑為:drivers/gpu/drm/panel/panel-simple.c
移植時(shí)可以在驅(qū)動(dòng)中支持新的面板的內(nèi)容,也可以找到一個(gè)與自己面板相仿的內(nèi)容進(jìn)行修改,本節(jié)即使用在原有面板修改的方法。如本節(jié)參考面板名稱為zj070na-01p,對(duì)于一個(gè)面板最關(guān)鍵的內(nèi)容在驅(qū)動(dòng)通過drm_display_mode的結(jié)構(gòu)體描述,zj070na-01p的描述如下:
static const struct drm_display_mode innolux_zj070na_01p_mode = {
.clock = 51501,
.hdisplay = 1024,
.hsync_start = 1024 + 128,
.hsync_end = 1024 + 128 + 64,
.htotal = 1024 + 128 + 64 + 128,
.vdisplay = 600,
.vsync_start = 600 + 16,
.vsync_end = 600 + 16 + 4,
.vtotal = 600 + 16 + 4 + 16,
.vrefresh = 60,
};
這個(gè)結(jié)構(gòu)體主要用來描述面板的時(shí)序相關(guān)信息,時(shí)序框圖如下:

hdisplay:有效顯示區(qū)水平像素?cái)?shù)量,對(duì)應(yīng)Active Width
hsync_start:水平同步開始,對(duì)應(yīng)hdispay + HFP
hsync_end:水平同步結(jié)束,對(duì)應(yīng)hdisplay + HFP + HSYNC width(HPW)
htotal:水平總像素,對(duì)應(yīng)hdisplay + HFP + HSYNC width + HBP
vdisplay:垂直顯示像素,對(duì)應(yīng)Active Height
vsync_start:垂直同步開始,對(duì)應(yīng)vdispay + VFP
vsync_end:垂直像素結(jié)束,對(duì)應(yīng)vdisplay + VFP + VSYNC width(VPW)
vtotal:垂直總像素,對(duì)應(yīng)vdisplay + VFP + VSYNC width + VBP
vrefresh:刷新率
面板芯片手冊(cè)中關(guān)于時(shí)序的描述如下:

表中可以確認(rèn)HBP=140、HPW=20、HFP=160、VBP=20、VPW=3、VFP=12,修改面板信息如下:
static const struct drm_display_mode innolux_zj070na_01p_mode = {
.clock = 51501,
.hdisplay = 1024,
.hsync_start = 1024 + 160,
.hsync_end = 1024 + 160 + 20,
.htotal = 1024 + 160 + 20 + 140,
.vdisplay = 600,
.vsync_start = 600 + 12,
.vsync_end = 600 + 12 + 3,
.vtotal = 600 + 12 + 3 + 12,
.vrefresh = 60,
};
設(shè)備樹修改
增加ltdc輸出端口:
<dc {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep1_out: endpoint@1 {
reg = <1>;
remote-endpoint = <&panel_in_rgb>;
};
};
};
增加面板節(jié)點(diǎn):
panel: panel-rgb {
compatible = "innolux,zj070na-01p";
pinctrl-names = "default", "sleep";
backlight = <&panel_backlight>;
status = "okay";
port {
panel_in_rgb: endpoint {
remote-endpoint = <<dc_ep1_out>;
};
};
};
PWM設(shè)備節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/pwm/pwm-stm32.txt
內(nèi)核中ST對(duì)STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
arch/arm/boot/dts/stm32mp151.dtsi
stm32mp151中timers2定義如下:
timers2: timer@40000000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40000000 0x400>;
clocks = <&rcc TIM2_K>;
clock-names = "int";
dmas = <&dmamux1 18 0x400 0x80000001>,
<&dmamux1 19 0x400 0x80000001>,
<&dmamux1 20 0x400 0x80000001>,
<&dmamux1 21 0x400 0x80000001>,
<&dmamux1 22 0x400 0x80000001>;
dma-names = "ch1", "ch2", "ch3", "ch4", "up";
status = "disabled";
pwm {
compatible = "st,stm32-pwm";
#pwm-cells = <3>;
status = "disabled";
};
timer@1 {
compatible = "st,stm32h7-timer-trigger";
reg = <1>;
status = "disabled";
};
counter {
compatible = "st,stm32-timer-counter";
status = "disabled";
};
};
上述代碼只對(duì)timers5做了基本的初始化,并沒有針對(duì)不同的硬件設(shè)計(jì)做適配,所以需結(jié)合硬件補(bǔ)全設(shè)備樹節(jié)點(diǎn)信息。
參考文檔或stm32mp15xx-dkx.dtsi對(duì)于i2c設(shè)備節(jié)點(diǎn)的描述,增加timers內(nèi)容如下:
&timers2 {
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
pwm2: pwm {
pinctrl-0 = <&pwm2_pins_b>;
pinctrl-1 = <&pwm2_sleep_pins_b>;
pinctrl-names = "default", "sleep";
#pwm-cells = <2>;
status = "okay";
};
timer@2 {
status = "disabled";
};
};
stm32mp15-pinctrl.dtsi對(duì)于pwm2的描述與FS-MP1A所使用管腳不一致,所以無法直接使用,需參考其增加如下內(nèi)容:
pwm2_pins_b: pwm2-0 {
pins {
pinmux = <STM32_PINMUX('A', 5, AF1)>; /* TIM2_CH1 */
bias-pull-down;
drive-push-pull;
slew-rate = <0>;
};
};
pwm2_sleep_pins_b: pwm1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 5, ANALOG)>; /* TIM2_CH1 */
};
};
背光設(shè)備節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
Documentation/devicetree/bindings/leds/backlight/gpio-backlight.txt
FS-MP1A背光可以通過GPIO驅(qū)動(dòng)也可通過PWM2的通道1驅(qū)動(dòng),可以對(duì)比參考文檔或內(nèi)核中其他設(shè)備樹關(guān)于背光的定義。
GPIO驅(qū)動(dòng)背光節(jié)點(diǎn)內(nèi)容如下:
panel_backlight: panel-backlight {
compatible = "gpio-backlight";
gpios = <&gpiod 13 GPIO_ACTIVE_LOW>;
default-on;
status = "okay";
};
PWM驅(qū)動(dòng)背光節(jié)點(diǎn)內(nèi)容如下:
panel_backlight: panel-backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 5000000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
status = "okay";
};
2.實(shí)驗(yàn)?zāi)康?/h1>
熟悉基于Linux操作系統(tǒng)下的攝像頭設(shè)備驅(qū)動(dòng)移植配置過程。
3.實(shí)驗(yàn)平臺(tái)
華清遠(yuǎn)見開發(fā)環(huán)境,F(xiàn)S-MP1A平臺(tái);
4.實(shí)驗(yàn)步驟
導(dǎo)入交叉編譯工具鏈
linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
增加設(shè)備樹文件
由于RGB LCD并非FS-MP1A必須配置,本節(jié)增加一個(gè)設(shè)備樹文件,對(duì)應(yīng)增加了屏幕的設(shè)備。
在內(nèi)核的arch/arm/boot/dts目錄下新建文件stm32mp157a-fsmp1a-rgb070.dts文件并添加如下內(nèi)容:
#include "stm32mp157a-fsmp1a.dts"
/ {
model = "HQYJ STM32MP157 FSMP1A RGB Discovery Board";
compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
};
由于增加了新的設(shè)備樹文件需修改arch/arm/boot/dts/Makefile,在文件中增加新的條目,紅色字體部分為增加內(nèi)容
dtb-$(CONFIG_ARCH_STM32) += \
…..
stm32mp157a-dk1.dtb \
stm32mp157a-fsmp1a.dtb \
stm32mp157a-fsmp1a-mipi050.dtb \
stm32mp157a-fsmp1a-rgb070.dtb \
stm32mp157d-dk1.dtb \
添加pwm2內(nèi)容
修改stm32mp15xx-fsmp1x.dtsi,在stm32mp15xx-fsmp1x.dtsi文件末尾添加如下內(nèi)容:
&timers2 {
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
pwm2: pwm {
pinctrl-0 = <&pwm2_pins_b>;
pinctrl-1 = <&pwm2_sleep_pins_b>;
pinctrl-names = "default", "sleep";
#pwm-cells = <2>;
status = "okay";
};
timer@2 {
status = "disabled";
};
};
&pinctrl {
pwm2_pins_b: pwm2-0 {
pins {
pinmux = <STM32_PINMUX('A', 5, AF1)>; /* TIM2_CH1 */
bias-pull-down;
drive-push-pull;
slew-rate = <0>;
};
};
pwm2_sleep_pins_b: pwm1-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 5, ANALOG)>; /* TIM2_CH1 */
};
};
};
添加背光內(nèi)容
修改stm32mp15xx-fsmp1x.dtsi,在根節(jié)點(diǎn)中添加如下內(nèi)容:
panel_backlight: panel-backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 5000000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
status = "okay";
};
添加ltdc端口
修改文件arm/arm/boot/dts/stm32mp157a-fsmp1a-rgb070.dts,在文件末尾添加如下內(nèi)容:
<dc {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep1_out: endpoint@1 {
reg = <1>;
remote-endpoint = <&panel_in_rgb>;
};
};
};
添加面板信息
修改文件arm/arm/boot/dts/stm32mp157a-fsmp1a-rgb070.dts,在根節(jié)點(diǎn)中添加如下內(nèi)容:
panel: panel-rgb {
compatible = "innolux,zj070na-01p";
pinctrl-names = "default", "sleep";
backlight = <&panel_backlight>;
status = "okay";
port {
panel_in_rgb: endpoint {
remote-endpoint = <<dc_ep1_out>;
};
};
};
修改面板驅(qū)動(dòng),修改面板時(shí)序參數(shù)
修改文件drivers/gpu/drm/panel/panel-simple.c,修改zj070na-01p面板信息,對(duì)照面板芯片手冊(cè)修改原有內(nèi)容,紅色字體部分為修改內(nèi)容:
static const struct drm_display_mode innolux_zj070na_01p_mode = {
.clock = 51501,
.hdisplay = 1024,
.hsync_start = 1024 + 160,
.hsync_end = 1024 + 160 + 20,
.htotal = 1024 + 160 + 20 + 140,
.vdisplay = 600,
.vsync_start = 600 + 12,
.vsync_end = 600 + 12 + 3,
.vtotal = 600 + 12 + 3 + 12,
.vrefresh = 60,
};
配置內(nèi)核
由于內(nèi)核默認(rèn)支持通用面板驅(qū)動(dòng),本節(jié)列出主要選項(xiàng),如下
linux@ubuntu:$ make menuconfig
Device Drivers --->
Graphics support --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
<*> DRM Support for STMicroelectronics SoC Series
Display Panels --->
<*> support for simple panels
Backlight & LCD device support --->
<*> Generic PWM based Backlight Driver
增加啟動(dòng)項(xiàng)
在虛擬機(jī)/tftpboot /tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17末尾添加
LABEL stm32mp157a-fsmp1a-mipi
KERNEL /uImage
FDT /stm32mp157a-fsmp1a-rgb070.dtb
APPEND root=/dev/mmcblk1p4 rootwait rw console=ttySTM0,115200
編譯內(nèi)核及設(shè)備樹
linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
重啟測(cè)試
安裝上7寸LCD面板,將編譯好的設(shè)備樹和內(nèi)核鏡像拷貝到/tftpboot目錄下,通過tftp引導(dǎo)內(nèi)核,啟動(dòng)后可正常顯示,如果屏幕顯示不正可適當(dāng)調(diào)節(jié)面板參數(shù)。

硬件平臺(tái):華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157)
部分開發(fā)教程下載:加QQ群459754978,群文件里有。
部分視頻課程收看:https://space.bilibili.com/670826565/channel/detail?cid=145472
淘寶購買鏈接:https://item.taobao.com/item.htm?id=622457259672
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?