Linux核心升級LCD驅動的更換(開發板)

來源:互聯網
上載者:User
文章目錄
  • 一. 概述

Linux核心升級LCD驅動的更換(開發板)

關鍵字

 

 

核心升級 ,更換驅動 ,LCD

 

 

 

 

本文給出了將一個已有的LCD驅動添加進一個新的linux核心中的方法

 


一. 概述

本文搜集整理了Linux系統編譯時間的主要配置選項(make config)的詳細說明,供Linux裁剪特別是裝置驅動和模組功能增刪時使用參考。需要注意的是,每個版本linux版本的config各選項意義,命名等都可能有所差異。

1、 修改核心根目錄config檔案

文本方式開啟config檔案,將LCD的幾個編譯開關添加進Frame buffer hardware drivers這一項目下,之後在make menuconfig中就可以看到。

#

# Frame buffer hardware drivers

#

CONFIG_FB_SIDSA=y

CONFIG_FB_TCM=y

# CONFIG_FB_SDRAM is not set

CONFIG_TFT_AT91=y

CONFIG_FB_SIDSA_DEFAULT_BPP=16

# CONFIG_FB_SIDSA_DEBUG is not set

在控制台顯示驅動項目中將linux logo顯示的編譯開關開啟,logo顯示16色或其他均可。

#

# Console display driver support

#

CONFIG_LOGO=y

# CONFIG_LOGO_LINUX_MONO is not set

CONFIG_LOGO_LINUX_VGA16=y

添加好上述config選項後,使用make menuconfig開啟該config檔案,即可看到這些選項,一一進行確認:

LCD的配置項位於drivers->graphices support下 分別將frame buffer和logo的選項選中,才能使用邏輯屏和logo圖片。Bootup logo中可選黑白圖,16色圖或256色圖其中一種均可。

Frame buffer的裝置驅動選中SIDSA控制器,目前邏輯屏比較小為QVGA,資料來源選為TCM等選項。開發板具有內建大約1M多的SRAM,當邏輯屏比較大時,應選SDRAM.

2、 添加屏驅動源碼到工程目錄

Linux的屏驅動一般位於drivers/video 目錄下,目前AT91SAM926開發板使用的LCD驅動是sidsafb.c和sidsafb.h,at91sam9261_lcdc.h三個檔案,在標準的linux2.6.25上是沒有的,從開發板源碼包中複製過來放到該目錄下(還要進行一些代碼修改,後面的步驟會講到)。

3、修改邏輯屏驅動模組的Makefile檔案

開啟drivers/video目錄下的Makefile檔案,在其中添加sidsafb.o檔案的編譯選項,依賴於編譯開關CONFIG_FB_SIDSA,也可使用檔案比較的方式和開發板同名makefile比較,將藍色方框部分複製到你的makefile

4、修改模組的Kconfig檔案

開啟drivers/video目錄下的Kconfig檔案,添加FB_SIDSA, FB_TCM等幾個編譯開關的配置,也可使用檔案比較子將開發板源碼包下的同名Kconfig檔案比較,將藍色方框部分的幾個編譯開關選項複製添加到你的drivers/video/Kconfig中,如:

5、原始碼的修改

移植驅動時有兩種工作方式,一種是所有驅動同時一併移植,這樣做的好處是各驅動模組公用檔案如寄存器表,相關宏的標頭檔放置的比較合理,移植完後清晰,缺點是交叉錯誤多,調試工作量大,一兩個人無法完成。另一種是單個模組串列一一移植,好處是調試比較好調,缺點是移植完代碼可能比較亂。綜合一下,個人認為驅動整合移植時先移植所有公用的標頭檔,公用的功能函數和宏,不添加具體模組,編譯出一個基本版本,在此版本基礎上在分頭移植各個模組比較合理。

單驅動模組移植時,總結下來原始碼的修改主要包括幾個部分:

a) 驅動的依賴關係整理清楚,若本驅動還依賴其他驅動,則還需要先移植添加其他驅動模組

b) 理清所添加驅動對外部變數,函數,宏的參考關聯性,去除編譯錯誤。

c) 修改虛擬位址->物理地址的映射函數為當前平台的映射函數,使寄存器map表映射正確。

d) 修改驅動的註冊和載入部分。

具體改動如下:(此部分改動已有改好的版本在FTP,列舉只是為了說明問題和給出方法)

模組依賴關係和編譯錯誤的整理

