国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32MP157驅(qū)動開發(fā)——Linux LCD驅(qū)動(上)

這篇具有很好參考價值的文章主要介紹了STM32MP157驅(qū)動開發(fā)——Linux LCD驅(qū)動(上)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


0.前言

??LCD 是很常用的一個外設(shè),通過 LCD 可以顯示圖片、界面UI等,提高人機交互的效率。STM32MP1 提供了一個 LTDC 接口用于連接 RGB 接口的液晶屏。本節(jié)就來學(xué)習(xí)如何使用這個接口。

一、LCD 和 LTDC 簡介

1.LCD 簡介

??LCD 全稱是 Liquid Crystal Display,也就是液晶顯示器,是現(xiàn)在最常用到的顯示器。網(wǎng)上對于 LCD 的原理解釋如下:

LCD 的構(gòu)造是在兩片平行的玻璃基板當(dāng)中放置液晶盒,下基板玻璃上設(shè)置 TFT(薄膜晶體管),上基板玻璃上設(shè)置彩色濾光片,通過 TFT 上的信號與電壓改變來控制液晶分子的轉(zhuǎn)動方向,從而達到控制每個像素點偏振光出射與否而達到顯示目的。

現(xiàn)在要在 STM32MP1 開發(fā)板上使用 LCD,不需要去研究 LCD 的具體實現(xiàn)原理,只需要從使用的角度去關(guān)注 LCD 的幾個重要點:

1)分辨率

??提起 LCD 顯示器,我們都會聽到 720P、1080P、2K 或 4K 這樣的字眼,這個就是 LCD 顯示器分辨率。LCD 顯示器都是由一個個的像素點組成,像素點就類似一個燈(在 OLED 顯示器中,像素點就是一個小燈),這個小燈是 RGB 燈,也就是由 R(紅色)、 G(綠色)和 B(藍色)這三種顏色組成的,而 RGB 就是光的三原色。1080P 的意思就是 LCD 屏幕上的像素數(shù)量是 19201080 個,也就是這個屏幕一列 1080 個像素點,一共 1920 列,如下圖所示:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
X 軸就是 LCD 顯示器的橫軸,Y 軸就是顯示器的豎軸。圖中的小方塊就是像素點,一共有 1920
1080=2073600 個像素點。左上角的 A 點是第一個像素點,右下角的 C 點就是最后一個像素點。2K 就是 25601440 個像素點,4K 是 38402160 個像素點。很明顯,在 LCD 尺寸不變的情況下,分辨率越高越清晰。同樣的,分辨率不變的情況下,LCD 尺寸越小越清晰。比如常用的 24 寸顯示器基本都是 1080P 的,而
現(xiàn)在使用的 5 寸的手機基本也是 1080P 的,但是手機顯示細膩程度就要比 24 寸的顯示器要好很多!
由此可見,LCD 顯示器的分辨率是一個很重要的參數(shù),但是并不是分辨率越高的 LCD 就越好。衡量一款 LCD 的好壞,分辨率只是其中的一個參數(shù),還有色彩還原程度、色彩偏離、亮度、可視角度、屏幕刷新率等其他參數(shù)。

2)像素格式

??一個像素點就相當(dāng)于一個 RGB 小燈,通過控制 R、G、B 這三種顏色的亮度就可以顯示出各種各樣的色彩。那該如何控制 R、G、B 這三種顏色的顯示亮度呢?一般一個像素點的 R、G、B 這三部分分別使用 8bit 的數(shù)據(jù),那么一個像素點就是 8bit*3=24bit,也就是說一個像素點 3 個字節(jié),這種像素格式稱為 RGB888。如果再加入 8bit 的 Alpha(透明)通道的話一個像素點就是 32bit,也就是 4 個字節(jié),這種像素格式稱為 ARGB8888。如果學(xué)習(xí)過 STM32 的話應(yīng)該還聽過 RGB565 這種像素格式,在本小節(jié)中使用 ARGB8888 這種像素格式,一個像素占用 4 個字節(jié)的內(nèi)存,這四個字節(jié)每個位的分配如下圖所示:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
??一個像素點是 4 個字節(jié),其中 bit31 ~ bit24 是 Alpha 通道,bit23 ~ bit16 是 RED 通道,bit15 ~ bit14 是 GREEN 通道,bit7 ~ bit0 是 BLUE 通道。所以紅色對應(yīng)的值就是 0X00FF0000,藍色對應(yīng)的值就是 0X000000FF,綠色對應(yīng)的值為 0X0000FF00。通過調(diào)節(jié) R、G、B的比例可以產(chǎn)生其它的顏色,比如0X00FFFF00就是黃色,0X00000000就是黑色,0X00FFFFFF 就是白色。例如電腦的畫圖工具也可以通過這種方式設(shè)置顏色。

3)LCD 屏幕接口

??LCD 屏幕或者說顯示器有很多種接口,比如在顯示器上常見的 VGA、HDMI、DP 等等,但是 STM32MP1 開發(fā)板不支持這些接口。STM32MP1 支持 RGB 接口的 LCD,RGBLCD 接口的信號線如下表所示:

信號線 描述
R[7:0] 8 根紅色數(shù)據(jù)線
G[7:0] 8 根綠色數(shù)據(jù)線
B[7:0] 8 根藍色數(shù)據(jù)線
DE 數(shù)據(jù)使能線
VSYNC 垂直同步信號線
HSYNC 水平同步信號線
PCLK 像素時鐘信號

R[7:0]、G[7:0] 和 B[7:0] 這 24 根是數(shù)據(jù)線,DE、VSYNC、HSYNC 和 PCLK 這四根是控制信號線。RGB LCD 一般有兩種驅(qū)動模式:DE 模式和 HV 模式,這兩個模式的區(qū)別是 DE 模式需要用到 DE 信號線,而 HV 模式不需要用到 DE 信號線,在 DE 模式下是可以不需要 HSYNC 信號線的,即使不接 HSYNC 信號線 LCD 也可以正常工作。

