LCD驅動(FrameBuffer)例項開發講解
一、開發環境
- 主 機:VMWare--Fedora 9
- 開發板:Mini2440--64MB Nand, Kernel:2.6.30.4
- 編譯器:arm-linux-gcc-4.3.2
二、背景知識
1. LCD工作的硬體需求: 要使一塊LCD正常的顯示文字或影象,不僅需要LCD驅動器,而且還需要相應的LCD控制器。在通常情況下,生產廠商把LCD驅動器會以COF/COG的 形式與LCD玻璃基板製作在一起,而LCD控制器則是由外部的電路來實現,現在很多的MCU內部都集成了LCD控制器,如S3C2410/2440等。通 過LCD控制器就可以產生LCD驅動器所需要的控制訊號來控制STN/TFT屏了。 2. S3C2440內部LCD控制器結構圖:
VSYNC/VFRAME/STV:垂直同步訊號(TFT)/幀同步訊號(STN)/SEC TFT訊號; |
A:顯示指標從矩形左上角的第一行第一個點開始,一個點一個點的在LCD上顯示,在上面的時序圖上用時間線表示就為VCLK,我們稱之為畫素時鐘訊號; |
VBPD(vertical back porch):表示在一幀影象開始時,垂直同步訊號以後的無效的行數,對應驅動中的upper_margin; |
LCDCON1:17 - 8位CLKVAL |
三、幀緩衝(FrameBuffer)裝置驅動結構: 幀 緩衝裝置為標準的字元型裝置,在Linux中主裝置號29,定義在/include/linux/major.h中的FB_MAJOR,次裝置號定義幀緩 衝的個數,最大允許有32個FrameBuffer,定義在/include/linux/fb.h中的FB_MAX,對應於檔案系統下/dev /fb%d裝置檔案。
1. 幀緩衝裝置驅動在Linux子系統中的結構如下:
我 們從上面這幅圖看,幀緩衝裝置在Linux中也可以看做是一個完整的子系統,大體由fbmem.c和xxxfb.c組成。向上給應用程式提供完善的裝置文 件操作介面(即對FrameBuffer裝置進行read、write、ioctl等操作),介面在Linux提供的fbmem.c檔案中實現;向下提供 了硬體操作的介面,只是這些介面Linux並沒有提供實現,因為這要根據具體的LCD控制器硬體進行設定,所以這就是我們要做的事情了(即xxxfb.c 部分的實現)。
2. 幀緩衝相關的重要資料結構:
從 幀緩衝裝置驅動程式結構看,該驅動主要跟fb_info結構體有關,該結構體記錄了幀緩衝裝置的全部資訊,包括裝置的設定引數、狀態以及對底層硬體操作的 函式指標。在Linux中,每一個幀緩衝裝置都必須對應一個fb_info,fb_info在/linux/fb.h中的定義如下:(只列出重要的一些)
fb_ops結構體是對底層硬體操作的函式指標,該結構體中定義了對硬體的操作有:(這裡只列出了常用的操作)
struct fb_ops { |
3. 幀緩衝裝置作為平臺裝置:
在S3C2440中,LCD控制器被整合在晶片的內部作為一個相對獨立的單元,所以Linux把它看做是一個平臺裝置,故在核心程式碼/arch/arm/plat-s3c24xx/devs.c中定義有LCD相關的平臺裝置及資源,程式碼如下:
除此之外,Linux還在/arch/arm/mach-s3c2410/include/mach/fb.h中為LCD平臺裝置定義了一個 s3c2410fb_mach_info結構體,該結構體主要是記錄LCD的硬體引數資訊(比如該結構體的s3c2410fb_display成員結構中 就用於記錄LCD的螢幕尺寸、螢幕資訊、可變的螢幕引數、LCD配置暫存器等),這樣在寫驅動的時候就直接使用這個結構體。下面,我們來看一下核心是如果
使用這個結構體的。在/arch/arm/mach-s3c2440/mach-smdk2440.c中定義有:
/* LCD driver info */
//LCD硬體的配置資訊,注意這裡我使用的LCD是NEC 3.5寸TFT屏,這些引數要根據具體的LCD屏進行設定
//這個地方的設定是配置LCD暫存器5,這些巨集定義在regs-lcd.h中,計算後二進位制為:111111111111,然後對照資料手冊上LCDCON5的各位來看,注意是從右邊開始
//以下一些引數在上面的時序圖分析中講到過,各引數的值請跟據具體的LCD屏資料手冊結合上面時序分析來設定 |
注意:可能有很多朋友不知道上面紅色部分的引數是做什麼的,其值又是怎麼設定的?其實它是跟你的開發板LCD控制器密切相關的,看了下面兩幅圖相信就大概知道他們是幹什麼用的:
上面第一幅圖是開發板原理圖的LCD控制器部分,第二幅圖是S3c2440資料手冊中IO埠C和IO埠D控制器部分。原理圖中使用了 GPC8-15和GPD0-15來用做LCD控制器VD0-VD23的資料埠,又分別使用GPC0、GPC1埠用做LCD控制器的LEND和VCLK 訊號,對於GPC2-7則是用做STN屏或者三星專業TFT屏的相關訊號。然而,S3C2440的各個IO口並不是單一的功能,都是複用埠,要使用他們 首先要對他們進行配置。所以上面紅色部分的引數就是把GPC和GPD的部分埠配置成LCD控制功能模式。
從以上講述的內容來看,要使LCD控制器支援其他的LCD屏,重要的是根據LCD的資料手冊修改以上這些引數的值。下面,我們再看一下在驅動中是如果引用 到s3c2410fb_mach_info結構體的(注意上面講的是在核心中如何使用的)。在mach-smdk2440.c中有:
s3c24xx_fb_set_platdata定義在plat-s3c24xx/devs.c中:
這裡再講一個小知識:不知大家有沒有留意,在平臺裝置驅動中,platform_data可以儲存各自平臺裝置例項的資料,但這些資料的型別都是不同的, 為什麼都可以儲存?這就要看看platform_data的定義,定義在/linux/device.h中,void *platform_data是一個void型別的指標,在Linux中void可儲存任何資料型別。
四、幀緩衝(FrameBuffer)裝置驅動例項程式碼:
①、建立驅動檔案:my2440_lcd.c,依就是驅動程式的最基本結構:FrameBuffer驅動的初始化和解除安裝部分及其他,如下:
#include <linux/kernel.h>
#include <linux/slab.h>
u32 pseudo_pal[16]; |