由於本開發板的屏是RGB屏,所以實際驅動是由AT91所帶的LCDC控制器來完成,因此屏的驅動主要工作是配置LCDC和管理Frame buffer兩部分。LCDC依賴於另外兩個模組:IO和CLOCK(即代碼中的PIO和PMC模組),IO用來控制LCDC的電源,CLOCK用來給出LCDC時序的時基。所以先要添加PIO和PMC部分的代碼.為了不至於要掛載整個PIO和PMC模組,開發板的BSP將一些簡單的功能獨立出來作為函數供其他模組調用。

從開發板源碼中找到PIO的寄存器定義相關宏,拷貝出來添加到sidsafb.c頭部或sidsafb.h,不嫌麻煩的話也可另建標頭檔,PIO的寄存器主要是這些宏:

#define PIO_PER (0x0000) /**< PIO Enable Register */

#define PIO_PDR (0x0004) /**< PIO Disable Register */

#define PIO_PSR (0x0008) /**< PIO Status Register */

#define PIO_OER (0x0010) /**< Output Enable Register */

#define PIO_ODR (0x0014) /**< Output Disable Registerr */

#define PIO_OSR (0x0018) /**< Output Status Register */

#define PIO_IFER (0x0020) /**< Input Filter Enable Register */

………

同樣添加PMC模組的寄存器宏,主要是這些:

#define PMC_SCER (0x0000) /**< System Clock Enable Register */

#define PMC_SCDR (0x0004) /**< System Clock Disable Register */

#define PMC_SCSR (0x0008) /**< System Clock Status Register */

#define PMC_PCER (0x0010) /**< Peripheral Clock Enable Register */

#define PMC_PCDR (0x0014) /**< Peripheral Clock Disable Register */

#define PMC_PCSR (0x0018) /**< Peripheral Clock Status Register */

#define PMC_MOR (0x0020) /**< Main Oscillator Register */

……..

添加各模組寄存器讀寫的宏

#define readreg_pmc(offset) readl(AT91C_VA_BASE_PMC + offset)

#define writereg_pmc(value, offset) writel(value, (AT91C_VA_BASE_PMC + offset))

有了這些宏,對IO和CLOCK的操作函數基本就可以加進來編譯,屏驅動中引用到的操作函數主要是:

at91_gpio_set_level

at91_gpio_periph_enable

at91_gpio_configure

at91_device_pio_setup

at91_enable_periph_clock

at91_disable_system_clock

at91_enable_system_clock

at91_lcdc_clock_enable

at91_lcdc_power_up

虛擬位址-物理地址轉換函式的修改

去除上述產生的所有編譯錯誤,將其他一些零碎的未定義的對象添加進來,基本就可以編譯通過了。但還不能運行,一般地講,兩個linux版本的虛擬位址到物理地址的轉換關係是不一致的,而驅動對寄存器的訪問都是通過虛擬位址進行,因此要使驅動能在新的linux核心上運行,必須使用該linux的虛擬位址-物理地址轉換公式,擷取到正確的寄存器虛擬位址。

Linux系統的裝置記憶體映射都映射到系統空間(0xc00000000-0xFFFFFFFF)的固定映射區之內,映射方式是線性、連續的,因此裝置的物理地址和虛擬位址只相差一個常數位移量,當實體記憶體小於896M時,高端映射區未用,固定映射區的首地址一般就是緊接在vmalloc區的後面,不同的版本不同的晶片體系中vmalloc區的尾地址定義有所不同,在vmalloc.h中定義:

Linux 2.6.15-AT91定義為

#define VMALLOC_END (0xFF000000 - 0x00200000)

Linux 2.6.25-AT91定義為

#define VMALLOC_END (AT91_VIRT_BASE & PGDIR_MASK)

在Linux2.6.15-AT91體系中,物理地址到虛擬位址的轉換相差的常數依賴於VMALLOC_END(/include/asm-arm/arch-at91sam9261/hardware.h):

#define AT91C_IO_PHYS_BASE 0xFFFFF000

#define AT91C_IO_VIRT_BASE VMALLOC_END

/* Convert a physical IO address to virtual IO address */

#define AT91_IO_P2V(x) ((x) - AT91C_IO_PHYS_BASE + AT91C_IO_VIRT_BASE)

即物理地址轉換為虛擬位址時,虛擬位址=物理地址-(0xFFFFF000- VMALLOC_END)

在Linux2.6.25-AT91體系中,IO物理地址到物理地址轉換公式為:

#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)