正點原子一共有四款 RGB LCD 屏幕,兩款 4.3 寸和兩款 7 寸屏,每一款有兩種分辨率。筆者在買開發(fā)板時沒有購買 LCD 屏,所以按照教程中,對 7 寸,1024*600這個屏幕進行驅(qū)動開發(fā)。(猜測都是通用接口,應(yīng)該差別不大)
原理圖:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
J1 就是對外接口,是一個 40PIN 的 FPC 座(0.5mm 間距),通過 FPC 線,可以連接到 STM32MP1 開發(fā)板上。該接口十分完善,采用 RGB888 格式,并支持 DE&HV 模式,還支持觸摸屏和背光控制。右側(cè)的幾個電阻,并不是都焊接的,用戶可以根據(jù)自己實際需要而選擇
是否焊接(正點原子出廠屏幕不能做修改!)。默認情況,R1和R6焊接,設(shè)置 LCD_LR 和 LCD_UD,控制 LCD 的掃描方向,是從左到右,從上到下(橫屏看)。而 LCD_R7/G7/B7 則用來設(shè)置 LCD 的 ID,由于 RGB LCD 沒有讀寫寄存器,也就沒有所謂的 ID,這里通過在模塊上面,控制R7/G7/B7 的上/下拉,來自定義 LCD 模塊的 ID,幫助 SOC 判斷當(dāng)前 LCD 面板的分辨率和相關(guān)參數(shù),以提高程序兼容性。這幾個位的設(shè)置關(guān)系如下表所示:

M2 LCD_B7 M1 LCD_G7 M0 LCD_R7 LCD ID 說明
0 0 0 4342 ATK-4342 RGBLCD 模塊,分辨率:480*272
0 0 1 7084 ATK-7084 RGBLCD 模塊,分辨率:800*480
0 1 0 7016 ATK-7016 RGBLCD 模塊,分辨率:1024*600
1 0 0 4384 ATK-4384 RGBLCD 模塊,分辨率:800*480
X X X NC 暫時未用到

ATK-7016 模塊,就設(shè)置 M2:M0=010 即可。這樣在程序里面讀取 LCD_R7/G7/B7,得到 M0:M2 的值,從而判斷 RGBLCD 模塊的型號,并執(zhí)行不同的配置,即可實現(xiàn)不同 LCD 模塊的兼容。

4)LCD 時間參數(shù)

??如果將 LCD 顯示一幀圖像的過程想象成繪畫,那么在顯示的過程中就是用一根“筆”在不同的像素點畫上不同的顏色。這根筆按照從左至右、從上到下的順序掃描每個像素點,并且在像素畫上對應(yīng)的顏色,當(dāng)畫到最后一個像素點的時候一幅圖像就繪制好了。假如一個 LCD 的分辨率為 1024*600,那么其掃描如下圖所示:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
??一幀圖像也是由一行一行組成的。HSYNC 是水平同步信號,也叫做行同步信號,當(dāng)產(chǎn)生此信號就表示開始顯示新的一行了,所以此信號都是在圖的最左邊。VSYNC 信號是垂直同步信號,也叫做幀同步信號,當(dāng)產(chǎn)生此信號就表示開始顯示新的一幀圖像了,所以此信號在圖的左上角。
??在圖中還有一圈“黑邊”,真正有效的顯示區(qū)域是中間的白色部分。這一圈“黑邊”要從顯示器的“祖先” CRT 顯示器開始說起,CRT 顯示器就是以前很常見的那種大屁股顯示器,CRT 顯示器屁股后面是個電子槍,這個電子槍就是上面說的“畫筆”,電子槍打出的電子撞擊到屏幕上的熒光物質(zhì)使其發(fā)光。只要控制電子槍從左到右掃完一行(也就是掃描一行),然后從上到下掃描完所有行,這樣一幀圖像就顯示出來了。也就是說,顯示一幀圖像電子槍是按照‘Z’形在運動,當(dāng)掃描速度很快的時候看起來就是一幅完成的畫面了。當(dāng)顯示完一行以后會發(fā)出 HSYNC 信號,此時電子槍就會關(guān)閉,然后迅速的移動到屏幕的左邊,當(dāng) HSYNC 信號結(jié)束以后就可以顯示新的一行數(shù)據(jù)了,電子槍就會重新打開。在 HSYNC 信號結(jié)束到電子槍重新打開之間會插入一段延時,這段延時就是圖中的 HBP。當(dāng)顯示完一行以后就會關(guān)閉電子槍等待 HSYNC 信號產(chǎn)生,關(guān)閉電子槍到 HSYNC 信號產(chǎn)生之間會插入一段延時,這段延時就是圖中的 HFP 信號。同理,當(dāng)顯示完一幀圖像以后電子槍也會關(guān)閉,然后等到 VSYNC 信號產(chǎn)生,期間也會加入一段延時,這段延時就是圖中的 VFP。VSYNC 信號產(chǎn)生,電子槍移動到左上角,當(dāng) VSYNC 信號結(jié)束以后電子槍重新打開,中間也會加入一段延時,這段延時就是圖 中的 VBP。
??HBP、HFP、VBP 和 VFP 就是導(dǎo)致圖中黑邊的原因,RGB LCD 屏幕內(nèi)部有一個 IC,發(fā)送一行或者一幀數(shù)據(jù)給 IC,IC 是需要反應(yīng)時間的。通過這段反應(yīng)時間可以讓 IC 識別到一行數(shù)據(jù)掃描完了,要換行了,或者一幀圖像掃描完了,要開始下一幀圖像顯示了。因此,在 LCD 屏幕中繼續(xù)存在 HBP、HFP、VPB 和 VFP 這四個參數(shù)的主要目的是為了鎖定有效的像素數(shù)據(jù)。這四個時間是 LCD 重要的時間參數(shù),后面編寫 LCD 驅(qū)動的時候要用到,至于這四個時間參數(shù)具體值是多少,需要去查看所使用的 LCD 數(shù)據(jù)手冊。

5)RGB LCD 屏幕時序

ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
HSYNC:行同步信號,當(dāng)此信號有效就表示開始顯示新的一行數(shù)據(jù),查閱所使用的LCD 數(shù)據(jù)手冊可以知道此信號是低電平有效還是高電平有效,假設(shè)此時是低電平有效。
HSPW:有些地方也叫做 thp,是 HSYNC 信號寬度,也就是 HSYNC 信號持續(xù)時間。HSYNC信號不是一個脈沖,而是需要持續(xù)一段時間才是有效的,單位為 CLK。
HBP:有些地方叫做 thb,術(shù)語叫做行同步信號后肩,單位是 CLK。
HOZVAL:有些地方叫做 thd,顯示一行數(shù)據(jù)所需的時間,假如屏幕分辨率為 1024*600,那么 HOZVAL 就是 1024,單位為 CLK。
HFP:有些地方叫做 thf,術(shù)語叫做行同步信號前肩,單位是 CLK。
當(dāng) HSYNC 信號發(fā)出以后,需要等待 HSPW+HBP 個 CLK 時間才會接收到真正有效的像素數(shù)據(jù)。當(dāng)顯示完一行數(shù)據(jù)以后需要等待 HFP 個 CLK 時間才能發(fā)出下一個 HSYNC 信號,所以顯示一行所需要的時間就是:HSPW + HBP + HOZVAL + HFP。

