嵌入式系統開發與應用概述
在今日,嵌入式ARM 技術已經成為了一門比較熱門的學科,無論是在電子類的什麼領域,你都可以看到嵌入式ARM 的影子。如果你還停留在微控制器級別的學習,那麼實際上你已經落下時代腳步了,ARM 嵌入式技術正以幾何的倍數高速發展,它幾乎滲透到了幾乎你所想到的領域。由於嵌入式系統具有體積小、效能強、功耗低、可靠性高以及面向行業具體應用等突出特徵, 目前已經廣泛地應用於軍事國防、消費電子、資訊家電、網路通訊、工業控制等各個領域。嵌入式的廣泛應用可以說是無所不在。
linux系統
linux系統主要是由使用者空間和核心空間再加上外部的硬體平臺構成,使用者空間就是使用者應用程式的執行空間,主要包括兩方面的內容:使用者應用程式和GNU C Library(glibc)。而核心空間有三方面的內容,一是系統呼叫介面,它作為使用者空間和核心空間相互轉移的一種方式,二是核心空間,三是體系相關核心程式碼,在linux核心程式碼中,可以看到arch目錄下有許多子目錄,其中每一個子目錄代表一種硬體平臺。
而為什麼要把linux系統劃分為使用者空間和核心空間呢?主要是一旦使用者空間和核心空間沒有分開,那使用者將擁有很大的許可權去操控核心或使用者應用程式的崩潰將會造成系統的崩潰,而linux系統是利用cpu的模式分級來分別執行使用者空間和核心空間,這樣就可以使作業系統得到充分的保護。而現代的cpu通常實現了不同的工作模式,以ARM處理器為例實現了7種執行模式,分別為:
1)使用者模式(usr):ARM微處理器正常程式執行模式
2)系統模式(sys):執行具有特權的作業系統任務
3)中斷模式(irq):用於通用的中斷處理
4)外部中斷模式(fiq):用於高速資料傳輸或通道處理
5)資料訪問終止模式(abt):當資料或指令預取終止時進入該模式,可用於虛擬儲存及儲存保護
6)管理模式(svc):作業系統使用的保護模式
7)未定義指令中止模式(und):當未定義的指令執行時進入該模式,可用於支援硬體協處理器的軟體模擬ARM微處理器的執行模式可以通過軟體改變,也可以通過外部中斷或異常處理改變,除使用者模式外,其他模式都是非使用者模式或特權模式,除使用者模式和系統模式外,其他模式都是異常模式,常用於處理異常或中斷,以及需要訪問受保護的系統資源等情況。
同時使用者空間和核心空間是程式執行的兩種不同狀態,通過系統呼叫和硬體中斷去實現使用者空間到核心空間的轉移,系統呼叫是主動的,硬體中斷是被動的,比如鍵盤按下或者串列埠中斷。
接下來說說linux的核心架構,它主要是包含7大組成部分
1.記憶體管理 記憶體管理的主要作用是使多個程序能安全高效的共享記憶體區域,通常使用以下兩個手段:
①記憶體對映:將實體記憶體對映到虛擬記憶體中,變有限為無限
②有效管理:使用各種記憶體管理演算法(如夥伴演算法),減少記憶體浪費
2.虛擬檔案系統 vfs隱藏了各種檔案系統的具體細節,為檔案操作提供統一的介面
3.網路協議棧 它為linux提供了完善豐富的網路協議實現
4.程序管理 程序管理的重點是建立程序、停止程序,並控制它們之間的通訊。程序管理還包括控制活動程序如何共享cpu,即程序排程。
5.裝置驅動 裝置驅動也是核心的一部分,它不同於核心的其他部件,並且獨立於核心的其他部件,同時它是與裝置互動的唯一模組,通常由第三方廠商開發,一個驅動程式不與其他驅動程式互動;核心與驅動程式之間也僅通過一個嚴格定義的介面-互動。
6.系統呼叫介面 SCI層為使用者空間提供了一套標準的系統呼叫函式來訪問Linux核心,搭起了使用者空間到核心空間的橋樑。
7.體系相關部分
Linux核心原始碼採用樹形結構進行組織,非常合理地把功能相關的檔案都放在同一個子目錄下,使得程式更具可讀性。
下面介紹下這些目錄的組成
arch目錄
arch是architecture的縮寫。核心所支援的每種CPU體系,在該目錄下都有對應的子目錄。每個CPU的子目錄,又進一步分解為boot,mm,kernel等子目錄,分別包含控制系統引導,記憶體管理,系統呼叫等。其下子目錄有
| --x86 /*英特爾cpu及與之相相容體系結構的子目錄*/
| |--boot /*載入程式*/
| | |--compressed /*核心解壓縮*/
| |--tools /*生成壓縮核心映像的程式*/
| |--kernel /*相關核心特性實現方式,如訊號處理、時鐘處理*/ | |--lib /*硬體相關工具函式*/
block目錄
部分塊裝置驅動程式
crypto目錄
加密、壓縮、CRC校驗演算法
documentation
核心的文件
drivers目錄(重點)
裝置驅動程式
fs目錄
存放各種檔案系統的實現程式碼。每個子目錄對應一種檔案系統的實現,公用的源程式用於實現虛擬檔案系統vfs。
| |--devpts /* /dev/pts虛擬檔案系統*/
| |--ext2 /*第二擴充套件檔案系統*/
| |--fat /*MS的fat32檔案系統*/
| |--isofs /*ISO9660光碟cd-rom上的檔案系統*/
include目錄
核心所需要的標頭檔案。與平臺無關的標頭檔案在include/linux 子目錄下,與平臺相關的標頭檔案則放在相應的子目錄中。
init目錄
核心初始化程式碼
ipc目錄
程序間通訊的實現程式碼
kernel目錄
Linux大多數關鍵的核心功能都是在這個目錄實現。(排程程式,程序控制,模組化)
lib目錄
庫檔案程式碼
mm目錄
mm目錄中的檔案用於實現記憶體管理中與體系結構無關的部分(與體系結構相關的部分在哪裡實現?arch)
net目錄
網路協議的實現程式碼
| |--802 /*802無線通訊協議核心支援程式碼*/
| |--appletalk /*與蘋果系統連網的協議*/
| |--ax25 /*AX25無線INTERNET協議*/
| |--bridge /*橋接裝置*/
| |--ipv4 /*IP協議族V4版32位定址模式*/
| |--ipv6 /*IP協議族V6版*/
samples
一些核心程式設計的範例
scripts
配置核心的指令碼
security
SElinux的模組
sound
音訊裝置的驅動程式
usr
cpio命令實現
virt
核心虛擬機器
Linux核心的配置與編譯
Linux核心具有可定製的優點,配置核心的目的是裁剪掉不必要的檔案和目錄,獲得一個最簡單的又能滿足使用者開發的作業系統,以解除嵌入式開發過程中所遇到的儲存空間有限的困擾。核心配置與編譯的具體步驟如下:
1.清除臨時檔案、中間檔案和配置檔案
1)make clean
Remove most generated files but keep the config即清除大部分生成的檔案但保留配置檔案
2)make mrproper
Remove all generated files + config files即清除所有生成的檔案還有配置檔案
3)make distclean
Mrproper + remove editor backup and patch files即實現
make mrproper命令的同時刪除編輯器備份檔案和補丁檔案
2.確定目標系統的軟硬體配置情況,比如cpu型別,網絡卡型號,所需支援的網路協議等。
3.使用如下命令之一配置核心:
1) make config:基於文字模式的互動式配置
2)make menuconfig:基於文字模式的選單型配置
3)make oldconfig:使用已有的配置檔案(ig),但是會詢問新增的配置選項
4)make xconfig:圖形化的配置(需安裝圖形化系統)
Make menuconfig是最為常用的核心配置方式 如果一個ig檔案已經存在,它將使用該檔案設定那些預設的值
4.編譯核心
編譯核心通常也需要幾個步驟,一是清除以前編譯通過的殘留檔案;二是編譯核心image檔案和可載入模組;三是安裝模組。
下面是編譯核心的具體步驟。
①make dep 命令用在核心2.4或之前,用於建立原始檔之間的依賴關係,在執行核心配置命令之後使用,不過在2.6核心中已經取消該命令,該功能由核心配置命令實現。
②make clean 命令用於刪除前面留下來的中間檔案,該命令不會刪除ig等配置檔案。這個步驟是可選的,它的目的是清除原先編譯過而殘留的和.o(obj檔案)。如果是剛下載的原始碼,那麼這一步就可以省略了,但是如果已經編譯多次核心,這一步是必要的,不然後面可能會出現很多莫名其妙的小問題。
③make zImage命令用於編譯生成壓縮形式的核心映象,當編譯成功後,就會在archarmboot目錄下生成zImage檔案,大小一般為幾百KB。對於嵌入式Linux核心而言,直接將生成的zImage下載到嵌入式目標板的flash中即可。對於較大的核心,如果用make zImage編譯,系統會提示使用make bzImage命令來編譯,bzImage是big zImage的縮寫,可用於生成較大的壓縮核心,比如桌面Linux系統核心。
④在配置選單的過程中,有些選項被選擇為模組的,即選項前為[M],並且在回答Enable loadable module support(CONFIG_MODULES)時選了Yes的,則接下來就還要用命令make modules 來編譯這些可載入模組,並用
make modules_install將make modules生成的模組檔案複製到相應目錄,桌面Linux核心一般是在/lib/modules目錄下。
⑤製作init ramdisk
mkinitrd initrd-$version $version
例:
mkinitrd initrd-2.6.29 2.6.29
$version 可以通過查詢/lib/modules下的目錄得到Ramdisk是將一部分固定大小的記憶體當做分割槽來使用。它並非一個實際的檔案系統,二是一種將實際的檔案系統裝入記憶體的機制,並且可以作為根檔案系統。將一些經常被訪問而又不會更改的檔案(如只讀的根檔案系統)通過ramdisk放在記憶體中,可以明顯的提高系統的效能。在linux的啟動階段,initrd提供了一套機制,可以將核心映像和根檔案系統一起載入記憶體。
⑥cp arch/x86/boot/bzImage
/boot/vmlinuz-$version
$version 為所編譯的核心版本號
(拷貝initrd-2.6.29到/boot下,將arch/x86/boot/bzImage更名為vmlinuz-2.6.29移動到/boot下)
⑦修改/etc/f 或者/etc/f
(GNU GRUB(簡稱 GRUB )是一個來自GNU專案的多作業系統啟動程式。GRUB是多啟動規範的實現,它允許使用者可以在計算機內同時擁有多個作業系統,並在計算機啟動時選擇希望執行的作業系統。GRUB可用於選擇作業系統分割槽上的不同核心,也可用於向這些核心傳遞啟動引數。)
這時重啟Linux作業系統,在進入核心時按下回車鍵進入核心選擇介面,選擇自己編譯的核心,即可進入自己編譯的核心的作業系統,用uname -r 可以檢視當前核心版本。
嵌入式linux檔案系統的製作與移植
檔案系統包含兩個層次的含義:
1.按照固定格式組織的目錄與檔案
2.在特定的儲存介質上管理這些目錄和檔案需要的資料
當我們在linux下輸入ls / 的時候,見到的目錄結構以及這些目錄下的內容都大同小異,這是因為所有的linux發行版在對根檔案系統的佈局上都遵循FHS(Filesystem Hierarchy Standard)標準的建議規定。
各個目錄名稱及其存放的內容:
/bin 必備的使用者命令,例如ls、cp等
/sbin 必備的系統管理員命令,例如ifconfig、reboot等
/dev 裝置檔案,例如mtdblock0、tty1等
/etc 系統配置檔案,包括啟動檔案,例如inittab等
/lib 必要的`連結庫,例如C連結庫、核心模組
/home 普通使用者主目錄
/root root使用者主目錄
/usr/bin 非必備的使用者程式,例如find、du等
/usr/sbin 非必備的管理員程式,例如chroot、inetd等
/usr/lib 庫檔案
/var 守護程式和工具程式所存放的可變,例如日誌檔案
/proc 用來提供核心與程序資訊的虛擬檔案系統,由核心自動生成目錄下的內容
/sys 用來提供核心與裝置資訊的虛擬檔案系統,由核心自動生成目錄下的內容
/mnt 檔案系統掛接點,用於臨時安裝檔案系統
/tmp 臨時性的檔案,重啟後將自動清除
根檔案系統是Linux啟動時使用的第一個檔案系統。沒有根檔案系統,Linux將無法正常啟動。根檔案系統由一系列目錄組成,目錄中包含了應用程式、C庫、以及相關的配置檔案。
那如何製作一個根檔案系統呢?主要包括以下步驟:
1、建立根檔案系統的目錄
如:mkdir bin sbin lib etc dev proc sys usr mnt tmp var
2、建立裝置檔案
cd dev
mknod -m 666 console c 5 1
mknod -m 666 null c 1 3
cd ..
3、安裝/etc
tar -xzvf /xx-x/rootfs/etc
4、配置busybox
進入busybox目錄執行
make menuconfig
進入 Busybox Settings
build Options->
選中 “Build busybox as a static binary”, 靜態連結
Cross Compiler prefix (arm-linux-)
Installation Options->
選中 “Don‘t use /usr”, 選中該項可以避免busybox被安裝到
宿主系統的/usr目錄下,破壞宿主系統
Busybox Installation Prefix (/nfsroot/rootfs)該選項表明編
譯後的busybox的安裝位置
7、編譯、安裝busybox
make ARCH=arm CROSS_COMPILE=arm-linux-
make install
前提是系統中安裝好了交叉編譯工具arm-linux-gcc
至此一個粗略的根檔案系統製作完成,下面就需要移植到開發板中。 我們知道ARM嵌入式系統的組成為:
1)bootloader 引導載入器
2)kernel 作業系統核心
3)rootfs 根檔案系統 (帶GUI,QTopia)
在系統載入完核心後就會去啟動根檔案系統,而啟動根檔案系統這個過程被bootargs這個引數控制,所以我們需要修改這個引數以使系統執行我們的根檔案系統,但這之前我們需要在宿主機上將根檔案系統共享出來。我們先在linux系統中配置好nfs伺服器,並且在設定配置檔案exports將根檔案系統所在路徑共享出來,接下來在ARM開發板啟動時控制超級終端進入shell介面,在這裡輸入命令print會顯示開發板啟動的配置資訊,通過set命令我們可以設定bootargs 引數為:
console=ttySAC0
root=/dev/nfs
nfsroot=:/mynfs/rootfs ip=:eth0:off
設定完成後用save命令儲存設定,輸入reset復位命令,ARM系統重啟,重啟完成後我們看到ARM系統的根檔案系統就是我們自己製作的根檔案系統。
實習體會
在嵌入式系統中,除了課本上的基礎知識外,還學會了軟體程式設計的基本思路,掌握了液晶屏的使用及其電路設計方法;掌握有關音訊處理的基礎知識;掌握液晶顯示文字及圖形的方法與程式設計。
通過這次設計,掌握了液晶顯示實驗、μC/OS-II移植、μC/OS-IILCD顯示的工作原理及串列埠通訊實驗的工作過程,學會了使用模擬軟體Embest EduKit-IV實驗平臺及ULINK2模擬器套件,並學會通過應用軟體模擬來實現各種通訊系統的設計,對以後的學習和工作都起到了一定的作用,加強了動手能力和學業技能。雖然花了很長時間編寫軟體程式設計,但這一切還是理論上的。希望學校能提供機會和條件,讓我們能夠去真正地將理論和實踐相結合。通過這次程式,感覺自己所掌握的知識是那麼的有限,還有許多需要改進和不足的地方,同時也幫助了我怎樣學好這門課程,增加了我對這門學科的興趣。總體來說,這次實習我受益匪淺。在摸索該如何設計電路使之實現所需功能的過程中特別有趣,培養了我的設計思維,增加了實際操作能力。在讓我體會到了設計電路的艱辛的同時,更讓我體會到成功的喜悅和快樂。通過這次實習通訊系統的設計,使我更加清楚以後的發展及學習的方向。