但其物理基地址AT91_IO_PHYS_BASE和虛擬基地址AT91_IO_VIRT_BASE和Linux2.6.15版本均不同,(由於對其的長度不同,因此IO物理基地址可能不同版本都不同,但具體到任意一個寄存器的物理地址,最終換算出來基地址+OFFSET都是一樣的),因此寄存器的訪問,必須採用當前體系的基地址,當前體系的OFFSET,當前體系的映射方式AT91_IO_P2V,才能得到當前體系下對應的正確的虛擬位址。

代碼中將舊的映射函數AT91_IO_P2V屏蔽不用,採用新版本同名的AT91_IO_P2V映射函數,並將所有使用到的寄存器基地址,位移量修改為當前體系的值,此處只用到LCDC,PIO,PMC三片寄存器,將其基地址改為目前的版本定義值:

#define AT91C_VA_BASE_PIOA AT91_IO_P2V(AT91C_BASE_PIOA)

#define AT91C_VA_BASE_PMC AT91_IO_P2V(AT91C_BASE_PMC)

改為

#define AT91C_VA_BASE_PIOA AT91_IO_P2V(AT91_PIOA)

#define AT91C_VA_BASE_PMC AT91_IO_P2V(AT91_PMC)

至此,在當前體系下寄存器的虛擬位址就可以正確地得到了,使用虛擬位址去配置寄存器,才不會產生分頁錯,data abort之類地記憶體錯誤,
裝置註冊和初始化的修改

裝置的註冊和初始化一般位於arch/arm/對應體系目錄下,使用AT91晶片時,主要是at91sam9261.c,at91sam9261_devices.c和board-sam9261ek.c三個代碼檔案和一些.h檔案,第一個at91sam9261.c負責總的調用和定義,第二個at91sam9261_devices.c負責主要片內控制器的定義,初始化,其中LCDC就包含在這裡面。第三個board-sam9261ek.c負責片外板上裝置的定義和初始化,同一款晶片不同的板子不同的硬體在這裡區別。

在at91sam9261_devices.c中找到LCD的定義和初始化,標準Linux2.6.25使用的是CONFIG_FB_ATMEL,將其改為當前開發板對應的代碼,主要是RGB屏時序的定義,FB的位置地區,和普通裝置device不一樣,LCDC屬於平台標配裝置,其類型為platform_device,需要定義對DMA的使用等,將其裝置名稱改為sidsafb.c檔案中定義的"sidsa-lcdc",這樣啟動時才能找到"sidsa-lcdc"並將其掛載。這樣,LCD驅動就移植完畢,編譯通過,燒寫後啟動即可亮屏,如果想修改logo圖片,到drivers/video/logo目錄下修改圖片,或直接修改其對應的數組。

LCDC的裝置是:

static struct platform_device at91_lcdc_device = {

.name = "sidsa-lcdc",

.id = 0,

.num_resources = ARRAY_SIZE(lcdc_resources),

.resource = lcdc_resources,

.dev = {

.dma_mask = &lcdc_dmamask,

.coherent_dma_mask = DMA_BIT_MASK(32),

.platform_data = &lcdc_data,

},

};

調試過程中可在關鍵的函數中使用printk添加一些列印語句,如:

init/main.c中的start_kernel函數是核心啟動的第一個函數,在這裡進行各項初始化,可在其中加一些列印觀察情況;

at91sam9260.c和at91sam9261_devices.c中進行晶片裝置的載入,可加一些列印,觀察哪些裝置載入成功,哪些載入失敗。

觀察所加的裝置"sidsa-lcdc”是否被正常掛載,可在裝置的初始化函數sidsafb_init中添加列印,觀察是否進入其中初始化,且註冊裝置driver_register時返回的值是否正確等。

編譯時間,要使用AT91-SAM926的config檔案,由於每個板子的記憶體基地址和長度不一樣,因此要在config中定義,也可以在代碼中定義:(include/asm-arm/arch-at91/hardware.h)

#define AT91_SDRAM_BASE 0x20000000

屏基本上可以亮了,但還有個bug,就是顯示完logo後之後一會兒就滅掉了,這是因為Linux2.6.25版本上的預設BSP時鐘使用方式和現有開發板不一致,LCD定義的CLOCK有衝突,將如下CLK定義宏暫時登出即可正常顯示:

//#define AT91_PMC_HCK1(1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */

//lingzj remove

#define AT91_PMC_HCK1 (1 << 1) /* AHB Clock (LCD) [AT91SAM9261 only] */

—— 完 ——

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.