一幀圖像就是由很多個行組成的, RGB LCD 的幀顯示時序如下圖所示:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
VSYNC:幀同步信號,當(dāng)此信號有效的話就表示開始顯示新的一幀數(shù)據(jù),查閱所使用的 LCD 數(shù)據(jù)手冊可以知道此信號是低電平有效還是高電平有效,假設(shè)此時是低電平有效。
VSPW:些地方也叫做 tvp,是 VSYNC 信號寬度,也就是 VSYNC 信號持續(xù)時間,單位為 1 行的時間。
VBP:有些地方叫做 tvb,術(shù)語叫做幀同步信號后肩,單位為 1 行的時間。
LINE:有些地方叫做 tvd,顯示一幀有效數(shù)據(jù)所需的時間,假如屏幕分辨率為 1024*600,那么 LINE 就是 600 行的時間。
VFP:有些地方叫做 tvf,術(shù)語叫做幀同步信號前肩,單位為 1 行的時間。

顯示一幀所需要的時間就是: VSPW+VBP+LINE+VFP 個行時間
最終的計算公式:T = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)
因此在配置一款 RGB LCD 的時候需要知道這幾個參數(shù):HOZVAL(屏幕有效寬度)、LINE(屏幕有效高度)、HBP、HSPW、HFP、VSPW、VBP 和 VFP。ALIENTEK 三款 RGB LCD屏幕的參數(shù)如下表所示:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux

6)像素時鐘

像素時鐘就是 RGB LCD 的時鐘信號,以 ATK7016 這款屏幕為例,顯示一幀圖像所需要的時鐘數(shù)就是:
= (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)
= (3 + 20 + 600 + 12) * (20 + 140 + 1024 + 160)
= 635 * 1344
= 853440
顯示一幀圖像需要853440個時鐘數(shù),那么顯示60幀就是: 853440 * 60 = 51206400 ≈ 51.2M,所以像素時鐘就是 51.2MHz。

7)顯存

如果采用 ARGB8888 格式,一個像素需要 4 個字節(jié)的內(nèi)存來存放像素數(shù)據(jù),那么 1024600 分辨率就需要 1024600*4 = 2457600B ≈ 2.4MB 內(nèi)存。但是 RGB LCD 內(nèi)部是沒有內(nèi)存的,所以就需要在開發(fā)板上的 DDR3 中分出一段內(nèi)存作為 RGB LCD 屏幕的顯存,如果要在屏幕上顯示圖像直接操作這部分顯存即可。

2.LTDC 接口

??LTDC 是 STM32MP1 自帶的液晶屏幕接口,用于連接 RGB LCD 接口的屏幕,LTDC 接口特性如下:

① 24 位 RGB 并行像素輸出,每像素 8 位(RGB888)
② 2 個帶有專用 FIFO 的顯示層(FIFO 深度 64x64 位)
③ 查色表(CLUT),每個圖層最高 256 種顏色(256x24)位
④ 可針對不同顯示面板編程時序
⑤ 每層有多達 8 個輸入顏色格式可供選擇,分別為:ARGB8888、RGB888、RGB565、ARGB1555、ARGB4444、L8、AL44、AL88

LTDC接口功能框架:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
從圖中可以看出 LTDC 的信號可以分為兩類:4 個控制信號(LCD_CLK 像素時鐘、LCD_HSYNC 水平同步、LCD_VSYNC 垂直同步、LCD_DE 數(shù)據(jù)有效)和 3 個 RGB 數(shù)據(jù)信號(8bit x 3)。

二、DRM 驅(qū)動框架

1.DRM 簡介

??在 Linux 系統(tǒng)中,主流的顯示框架有兩種:DRM(Direct Rendering Module)框架和 FB(FrameBuffer)框架。FB 框架不能處理基于 3D 加速 GPU 顯卡,而 DRM 可以統(tǒng)一管理 GPU顯示,所以 DRM 相對于 FB 更能適應(yīng)新的顯示硬件。比如 DRM 支持多層合成、支持 VSYNC、支持 DMA-BUF、支持 fence 機制等等。
??下圖就是一個 DRM 驅(qū)動框架,包括兩部分:DRM core 和 DRM driver。DRM core 提供了一個基本的 DRM 框架,DRM driver 就可以注冊進 DRM 框架,同時為用戶空間提供一組 ioctl。libdrm 對底層接口(DRM driver 提供的 ioctl)進行封裝,向上層提供統(tǒng)一的 API 接口。DRM driver 包含了 GEM 模塊和 KMS 模塊,這兩模塊也分為好幾個小模塊。
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
圖形執(zhí)行管理器(GEM):全稱 Graphics Execution Manager,這是一個內(nèi)存管理器,主要負責(zé)內(nèi)存的分配和釋放,可以調(diào)用 GPU。
DUMB:這是一個 dumb 緩沖區(qū),主要負責(zé)一些簡單的 buffer 顯示,可以通過 CPU 直接渲染 dumb,GPU 不會使用 dumb。
內(nèi)核顯示模式設(shè)置(KMS):全稱 Kernel Mode Setting,主要負責(zé)顯示的控制,包括屏幕分辨率、屏幕刷新率和顏色深度等等。
CRTC:就是指顯示控制器,在 DRM 里有多個顯存,就可以通過操作 CRTC 來控制要顯示那個顯存。
Encoder:負責(zé)從 CRTC 里輸出的 timing 時序轉(zhuǎn)換成外部設(shè)備所需要的信號的模塊,同時也負責(zé)控制 LCD 的顯示。
Connector:連接物理顯示設(shè)備的連接器,比如 DSI、 HDMI 等等。
Plane:負責(zé)獲取顯存,再輸出到 CRTC 里,說明 CRTC 必須要有一個 Plane。
幀緩沖(FB):能夠顯示圖層的 buffer。

