0引言
嵌入式系統開發已經進入32位時代,在當前數字信息技術和網絡技術高速發展的后PC時代,嵌入式系統已經廣泛地滲透到科學研究、工程設計、軍事技術等各個方面。
嵌入式系統通常由硬件和軟件兩個大部分組成。其硬件部分的核心部件就是各類嵌入式微處理器,并配置存儲器、I/O設備、通信模塊等必要的外設。目前市場上主流銷售的32位嵌入式處理器有MOTOROLA、MIPS、ARM等系列,其中ARM以其體積小、成本低、功耗低、性能高等特點成為嵌入式系統設計的首選。
軟件部分一般由嵌入式操作系統和應用軟件組成。嵌入式操作系統是一種支持嵌入式應用的操作系統軟件,它負責全部軟硬件資源的分配和調度、控制協調等活動。從20世紀80年代末開始,陸續出現了很多典型的嵌入式操作系統,如Linux、μC/OS、WindowsCE等,其中使用最廣泛、最受歡迎的是Linux,這是由于其源代碼公開、可移植性好等優點。
1嵌入式視頻處理平臺和Linux系統移植
本文開發的嵌入式視頻處理平臺在達芬奇(Da-Vinci)數字媒體技術平臺TMS320DM*6上進行的。此平臺是以嵌入式處理器ARM為中心,由存儲器、I/O設備、通信模塊以及電源等必要的輔助接口組成。它的工作流程如圖1所示。攝像頭將視頻信號傳輸進來后,再通過視頻采集卡轉換成數字信號然后送人TMS320DM*6,經過處理后通過視頻輸出接口在LCD(液晶顯示器)上顯示,在此過程中可以由USB口上所接的操縱桿進行控制,以及與存儲設備進行存取操作。
此嵌入式視頻處理平臺主要應用于視頻和圖像的處理,如進行視頻跟蹤、圖像的編解碼等。
本文詳細闡述如何在TMS320DM*6平臺上進行Linux系統移植,形成了一個完整的Linux移植體系,為后續在此平臺上的開發搭建了一個良好的平臺,其移植流程如圖2所示。
2交叉編譯環境的建立
開發一個嵌入式Linux系統,首先要建立良好的交叉編譯環境。所謂交叉編譯環境,是由編譯器、連接器和解釋器組成的綜合開發環境。交叉編譯是嵌入式系統開發過程中的一項重要技術,它的主要特征是某機器中執行的程序代碼不是在本機編譯生成,而是由另一臺機器編譯生成。一般把前者稱為目標機 (tar-get),后者稱為宿主機(host)。在宿主機上編譯好適合目標機運行的代碼后,通過宿主機到目標機的調試通道將代碼下載到目標機,然后由運行于宿主機的調試軟件控制代碼在目標機上運行調試,其交叉編譯開發模型如圖3所示。
建立ARM的交叉編譯環境主要用到的開發工具有:binutils、gcc、glibc。其中binutils是二進制文件的處理工具,它主要包含了一些輔助開發工具,例如obj-dump顯示反匯編碼、nm列出符號表、readelf顯示elf文件信息及段信息等。這些工具在嵌入式開發初期,尤其是移植調試操作系統時非常有用;gcc是用來編譯內核代碼的工具,可以編譯匯編語言和C語言的程序,生成ARM的代碼;glibc是一個提供系統調用和基本函數的C語言庫,所有動態鏈接的程序都要用到它。將這些開發工具包下載到宿主機上進行編譯、安裝,即可創建ARM的交叉編譯環境。
3BootLoader的設計
BootLoader即引導加載程序,是在操作系統內核運行之前運行的一段程序。它建立起操作系統運行的環境,包括初始化硬件、建立存儲空間映射和傳遞給操作系統一些基本的配置參數等。因此,Bootloader是非常重要的組成部分,它獨立于操作系統,必須由用戶自己設計,而且其實現高度依賴于硬件。在系統存儲的空間分配結構中BootLoader、內核啟動參數、內核映像和根文件系統映像的關系如圖4所示。
BootLoader的作用是正確地調用內核來執行。系統開機后,執行的第1條指令是從Flash的0x00地址開始的,BootLoader 程序就是放在此。由于它是直接操作硬件且依據硬件環境不同而代碼不同,所以適合用匯編語言寫,以達到短小精悍執行效率高的目的;內核從Flash復制到 SDRAM時,采用C語言實現,能實現較復雜的功能,因此BootLoader的設計分為兩個階段。用匯編語言實現的放在第1階段,主要完成硬件初始化,設置SDRAM,然后把Boot-Loader從Flash復制到SDRAM的起始地址,即2M處,最后內存重映射,Flash地址從0x00- 0xlff映射成0x1000000-0x11fff,SDRAM地址0x200000-0xllfff映射成0x00-0xfff,至此控制權交給了用 C語言實現的loaderkernel()函數,就進入了第2階段。第2階段是用C語言實現的,它主要完成內核從Flash到SDRAM的復制,然后控制權交給Kernel,流程如圖5所示。這樣設計代碼會具有很好的可讀性和可移植性。
本系統BootLoader的第1階段設計包括:
a)關閉看門狗程序,屏蔽所有中斷;
b)設置處理器時鐘和工作頻率,TMS320-DM*6中ARM9的工作頻率為300 MHz;
c)初始化外部寄存器;
d)初始化堆棧指針;
e)復制BootLoader的第2階段到RAM空間中,使用一條跳轉語句跳轉到第2階段的C程序如入口處。
第2階段用C語言編寫,具體步驟如下:
a)設置通用I/O口參數;
b)初始化內存映射和內存管理單元;
c)初始化mtd設備;
d)復制Flash中的Kernel映像和根文件系統映像到RAM空間中;
e)跳轉到內核的第1條指令處,跳轉時需要滿足這些條件:R0=0,R1=機器類型ID,R2=啟動參數,同時禁止中斷(IRQ和FIQ),CPU設置為保護模式,關閉MMU和數據Cache。
這樣,本系統的BootLoader就設計完成了,下面就可以進行Linux內核移植。
4 Linux內核移植
Linux內核主要由5個子系統構成:
a)進程調度(Process Scheduler):負責控制進程對CPU的使用。
b)內存管理(Memory Manager):標準Linux的內存管理支持虛擬內存,進程代碼、數據和堆棧的總量可以超過實際內存的大小。
c)虛擬文件系統(Virtual File System):隱藏了不同硬件的具體細節,為所有設備提供統一的接口。
d)網絡接口(Network Interface):負責支持標準的網絡通信協議和各種網絡硬件設備。
e)進程間通信(Inter-Process Communica-tion):支持進程間各種通信機制。
根據嵌入式系統的特點,要使嵌入式Linux系統具備一定的功能且保持小型化,應包括啟動加載程序、內核、初始化進程,以及硬件驅動程序、文件系統、必要的應用程序等。
不管是哪一款嵌入式處理器,完成移植工作就要修改所有與體系結構有關的代碼,主要指內核人口、處理器初始化、I/O口映射等。具體操作如下:
(1)修改配置文件
a)打開根目錄下的Makefile文件,指定目標平臺ARCH=arm;指定交叉編譯器CROSS_COMPILE=arm-linux-gcc;
b)打開/arch/arm目錄下的Makefile文件,添加內核起始運行地址,即image.ram應下載的位置,該位置一般在RAM區起始地址偏移0x8000處;
c)打開/arch/arm/boot目錄下的Makefile文件,指定Bootloader的壓縮內核解壓后數據的輸出地址。
(2)編譯Linux內核
在完成上述工作后,開始編譯Linux內核,生成目標代碼。在內核源代碼目錄下依次鍵入以下命令:
a)make clean:清除以前構造內核時生成的所有目標文件、模塊和臨時文件;
b)make dep:搜索Linux輸出與源代碼之間的依賴關系,并以此生成依賴文件;
c)make menuconfig:調用菜單式的配置內核界面,內核配置的選項非常多,根據自己系統的具體情況選擇合理的配置,在內核配置時選上相應型號的硬件;
d)make zImage:編譯內核,生成壓縮的Linux內核目標代碼zImage文件;
e)make modules:編譯塊模塊驅動程序,凡是在menuconfig中被選為的都會在這條命令運行時被編譯。
至此,已編譯好能在本系統上運行的Linux內核。
(3)創建JFFS2文件系統
文件系統是Linux系統的重要組成部分。本系統使用mkfs.jffs2工具創建JFFS2文件系統。首先建立/bin、/sbin等目錄,然后復制命令工具到/bin文件夾,復制系統控制程序到/sbin目錄下,復制應用程序運行時所需的庫到/lib,庫文件可從PC機的交叉編譯工具安裝目錄下復制。最后鍵人命令:mkfs.jffs2-o jffs2root.jffs2,生成JFFS2根文件系統。
上述工作完成后,將BootLoader、Linux內核、文件系統燒寫到TMS320DM*6的Flash中,這樣就能運行Linux系統了。
5設備驅動程序開發
5.1 Linux設備驅動程序開發步驟
Linux系統設備分為字符設備、塊設備和網絡設備3種。其設備驅動的開發主要包括:
a)在驅動程序源文件中定義file_opera-tions結構,并編寫出設備需要的各個操作函數,對于設備不需要的操作函數用NULL初始化,這些操作函數將被注冊到內核中。
b)定義一個初始化函數,在Linux初始化時會調用此函數。此函數包含:初始化驅動程序要用到的硬件寄存器;初始化與設備相關的參數;注冊設備;注冊設備使用的中斷和函數;其他一些初始化工作。
c)對于驅動程序的使用,可以進行靜態編譯,也可以進行動態編譯。靜態編譯是指將設備驅動程序添加到內核中,動態編譯是指將設備驅動程序編譯成驅動模塊。
本嵌入式系統主要用于視頻處理,涉及到的外設主要是顯示設備和輸入設備。這里采用的顯示設備是LCD,而輸入設備是通過USB接口與系統相連的。
5.2 LCD顯示驅動程序開發
LCD的設備驅動程序屬于字符設備的驅動,應按照字符設備的規則編寫。在Linux下進行LCD顯示用Framebuffer技術,這是提取圖形的設備,是用戶進入圖形界面很好的接口。Linux內核根據硬件描述抽象出Framebuffer設備,供用戶態的進程直接進行寫屏??梢詫?Framebuffer看成是顯示內存的一個映像,將其映射到進程地址空間之后,就可以直接進行讀寫操作,寫操作立即反應在屏幕上。 Framebuffer的設備文件一般存放在/dev這個目錄下,對此設備文件進行操作即可實現圖像的顯示。
LCD顯示驅動程序主要包括:
a)LCD驅動的文件結構:包括打開設備文件、設備文件其它操作、關閉設備文件等;
b)LCD的打開:LCD設備以讀寫的方式打開;
c)LCD設備的硬件初始化:包括注冊LCD設備、卸載LCD設備等;
d)LCD相關結構的設置:以獲取顯存起始地址、分別率、色深等;
e)映射內存區的操作:包括初始化顯存清零等,將攝像頭采集到的圖像數據讀至顯存處,以顯示圖像;
f)LCD控制輸出:包括得到命令、畫水平線、畫垂直線、畫圓等;
g)LCD的關閉。
將上面的內容用程序實現,進行動態編譯。通過后,將LCD驅動模塊進行移植加載,一個完整的LCD驅動就開發完畢了。
5.3 USB驅動程序開發
與LCD設備不同,USB既不屬于字符設備,也不屬于塊設備,而是一個新的設備類別,設計框架和流程如下:首先,提供一個“.o”的驅動模塊文件,且在一開始就加載運行。USB驅動就會根據其類型向系統注冊。注冊成功后,系統會反饋一個主設備號,這個主設備號就是其唯一標識。USB驅動就是根據主設備號創建一個放置在/dev目錄下的設備文件。要訪問此硬件,可用open、read和write等命令訪問相應的設備文件,驅動就會接收到相應的 read或write函數,根據模塊中相對應的函數進行操作。驅動流程見圖6。
USB驅動的具體設計過程如下:
a)USB驅動的注冊。USB驅動程序在注冊時會發送一個命令給函數register_chrdev,通常在驅動程序的初始化函數中。當USB 設備插入時,為了使linux-hotplug(Linux中USB等設備熱插拔支持)系統自動裝載驅動程序,需創建 MODULE_DEVICE_TABLE,在此過程中需將USB的主設備號傳遞給相應的函數。
b)USB設備的打開。打開設備是通過調用file_operations結構中的函數open()來完成的。其主要完成的任務是:檢查設備相關錯誤,如果是第一次打開,則初始化硬件設備;識別次設備號;使用計數增1。
c)USB設備的釋放。釋放設備是通過調用file_operations結構中的函數release()來完成的。它的作用正好與open()相反,通常要完成這樣的工作:使用計數減1,如果使用計算為0,則關閉設備。
d)USB設備的控制信息與數據讀寫。USB設備驅動程序可以通過文件操作結構中的函數向應用程序提供對硬件進行控制的接口,同時讀寫操作也要通過此函數來完成。
e)USB驅動的注銷。當從系統卸載驅動程序時,需要注銷USB設備,這樣必須編寫一個注銷函數unregister_chrdev。
6結束語
本文基于TMS320DM*6平臺實現了Linux移植,包括創建交叉編譯環境、BootLoader的設計、Linux內核移植以及LCD、 USB設備驅動程序開發,為實時視頻處理應用開發創建了一個良好的嵌入式平臺,在此平臺上可進一步進行應用程序、GUI及視頻處理算法開發與測試。
評論
查看更多