SkyEye硬件模擬平臺,第三部分: 硬件仿真實現之六SkyEye的擴展 |
| |||||||||||
未顯示需要 JavaScript 的文檔選項 |
級別: 初級
陳渝 ([email protected])清華大學
2004 年 11 月 01 日
本系列文章的第三部分主要介紹了SkyEye硬件模擬平臺的實現細節。主要內容包括SkyEye的總體設計、SkyEye的可擴展框架、SkyEye的關鍵數據結構、SkyEye對各種CPU的模擬實現、SkyEye對各種外設的模擬實現、如何安裝使用SkyEye以及如何擴展SkyEye的仿真模塊等。對SkyEye的深入瞭解,有助於對嵌入式硬件系統有更深入的認識,特別是對操作系統、驅動程序如何與嵌入式硬件系統進行交互有更深刻的瞭解。
對SkyEye的擴展可以在三個層次上,一是加入新的體系結構,如X86、MIPS等;二是在已有的體系結構下添加新的開發板,如你可以在ARM體系結構中添加Lubbock開發板;第三種就是在SkyEye已經模擬的開發板上添加新的硬件。
目前SkyEye模擬的體系結構相關目錄都在sim目錄中,如sim/arm是模擬arm體系結構的開發板,sim/ppc是模擬ppc體系結構的開發板,sim/mips是模擬mips體系結構中的開發板等等。如果需要加新的體系結構進去,需要在sim/目錄下新建一個目錄,把你的相關代碼放入。而加新的開發板進去,則要視所加具體開發板處理器的體系結構而定,來重用已有代碼。
下面我們以在ep7312開發板上擴展8019網絡芯片爲例,來講解如何在模擬的ep7312開發板加入網絡芯片模擬。驅動程序作爲底層硬件和操作系統之間的接口,管理硬件,併爲操作系統屏蔽底層硬件,提供服務。
我們需要做兩件事情,操作系統的驅動程序如何可以訪問我們虛擬網絡芯片的數據和控制信息?在虛擬網絡芯片接收到數據包時,如何通知CPU發出中斷,通知驅動程序處理到達的數據包?
我們在ep7312的硬件手冊上可以看到它的地址分佈:
起始地址 | 用途 | 大小 |
0x80004000 | 未使用 | ~1G |
0x80000000 | 內部寄存器 | 8k |
0x70000000 | BootRom(nCS[7]) | 128字節 |
在這裏,我們是使用0x8000a000爲起始地址,大小爲 255字節的地址空間作爲虛擬網絡芯片的io內存,供驅動程序訪問。同時我們選擇了尚未被使用的外部中斷號EINT1作爲我們的網絡中斷。關於中斷寄存器的定義請參考ep7312的相關文檔。
相關代碼在sim/arm/skyeye_mach_ep7312.c的ep7312_io_reset函數中:
io.net_int = EINT1; /* Here we use RINT1 as netcard interrupt io.net_io_baseaddr = 0x8000a000; /* netcard iomem start address*/ io.net_io_size = 255; /* netcard iomeme size*/ |
下面我們來看一下虛擬網絡芯片的硬件中斷是如何產生的:
圖 0-1 中斷處理流程圖
在這裏,有些人會問,我們產生中斷之後,誰來處理?首先我們要明確,硬件只產生中斷,如何處理則是操作系統的任務,虛擬網絡芯片會將自己相應的中斷置位,由操作系統輪詢中斷狀態寄存器,並調用網絡芯片的驅動程序在初始化時所註冊的中斷處理程序處理中斷。需要注意的是,在處理完中斷之後,一定要清除相應的中斷位,否則後面的中斷無法進來。
SkyEye的相關代碼如下:
//判斷當前模擬開發板的網絡選項是否打開,並且當前是否已經有中斷在處理 if(skyeye_net_on && !(io.intsr & io.net_int)){ fd_set frds; struct timeval tv; FD_ZERO(&frds); skyeye_net_fdset(&frds); tv.tv_sec = 0; tv.tv_usec = 0; ret = 0; //判斷虛擬網絡接口是否接收到數據,如果有,則轉入網絡芯片的接收處理函數 if((ret = select(skyeye_net_maxfd+1,&frds,NULL,NULL,&tv))>0){ skyeye_net_input(&frds,state); } } 下面是網絡芯片接收函數skyeye_net_input void tapif_input(int tapif_fd, ARMul_State *state) { ………………………………………… //這裏省略大段網絡芯片接收數據的代碼 …………………………………………… //如果接收數據正常,則調用SET_NET_INT()來給相應的中斷置位 if((ISR_PRX & rtl8019.IMR)){ SET_NET_INT(); skyeye_config.mach->mach_update_int(state); } DBG_PRINT("tapif_input end/n"); } |
SET_NET_INT();是一個定義在skyeye-ne2k.c的宏,定義如下: #define SET_NET_INT() *state->mach_io.instr |= *state->mach_io.net_int 這樣我們便完成了和驅動程序通信的任務。
在這裏我們並沒有指定特定的開發板,所有的開發板和CPU的細節被放到了state這個結構指針中,這樣我們可以在不同的開發板和CPU上不加更改的重用這段代碼。
在這裏我們還需要注意的一個細節是,對於有MMU的CPU來說,驅動程序看到的地址是經過MMU變換的虛擬地址。至於具體到ep7312開發板,對應於我們虛擬網絡芯片的io內存的虛地址爲0xffffa000。
|
本文講解了SkyEye硬件模擬平臺的實現細節,以及如何擴展SkyEye。瞭解SkyEye的實現細節可以讓嵌入式系統開發人員對嵌入式系統硬件的運行機理有更深入的掌握,特別是對操作系統、驅動程序如何與嵌入式硬件系統進行交互有更深刻的瞭解。
- 本文節自 《源碼開放的嵌入式系統軟件分析與實踐--基於SkyEye和ARM開發平臺》一書的第三章,對 SkyEye 開源項目感興趣的可以閱讀本書。
- SkyEye硬件模擬平臺, 第一部分: SkyEye 介紹
- SkyEye硬件模擬平臺,第二部分: 安裝與使用
- SkyEye硬件模擬平臺,第三部分: 硬件仿真實現之一
- SkyEye硬件模擬平臺,第三部分: 硬件仿真實現之二
- SkyEye 硬件模擬平臺,第三部分: 硬件仿真實現之三
- SkyEye 硬件模擬平臺,第三部分: 硬件仿真實現之四
- SkyEye 硬件模擬平臺,第三部分: 硬件仿真實現之五
- 在 developerWorks Linux 專區 可以找到更多爲 Linux 開發者準備的參考資料。
陳渝, 清華大學,通過 [email protected] 可以和他聯繫。 |