GEM 和 KMS 通過以下結(jié)構(gòu)來與顯示器對接:
ips_dev_panel_t參數(shù)設(shè)置,STM32MP157,驅(qū)動開發(fā),stm32,linux
藍色框表示 KMS 里的模塊。plane 是連接 crtc 和 framebuffer 的紐帶;encoder 是連接 crtc 和 connector 的紐帶。GEM 是負責(zé)和物理的 buffer 打交道。plane 把獲取到顯存輸出到 crtc 里,crtc 通過 connector 接口輸出到顯示器。

2.ST 官方的 DRM 驅(qū)動框架介紹

??在 Linux 系統(tǒng)中,DRM 驅(qū)動的核心主要就是一個 drm_driver 結(jié)構(gòu)體,驅(qū)動程序要初始化drm_driver 結(jié)構(gòu)體,然后調(diào)用 drm_dev_init 函數(shù),將其注冊到 DRM core。
?? 在設(shè)備樹文件 stm32mp151.dtsi 中,有一個 ltdc 節(jié)點:

ltdc: display-controller@5a001000 {
	compatible = "st,stm32-ltdc";
	reg = <0x5a001000 0x400>;
	interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
				 <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&rcc LTDC_PX>;
	clock-names = "lcd";
	resets = <&rcc LTDC_R>;
	status = "disabled";
};

?? 這個文件中的 ltdc 節(jié)點信息是所有使用 STM32MP1 芯片的板子所共有的,且不是完整的 ltdc 節(jié)點信息。其中 ltdc 節(jié)點的 compatible 屬性值為“st,stm32-ltdc”,在 Linux源碼中搜索這個字符串就可以找到 STM32MP1 的 DRM 驅(qū)動文件,這個文件為 “drivers/gpu/drm/stm/drv.c”文件:

static const struct of_device_id drv_dt_ids[] = {
	{.compatible = "st,stm32-ltdc"},
	{},
};
MODULE_DEVICE_TABLE(of, drv_dt_ids);

static struct platform_driver stm_drm_platform_driver = {
		.probe = stm_drm_platform_probe,
		.remove = stm_drm_platform_remove,
		.driver = {
			.name = "stm32-display",
			.of_match_table = drv_dt_ids,
			.pm = &drv_pm_ops,
		},
};

?? 可以看出,這是一個標準的 platform 驅(qū)動,當(dāng)驅(qū)動和設(shè)備匹配以后 stm_drm_platform_probe 函數(shù)就會執(zhí)行。和其他設(shè)備驅(qū)動一樣,DRM 也分為 DRM 設(shè)備和 DRM 驅(qū)動,drm_device 結(jié)構(gòu)體為 DRM 設(shè)備,drm_driver 為 DRM 驅(qū)動。

drm_device 結(jié)構(gòu)體

drm_device 結(jié)構(gòu)體定義在 include/drm/drm_device.h 文件里,部分內(nèi)容如下:

struct drm_device {
	struct list_head legacy_dev_list;
	int if_version;
	struct kref ref;
......
	u32 max_vblank_count;
	struct list_head vblank_event_list;
	spinlock_t event_lock;
	struct drm_agp_head *agp;
	struct pci_dev *pdev;
	unsigned int num_crtcs;
	struct drm_mode_config mode_config;
	struct mutex object_name_lock;
	struct idr object_name_idr;
	struct drm_vma_offset_manager *vma_offset_manager;
	struct drm_vram_mm *vram_mm;
	enum switch_power_state switch_power_state;
	struct drm_fb_helper *fb_helper;
};

?? 在編寫 DRM 驅(qū)動時需要自行申請 drm_device 內(nèi)存并且使用初始化,可以直接通過 drm_dev_alloc 函數(shù)來完成,此函數(shù)會先調(diào)用 kzalloc 為 drm_device 分配內(nèi)存,然后調(diào)用 drm_dev_init 初始化 drm_device。
原型

struct drm_device *drm_dev_alloc(struct drm_driver *driver, struct device *parent)

參數(shù)
driver:drm_driver 結(jié)構(gòu)體指針,也就是 DRM 設(shè)備對應(yīng)的 DRM 驅(qū)動
parent:父設(shè)備
返回值
返回分配成功的新 DRM 設(shè)備
ERR_PTR:drm_device 申請失敗

drm_device 分配成功以后還需要使用 drm_dev_register 函數(shù)向內(nèi)核注冊:
原型

int drm_dev_register(struct drm_device *dev, unsigned long flags)

參數(shù)
dev:需要注冊到內(nèi)核的 drm_device
flags:傳遞給驅(qū)動 .load 函數(shù)的標志
返回值
0:成功
負數(shù):失敗

drm_driver 結(jié)構(gòu)體

?? Linux 內(nèi)核為 DRM 驅(qū)動提供一個叫做 drm_driver 的結(jié)構(gòu)體,drm_driver 結(jié)構(gòu)體包含了 DRM驅(qū)動的完整屬性和操作集合,因此每一個 DRM 驅(qū)動都必須有一個 drm_driver。drm_driver 結(jié)構(gòu)體定義在 include/drm/drm_drv.h 文件里:

struct drm_driver {
	int (*load) (struct drm_device *, unsigned long flags);
	int (*open) (struct drm_device *, struct drm_file *);
......

	int (*dumb_create)(struct drm_file *file_priv,
					   struct drm_device *dev,
					   struct drm_mode_create_dumb *args);
	int (*dumb_map_offset)(struct drm_file *file_priv,
						   struct drm_device *dev, uint32_t handle,
						   uint64_t *offset);
	int (*dumb_destroy)(struct drm_file *file_priv,
						struct drm_device *dev,
						uint32_t handle);
	const struct vm_operations_struct *gem_vm_ops;
	
	int major; /* 驅(qū)動主設(shè)備號 */
	int minor; /* 驅(qū)動次設(shè)備號 */
	int patchlevel; /* 驅(qū)動補丁等級 */
	char *name; /* 驅(qū)動名字 */
	char *desc; /* 驅(qū)動描述 */
	char *date; /* 驅(qū)動日期 */
	u32 driver_features; /* 驅(qū)動特性 */
	const struct drm_ioctl_desc *ioctls;
	int num_ioctls;
	const struct file_operations *fops;
	
