1.Eclipse軟體工程結構
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLzMGVOFTUE5keRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3cDN0IzMyYTMzATOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
主要介紹上面兩個:
- 應用程式開發,開發者建立的軟體工程
- BSP
- system.h,連接配接QSYS硬體和軟體的橋梁,包括所有QSYS系統中的IP資訊,包括基位址、中斷号等。
- HAL結構,硬體抽象層系統庫是在應用程式和系統硬體之間的一個系統庫,HAL應用程式接口(API)與ANSI C标準庫綜合在一起,可以使用類似C語言的庫函數的方式通路硬體裝置或檔案。我們可以用這個系統庫函數來和底層的硬體進行互動而無需關注底層細節。HAL可看做是一個支援應用程式開發的軟體平台,提供了大量API函數接口,屏蔽硬體通路細節(不像HDL語言一樣必須去描述複雜時序)雖然占用一些額外資源,但大大提升開發速度和可移植性。比如想要擷取時間資訊,需要在QSYS中調用Timer,在軟體工程中擷取時間戳資訊時,隻需要#include <sys/alt_timestamp.h>就可以調用API函數alt_timestamp_start()來開啟時間戳服務,調用t1 = alt_timestamp()擷取時間資訊。
- BSP包括五部分:
- 內建C标準函數庫,在Include檔案中
- 提供通路QSYS系統中各個裝置的驅動程式, 在drivers檔案夾中,包含以下6類裝置:
- 字元型裝置,接收和發送字元串的外圍硬體裝置,如JTAG、UART
- 檔案子系統,提供通路存儲在實體裝置中的檔案操作,如使用者可以利用有關flash的HAL API來編寫Flash檔案子系統驅動來通路Flash
- DMA裝置,包括DMA控制器核。執行大量資料在資料源和目的地之間傳輸的外圍裝置。資料源和目的地可以是儲存設備,也可以是其他裝置(以太網、usb)
- 定時器裝置,對時鐘脈沖計數并産生周期行中斷請求的外圍裝置
- Flash裝置,包括通用Flash接口晶片和主動串行配置器件EPCS控制器
- 以太網裝置,對Altera提供的輕量級IP協定提供通路的以太網連接配接(包括LAN9111以太網MAC/PHY控制器,并且需要uC/OS-II的支援)
- HAL通用的API函數(庫),在HAL檔案夾中
- 系統初始化函數(alt_sys_init.c),為main函數建立運作環境,包括BootLoader、程式重定位
- 裝置初始化函數 ,在main()函數之前,配置設定裝置空間并初始化所有外圍裝置
2.HAL異常處理
NIOS中的異常不采用中斷向量表,所有異常都駐留在一個單一存儲空間的代碼來處理,該空間為exception address。該空間内,系統會自動插入判斷中斷源和優先級的代碼,使用者隻需要編寫中斷服務子程式即可。
2.1 中斷異常處理過程
- 保護現場;查找中斷源;調用相應中斷服務子程式(使用者編寫);恢複現場;中斷傳回。
- 把status寄存器内容複制到estatus寄存器中,保持目前處理器狀态
- 清除status寄存器的PIE位為0,禁止所有硬體中斷
- 異常傳回位址寫入ea寄存器(r29)
- 跳轉到異常處理位址。若是内部中斷,則跳向異常位址;若是外部中斷則跳向裝置指定的中斷位址
- 使用HAL API 函數編寫中斷服務程式分兩步:
- 注冊中斷。推薦使用新版本中斷函數即帶ic的版本,雖然大部分IP支援兩種中斷函數,但是當用外部中斷時必須使用新版本中斷函數。alt_ic_isr_register(UART0_IRQ_INTERRUPT_CONTROLLER_ID(控制器ID),UART0_IRQ(中斷優先級),uart0_cmd_isr(中斷處理函數),(void *) &uart_context(可選指針指向特定元件的資料結構,可聲明一個 char * p 但是不用它),0(保留項,為0))【後兩個也可以直接寫NULL】
- 編寫中斷服務函數 void uart0_cmd_isr(void* isr_context) //isr_context可為空。
2.2 中斷注意事項:
- 中斷服務程式主要處理一些高優先級,實時性強的操作,是以不可以在中斷服務程式裡面進行等待或者其他阻塞性質的操作。
- 保持中斷服務程式精簡,保證快速可靠
- 把無關緊要的事務放在中斷服務程式之外處理
- 避免調用C庫函數,運作效率較低(如printf()),可能會引起阻塞且運作時間不可預知,對實時響應不利
- 避免浮點運算
- 中斷調試時在中斷服務程式中設定斷點,中斷來臨後單步調試時會忽略其他中斷
- 避免使用printf函數,而是用sprintf()函數代替,将關鍵資料寫到記憶體,然後觸發外部分析程式。
3.NIOS上電自啟動
3.1 BootLoader
- 程式在RAM中運作,若想讓他斷電後不消失必然需要将它存儲在非易失存儲器中,而上電自啟動的過程需要BootLoader作為一個搬運工,将存儲在非易失存儲器中的代碼轉移到RAM。主要包括兩步:
- 1.FPGA器件本身的配置過程。使用FPGA器件外部配置控制器或者Qsys自帶的配置控制器IP(EPCS/EPCQ)控制配置FPGA的内部邏輯。若内部邏輯使用了NIOS則配置完成後的FPGA中也會有NIOS。
- 2.NIOS本身的引導過程。FPGA配置完畢後,NIOS就被邏輯中的複位電路複位,然後從頭開始執行代碼。
- 下圖是BSP editor中的連結腳本linker script頁面(灰色部分在QSYS的處理器配置頁面指定):
NIOS軟體架構1.Eclipse軟體工程結構2.HAL異常處理3.NIOS上電自啟動 - .bss(未初始化變量資料段):未初始化變量,如全局變量定以後,但未初始化的都在這裡
- .entry(複位位址):軟體代碼的存儲區,程式從此處開始啟動
- .exceptions(異常處理位址):系統異常處理代碼的存放區域
- .heap(堆):動态配置設定記憶體的存儲區,從小位址向大位址方向增長
- .rodata(隻讀資料段):存放程式中靜态全局變量,所有有初值的全局變量放在這裡
- .rwdata(可讀寫資料段):用于存放程式中可讀寫變量和指針變量
- .stack(棧):函數調用變量與臨時資料存儲器區域(如傳回位址、現場資訊),從大向小位址方向增長
- .text(正文段,隻讀):代碼執行區,也就是NIOS程式最終運作的地方;一個程式隻有一個副本;隻讀,防止意外修改自身指令
- 上圖中所有配置會反應在BSP檔案夾中的linker.x檔案中
- 上電後程式運作前所有的資料都是放在Flash中的,若系統Reset位址和其他段位址設定(Exception位址、.text位址)的不同,那麼系統從Reset位址啟動時會從Flash中把相關資料自動下載下傳到相應位址或初始化相應位址。
- 若Exception address和Reset address不同,那麼程式從Reset address中啟動後将把放在後者中的系統異常處理代碼拷貝到前者
- test address類似,将會把後者中的隻讀程式段拷貝到test address中
- 在NIOS的Flash Programmer中,我們需要添加QSYS系統的.sopcinfo檔案,軟體elf檔案,硬體sof檔案。Flash Programmer會根據前兩個中指定的複位位址以及各個段的運作位址來判斷到底是否需要添加BootLoader(由EPCS/EPCQ Controller提供),若所有的段都運作在flash存儲器中,那就不用添加。但這是不可能的,會導緻程式運作的效率差。若存在,BootLoader就是系統加電後運作的第一段代碼,實作代碼的搬運。
- BootLoader的任務:
- 1.完成複位子程式的功能。在從複位位址開始的32位元組(指令緩存行的尺寸)空間内完成複位的軟體響應。
- 2.加載應用項目程式映像中的代碼和資料段。從裝載位址Reset address加載程式運作位址.text。
- 3.跳轉到應用程式入口。通常是__start。
- 當BootLoader跳轉到應用程式入口後,會用到NIOS軟體架構準備的啟動代碼,即Crt0.S(先)和alt_main.c(後)兩個HAL源檔案。包括各種初始化任務,在alt_main.c的末尾最終跳轉到我們編寫的main.c。
3.2 程式上電後的執行過程
- 1.由BootLoader将Flash中的.entry内容拷貝到.text中
- 2.跳轉到ctr0.S _start标号處
- 3.初始化資料緩存
- 4.初始化全局變量指針
- 5.清零.bss
- 6.調用alt_load函數。調用alt_load_section函數加載.rwdata,.exception,.rodata節點,調用alt_deche_flush_all函數和alt_icache_flush_all函數同步緩存。(當使用了BootLoader後不用調用alt_load,它們完成一樣的功能)
- 7.調用alt_main()函數。調用alt_irq_init函數初始化中斷,調用alt_sys_init函數初始化添加的IP。其它初始化。
- 8.調用main()函數
- 9.調用close函數
- 10.調用exit函數
NIOS軟體架構1.Eclipse軟體工程結構2.HAL異常處理3.NIOS上電自啟動