	struct list_head legacy_dev_list;
	int (*firstopen) (struct drm_device *);
	void (*preclose) (struct drm_device *, struct drm_file *file_priv);
	int (*dma_ioctl) (struct drm_device *dev, void *data,
					  struct drm_file *file_priv);
	int (*dma_quiescent) (struct drm_device *);
	int (*context_dtor) (struct drm_device *dev, int context);
	int dev_priv_size;
};

成員變量比較多,重點是driver_features、fops 和 dumb_create。
①dumb_create 是一個回調(diào)函數(shù), 用于創(chuàng)建 gem 對象,并分配物理 buffer。
②driver_features 用來描述驅(qū)動特性,枚舉類型 drm_driver_feature 定義了可以選擇的驅(qū)動特性:

DRIVER_GEM:驅(qū)動使用 GEM 內(nèi)存管理,此特性必須選中!
DRIVER_MODESET:驅(qū)動支持模式設(shè)置接口(KMS)。
DRIVER_RENDER:驅(qū)動支持專用渲染節(jié)點。
DRIVER_ATOMIC:驅(qū)動提供完整的原子操作,以供用戶空間 API 函數(shù)操作。
DRIVER_SYNCOBJ:驅(qū)動支持 SYNCOBJ, 用于命令提交的顯式同步。
DRIVER_SYNCOBJ_TIMELINE:驅(qū)動支持 SYNCOBJ 時間線。
DRIVER_USE_AGP:驅(qū)動程序使用 AGP 接口, DRM 核心將管理 AGP 資源。
DRIVER_LEGACY:表明這是一個使用影子附著的舊驅(qū)動程序,不使用。
DRIVER_PCI_DMA:驅(qū)動支持 PCI DMA。
DRIVER_SG:驅(qū)動可以提供 scatter/gather DMA 功能
DRIVER_HAVE_DMA:驅(qū)動支持 DMA。
DRIVER_HAVE_IRQ:驅(qū)動支持 IRQ,舊驅(qū)動使用。
DRIVER_KMS_LEGACY_CONTEXT:僅供 nouveau 使用!

③fops 就是一個簡單的字符設(shè)備接口結(jié)構(gòu)體

當(dāng)設(shè)備和驅(qū)動匹配成功以后 stm_drm_platform_probe 函數(shù)就會執(zhí)行, 函數(shù)內(nèi)容如下:

static int stm_drm_platform_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct drm_device *ddev;
	int ret;
	
	DRM_DEBUG("%s\n", __func__);
	
	dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
	
	ddev = drm_dev_alloc(&drv_driver, dev);
	if (IS_ERR(ddev))
		return PTR_ERR(ddev);
	
	ret = drv_load(ddev);
	if (ret)
		goto err_put;
	
	ret = drm_dev_register(ddev, 0);
	if (ret)
		goto err_put;
	
	drm_fbdev_generic_setup(ddev, 16);
	
	return 0;
	
err_put:
	drm_dev_put(ddev);
	return ret;
}

①drm_dev_alloc 函數(shù),此函數(shù)主要完成以下功能:

a.給 drm_device 分配內(nèi)存。
b.通過 drm_dev_init 函數(shù)初始化 drm_device3

drm_dev_alloc 會通過調(diào)用 drm_dev_init 函數(shù)將 drm_driver 和 drm_device 聯(lián)系起來,drm_device 結(jié)構(gòu)體里面有個 drvier 指針成員變量,此成員變量指向 DRM 設(shè)備對應(yīng)的 DRM 驅(qū)動的。因此,drm_dev_init 函數(shù)會通過將 drm_device 下的 driver 成員變量指向 drm_driver 來實現(xiàn)兩者相連。
②drv_load 這個函數(shù)就是初始化 KMS
③注冊 drm_device 對象進 DRM core

drv_load 函數(shù):

#define STM_MAX_FB_WIDTH 2048
#define STM_MAX_FB_HEIGHT 2048

static const struct drm_mode_config_funcs drv_mode_config_funcs = {
	.fb_create = drm_gem_fb_create,
	.atomic_check = drm_atomic_helper_check,
	.atomic_commit = drm_atomic_helper_commit,
};
......
static int drv_load(struct drm_device *ddev)
{
	struct platform_device *pdev = to_platform_device(ddev->dev);
	struct ltdc_device *ldev;
	int ret;

	DRM_DEBUG("%s\n", __func__);
	
	ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL);
	if (!ldev)
		return -ENOMEM;

	ddev->dev_private = (void *)ldev;

	drm_mode_config_init(ddev);

	/*
	* set max width and height as default value.
	* this value would be used to check framebuffer size limitation
	* at drm_mode_addfb().
	*/
	ddev->mode_config.min_width = 0;
	ddev->mode_config.min_height = 0;
	ddev->mode_config.max_width = STM_MAX_FB_WIDTH;
	ddev->mode_config.max_height = STM_MAX_FB_HEIGHT;
	ddev->mode_config.funcs = &drv_mode_config_funcs;
	
	ret = ltdc_load(ddev);
	if (ret)
		goto err;
	
	drm_mode_config_reset(ddev);
	drm_kms_helper_poll_init(ddev);
	
	platform_set_drvdata(pdev, ddev);
	
	return 0;
err:
	drm_mode_config_cleanup(ddev);
	return ret;
}

①前兩行設(shè)置DRM 驅(qū)動 X 軸(寬度)最大支持 2048 個像素,設(shè)置 DRM 驅(qū)動 Y 軸(寬度)最大支持 2048 個像素,可以看出驅(qū)動里面設(shè)置的最大分辨率支持2048 * 2048。但是根據(jù)STM32MP157 手冊所描述,最大支持1366 * 768分辨率的屏幕。
② mode_config.funcs 設(shè)置 framebuffer 的回調(diào)函數(shù)結(jié)構(gòu)體。
③ ltdc_load 引入 drm_panel 結(jié)構(gòu)體,此結(jié)構(gòu)體作用是提供一堆控制回調(diào)函數(shù),比如屏幕參數(shù)回調(diào)函數(shù),背光控制函數(shù)等等。ltdc_load函數(shù)是負責(zé)初始化ltdc接口(同時connector 和 encoder 一起初始化)。在 connector 初始化時,就會調(diào)用 drm_panel 結(jié)構(gòu)體里的獲取屏幕參數(shù)函數(shù)(所以只需要提供一個屏的驅(qū)動就能正常顯示了)。通常 encoder 和 connector 是放在同一個驅(qū)動初始化的,目的是為了方便驅(qū)動程序設(shè)計。

要完成整個 DRM 驅(qū)動的正常初始化,前面的 GEM 和 KMS 這些模塊已經(jīng)由 ST 官方提供,開發(fā)人員只需提供一個 drm_panel 對象即可。打開“include/drm/drm_panel.h”文件:

struct drm_panel {
	struct drm_device *drm; /* drm_device 對象 */
	struct drm_connector *connector; /* connector 對象 */
	struct device *dev; /* 設(shè)備節(jié)點 dev */
	const struct drm_panel_funcs *funcs; /* 回調(diào)函數(shù)的結(jié)構(gòu)體 */
	struct list_head list;
};

這里就是 drm_panel 的結(jié)構(gòu)體定義,開發(fā)者按照要求實現(xiàn)一個 drm_panel 對象后,傳入驅(qū)動框架即可完成驅(qū)動開發(fā)。

3.RGB LCD 驅(qū)動分析(屏的驅(qū)動)

??drm_panel 結(jié)構(gòu)體是基類,panel_simple 在 drm_panel 基礎(chǔ)上增加了一些成員變量,相當(dāng)于繼承類。LCD 驅(qū)動文件為 drivers/gpu/drm/panel/panelsimple.c,其中有如下內(nèi)容:

99  struct panel_simple {
100 	struct drm_panel base;
101 	bool prepared;
102 	bool enabled;
103 	bool no_hpd;
104
105 	const struct panel_desc *desc;
106
107 	struct backlight_device *backlight;
108 	struct regulator *supply;
109 	struct i2c_adapter *ddc;
110
111 	struct gpio_desc *enable_gpio;
112
113 	struct drm_display_mode override_mode;
114 };

panel_simple 結(jié)構(gòu)體用來管理 RGB LCD 設(shè)備。
第 100行,base成員變量,為 drm_panel 結(jié)構(gòu)體類型??梢钥闯?panel_simple 就是在 drm_panel 的基礎(chǔ)上發(fā)展而來的,在 DRM 驅(qū)動注冊的時候就會回調(diào) base->funcs。
第 105 行,desc 屬性就是 RGB 屏參數(shù)結(jié)構(gòu)體。
第 107 行,屏的背光結(jié)構(gòu)體。

與設(shè)備樹匹配

LCD 驅(qū)動的 platform_driver:

3491 static struct platform_driver panel_simple_platform_driver = {
3492 	.driver = {
3493 		.name = "panel-simple",
3494 		.of_match_table = platform_of_match,
3495 },
3496 	.probe = panel_simple_platform_probe,
3497 	.remove = panel_simple_platform_remove,
3498 	.shutdown = panel_simple_platform_shutdown,
3499 };

這是一個標準的 platform 驅(qū)動框架, 第 3494 行就是匹配表。platform_of_match 內(nèi)容如下所示(有省略):

3133 static const struct of_device_id platform_of_match[] = {
3134 	{
3135 		.compatible = "ampire,am-480272h3tmqw-t01h",
3136 		.data = &ampire_am_480272h3tmqw_t01h,
3137 	}, {
3138 		.compatible = "ampire,am800480r3tmqwa1h",
3139 		.data = &ampire_am800480r3tmqwa1h,
3140 	}, {}
3141 };

platform_of_match 里面有大量的匹配項,分別針對不同的屏幕,比如:第 3135 行就是一個匹配項,compatible 內(nèi)容為“ampire,am-480272h3tmqw-t01h”。
第 3136 行,在 platform 框架里有個 data 成員變量,這個是一個 void 類型的指針,這里指向 ampire_am_480272h3tmqw_t01h,內(nèi)容如下所示:

515 static const struct drm_display_mode ampire_am_480272h3tmqw_t01h_mode = {
516 	.clock = 9000, /* LCD 像素時鐘,單位 KHz */
517 	.hdisplay = 480, /* LCD X 軸像素個數(shù) */
518 	.hsync_start = 480 + 2, /* LCD X 軸+hbp 的像素個數(shù) */
519 	.hsync_end = 480 + 2 + 41, /* LCD X 軸+hbp+hspw 的像素個數(shù) */
520 	.htotal = 480 + 2 + 41 + 2, /* LCD X 軸+hbp+hspw+hfp 的像素個數(shù) */
521 	.vdisplay = 272, /* LCD Y 軸像素個數(shù) */
522 	.vsync_start = 272 + 2, /* LCD Y 軸+vbp 的像素個數(shù) */
523 	.vsync_end = 272 + 2 + 10, /* LCD Y 軸+vbp+vspw 的像素個數(shù) */
524 	.vtotal = 272 + 2 + 10 + 2, /* LCD Y 軸+vbp+vspw+vfp 的像素個數(shù) */
525 	.vrefresh = 60, /* LCD 的刷新頻率為 60HZ */
526 	.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
527 };
528
529 static const struct panel_desc ampire_am_480272h3tmqw_t01h = {
530 	.modes = &ampire_am_480272h3tmqw_t01h_mode,
531 	.num_modes = 1,
532 	.bpc = 8,
533 	.size = {
534 		.width = 105,
535 		.height = 67,
536 	},
537 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
538 };

第 516~525 行,drm_display_mode 結(jié)構(gòu)體就是用來設(shè)置屏幕參數(shù)。
第 529 行,定義一個 panel_desc 結(jié)構(gòu)體對象。
第 530 行,modes 變量設(shè)置為 ampire_am_480272h3tmqw_t01h_mode。
第 531 行,設(shè)置 modes 的數(shù)量。
第 532 行,設(shè)置屏幕為 8bit。
第 533~536 行,設(shè)置屏幕實際顯示區(qū)域的物理寬度,單位為毫米,此屏幕尺寸為 105mm x 67mm。
第 537 行,bus_format 屬性設(shè)置總線模式, include/uapi/linux/media-bus-format.h 里面定義了所有可選的總線類型:

1  #define MEDIA_BUS_FMT_FIXED 0x0001
2
3  /* RGB - next is 0x101d */
4  #define MEDIA_BUS_FMT_RGB444_1X12 0x1016
5  #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
6  #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
7  #define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE 0x1003
8  #define MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE 0x1004
9  #define MEDIA_BUS_FMT_RGB565_1X16 0x1017
10 #define MEDIA_BUS_FMT_BGR565_2X8_BE 0x1005
11 #define MEDIA_BUS_FMT_BGR565_2X8_LE 0x1006
12 #define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007
13 #define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008
14 #define MEDIA_BUS_FMT_RGB666_1X18 0x1009
15 #define MEDIA_BUS_FMT_RBG888_1X24 0x100e
16 #define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015
17 #define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010
18 #define MEDIA_BUS_FMT_BGR888_1X24 0x1013
19 #define MEDIA_BUS_FMT_BGR888_3X8 0x101b
20 #define MEDIA_BUS_FMT_GBR888_1X24 0x1014
21 #define MEDIA_BUS_FMT_RGB888_1X24 0x100a
22 #define MEDIA_BUS_FMT_RGB888_2X12_BE 0x100b
23 #define MEDIA_BUS_FMT_RGB888_2X12_LE 0x100c
24 #define MEDIA_BUS_FMT_RGB888_3X8 0x101c
25 #define MEDIA_BUS_FMT_RGB888_1X7X4_SPWG 0x1011
26 #define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA 0x1012
27 #define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d
......
121 /* HSV - next is 0x6002 */
122 #define MEDIA_BUS_FMT_AHSV8888_1X32 0x6001

可以看出,Linux 內(nèi)核支持很多種不同的總線格式,比如 RGB、YUV、Bayer 等。以 MEDIA_BUS_FMT_RGB888_1X24 為例,這個總線格式的含義如下:
①從“RGB888”可以看出,這是一個 RGB888 格式的。
②后面的“1X24”表示一個像素點使用 24bit,如果是 2X8 就表示一個像素點使用 2 個 8bit 表示。
③有的右邊還會有“BE”或“LE”,BE 表示最高位先傳輸,LE 表示最低位先傳輸。假設(shè)設(shè)備樹里有個設(shè)備節(jié)點的 compatible 屬性為“ampire,am-480272h3tmqw-t01h”,那么就會和驅(qū)動匹配成功,然后運行 panel_simple_platform_probe 函數(shù),此函數(shù)的內(nèi)容如下所示:

3470 static int panel_simple_platform_probe(struct platform_device *pdev)
3471 {
3472 const struct of_device_id *id;
3473
3474 id = of_match_node(platform_of_match, pdev->dev.of_node);
3475 if (!id)
3476 return -ENODEV;
3477
3478 return panel_simple_probe(&pdev->dev, id->data);
3479 }

第 3474 行,使用 of_match_node 函數(shù)查找匹配的設(shè)備 ID。
第 3478 行,當(dāng)?shù)玫狡ヅ涞脑O(shè)備 ID(of_device_id)以后就可以通過提取 data 成員變量得到屏幕參數(shù)信息,比如此處 id->data 就是 ampire_am_480272h3tmqw_t01h。最后調(diào)用 panel_simple_probe 函數(shù)將其注冊到內(nèi)核,panel_simple_probe 函數(shù)也定義在 drivers/gpu/drm/panel/panel-simple.c 文件中,函數(shù)內(nèi)容如下所示:

414 static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
415 {
416 	struct device_node *backlight, *ddc;
417 	struct panel_simple *panel;
418 	struct display_timing dt;
419 	int err;
420
421 	panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
422 	if (!panel)
423 		return -ENOMEM;
424
425 	panel->enabled = false;
426 	panel->prepared = false;
427 	panel->desc = desc;
428
......
444 	backlight = of_parse_phandle(dev->of_node, "backlight", 0);
445 	if (backlight) {
446 		panel->backlight = of_find_backlight_by_node(backlight);
447 		of_node_put(backlight);
448
449 		if (!panel->backlight)
450 			return -EPROBE_DEFER;
451 	}
452
......
467 	drm_panel_init(&panel->base);
468 	panel->base.dev = dev;
469 	panel->base.funcs = &panel_simple_funcs;
470
471 	err = drm_panel_add(&panel->base);
472 	if (err < 0)
473 		goto free_ddc;
474
475 	dev_set_drvdata(dev, panel);
476
477 	return 0;
478
479 free_ddc:
480 	if (panel->ddc)
481 		put_device(&panel->ddc->dev);
482 free_backlight:
483 	if (panel->backlight)
484 		put_device(&panel->backlight->dev);
485 	return err;
486 }

第 427 行,設(shè)置屏幕參數(shù)。
第 444 行,從設(shè)備樹里獲取背光節(jié)點,所以我們的設(shè)備樹要提供“backlight”屬性。
第 467 行,用 drm_panel_init 函數(shù)初始化屏幕。
第 469 行,設(shè)置 panel_simple 的回調(diào)函數(shù),為 DRM 驅(qū)動注冊的時候提供屏的參數(shù)。
第 471 行,把屏幕注冊到內(nèi)核。

三、總結(jié)

LCD 屏的驅(qū)動分析結(jié)束,總結(jié)一下添加自己的屏要做哪些操作:
①在根節(jié)點下提供一個 LCD 設(shè)備樹,包含背光的節(jié)點和引用 ltdc 節(jié)點。
②在 panel-simple.c 文件里的 platform_of_match 結(jié)構(gòu)體里添加一組設(shè)備 ID,此設(shè)備 ID 對應(yīng)所使用的屏幕,重點是屏幕參數(shù) panel_desc 結(jié)構(gòu)體。文章來源地址http://www.zghlxwxcb.cn/news/detail-719193.html

到了這里,關(guān)于STM32MP157驅(qū)動開發(fā)——Linux LCD驅(qū)動(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(POLL 機制)

    STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(POLL 機制)

    使用休眠-喚醒的方式等待某個事件發(fā)生時,有一個缺點:等待的時間可能很久。我們可以加上一個超時時間,這時就可以使用 poll 機制。 ① APP 不知道驅(qū)動程序中是否有數(shù)據(jù),可以先調(diào)用 poll 函數(shù)查詢一下,poll 函數(shù)可以傳入超時時間; ② APP 進入內(nèi)核態(tài), 調(diào)用到驅(qū)動程序的

    2024年02月15日
    瀏覽(19)
  • STM32MP157驅(qū)動開發(fā)——LED驅(qū)動(原始架構(gòu))

    STM32MP157驅(qū)動開發(fā)——LED驅(qū)動(原始架構(gòu))

    LED 的驅(qū)動方式,常見的有四種。 ① 使用引腳輸出 3.3V 點亮 LED,輸出 0V 熄滅 LED。 ② 使用引腳拉低到 0V 點亮 LED,輸出 3.3V 熄滅 LED。 ③ 使用引腳輸出 1.2V 點亮 LED,輸出 0V 熄滅 LED。 ④ 使用引腳輸出 0V 點亮 LED,輸出 1.2V 熄滅 LED。 有的芯片為了省電等原因,其引腳驅(qū)動能力

    2024年02月03日
    瀏覽(28)
  • STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(定時器)

    STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(定時器)

    定時器涉及函數(shù)參考內(nèi)核源碼:includelinuxtimer.h 給定時器的各個參數(shù)賦值: 設(shè)置定時器 :主要是初始化 timer_list 結(jié)構(gòu)體,設(shè)置其中的函數(shù)、參數(shù)。 a) 向內(nèi)核添加定時器。timer-expires 表示超時時間。 b) 當(dāng)超時時間到達,內(nèi)核就會調(diào)用這個函數(shù):timer-function(timer-data)。 修改定時

    2024年02月15日
    瀏覽(23)
  • STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(線程化處理)

    STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(線程化處理)

    工作隊列是在內(nèi)核的線程的上下文中執(zhí)行的 工作隊列中有多個 work,前一個 work 沒處理完會影響后面的 work。解決方法有如下2種: 比如自己創(chuàng)建一個內(nèi)核線程,不跟別的 work 在一塊。例如存儲設(shè)備比如 SD/TF采用的就是單獨一個線程。 使用線程化的中斷處理。中斷的處理仍然

    2024年02月16日
    瀏覽(23)
  • STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(休眠與喚醒)

    STM32MP157驅(qū)動開發(fā)——按鍵驅(qū)動(休眠與喚醒)

    當(dāng)應(yīng)用程序必須等待某個事件發(fā)生,比如必須等待按鍵被按下時,可以使用“休眠-喚醒”機制: ① APP 調(diào)用 read 等函數(shù)試圖讀取數(shù)據(jù),比如讀取按鍵; ② APP 進入內(nèi)核態(tài),也就是調(diào)用驅(qū)動中的對應(yīng)函數(shù),發(fā)現(xiàn)有數(shù)據(jù)則復(fù)制到用戶空間并馬上返回; ③ 如果 APP 在內(nèi)核態(tài),也就

    2024年02月16日
    瀏覽(52)
  • STM32MP157驅(qū)動開發(fā)——USB設(shè)備驅(qū)動

    STM32MP157驅(qū)動開發(fā)——USB設(shè)備驅(qū)動

    參考文章:【正點原子】I.MX6U嵌入式Linux驅(qū)動開發(fā)——Linux USB驅(qū)動 ??由于 USB 協(xié)議太過龐大和復(fù)雜,所以本節(jié)只對 STM32MP157 自帶的 USB 驅(qū)動進行使能和測試。詳細的 USB 接口和協(xié)議的介紹,可以參考原子哥的資料《USB2.0 協(xié)議中文版.pdf》和《USB3.0 協(xié)議中文版.pdf》。 ??USB 全

    2023年04月14日
    瀏覽(42)
  • 驅(qū)動開發(fā),stm32mp157a開發(fā)板的led燈控制實驗

    驅(qū)動開發(fā),stm32mp157a開發(fā)板的led燈控制實驗

    ????????編寫LED燈的驅(qū)動,在應(yīng)用程序中編寫控制LED燈亮滅的代碼邏輯實現(xiàn)LED燈功能的控制; LED1-PE10 LED1亮滅: RCC寄存器[4]-1 0X50000A28 GPIOE_MODER[21:20]-01 (輸出) 0X50006000 GPIOE_ODR[10]-1(輸出高電平) 0(輸出低電平)0X50006014 LED2-PF10 LED2亮滅: RCC寄存器[5]-1 0X50000A28 GPIOE_MODER[21:20]

    2024年02月09日
    瀏覽(24)
  • STM32 Linux開發(fā)板丨STM32MP157開發(fā)板資料手冊+實戰(zhàn)教程+視頻教程

    STM32 Linux開發(fā)板丨STM32MP157開發(fā)板資料手冊+實戰(zhàn)教程+視頻教程

    iTOP-STM32MP157開發(fā)板是基于意法半導(dǎo)體STARM雙Cortex-A7核加單Cortex-M4核的一款多核異構(gòu)處理器。Cortex-A7內(nèi)核提供對開源操作系統(tǒng)Linux的支持,借助Linux系統(tǒng)龐大而豐富的軟件組件處理復(fù)雜應(yīng)用。M4內(nèi)核上運行對于實時性要求嚴格的應(yīng)用。 開發(fā)板既有A7核,又有M4核,從學(xué)習(xí)者角度來看

    2024年02月12日
    瀏覽(16)
  • STM32MP157開發(fā)板Linux+Qt項目實戰(zhàn):智慧家庭

    STM32MP157開發(fā)板Linux+Qt項目實戰(zhàn):智慧家庭

    stm32mp157開發(fā)板FS-MP1A是華清遠見自主研發(fā)的一款高品質(zhì)、高性價比的Linux+單片機二合一的嵌入式教學(xué)級開發(fā)板。開發(fā)板搭載ST的STM32MP157高性能微處理器,集成2個Cortex-A7核和1個Cortex-M4 核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實時操作系統(tǒng)。開發(fā)板搭配仿真

    2024年02月09日
    瀏覽(21)
  • LED驅(qū)動(原始架構(gòu))——STM32MP157

    LED驅(qū)動(原始架構(gòu))——STM32MP157

    LED 的驅(qū)動方式,常見的有四種。 ① 使用引腳輸出 3.3V 點亮 LED,輸出 0V 熄滅 LED。 ② 使用引腳拉低到 0V 點亮 LED,輸出 3.3V 熄滅 LED。 ③ 使用引腳輸出 1.2V 點亮 LED,輸出 0V 熄滅 LED。 ④ 使用引腳輸出 0V 點亮 LED,輸出 1.2V 熄滅 LED。 有的芯片為了省電等原因,其引腳驅(qū)動能力

    2024年02月16日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包