FPGA 之 SOPC 系列(六)Nios II 程序开发 II
FPGA 之 SOPC 系列(六)Nios II 程序開發(fā) II
今天給大俠帶來今天帶來FPGA 之 SOPC 系列第六篇,Nios II 程序開發(fā) II,希望對各位大俠的學(xué)習(xí)有參考價值,話不多說,上貨。
本篇接著第五篇繼續(xù)介紹NIOS II的寄存器級編程方式,以該方式的定時器的編程實(shí)例應(yīng)用。
以下為本篇的目錄簡介:
-
6.1 項(xiàng)目文件的管理
-
6.2 寄存器級編程
-
6.3 定時器應(yīng)用
?
6.1 項(xiàng)目文件的管理
每個C工程中,可以以功能為依據(jù)對源文件迕行文件夾分類。文件夾不可以出現(xiàn)空格、除英文字母、數(shù)字、下劃線外的字符;更不允許出現(xiàn)漢字等非 ASCII碼字符。例如某個工程可以劃分為如下文件夾:
-
doc 說明文檔
-
config 系統(tǒng)相關(guān)配置文件夾(系統(tǒng)參數(shù)配置、編譯器、連接器配置文件等)
-
driver 硬件驅(qū)動文件夾(包括芯片驅(qū)動、cpu外設(shè)驅(qū)動等)
-
font 字體驅(qū)動
-
Gui 圖形界面驅(qū)動
-
main 主程序
-
include 頭文件
-
obj 編譯后的目標(biāo)文件
功能劃分應(yīng)以邏輯清晰、層次關(guān)系明顯為目的。一旦劃分好后,不可越級調(diào)用系統(tǒng)資源(例如只有driver內(nèi)文件內(nèi)直接操作硬件資源,其他文件夾代碼均不可調(diào)用最底層硬件資源)。也不要互相調(diào)用而使系統(tǒng)資源很快耗盡
文件一旦建立,就需在文件頭說明文件目的、版權(quán)及歷史記錄,每次修改后必須記錄。工程完工或者是間歇性擱置時,需要對所有工程文件夾、文件進(jìn)行只讀屬性設(shè)置及當(dāng)前狀態(tài)設(shè)置。對源代碼最好做到每天一備份,以防意外篡改及丟失,以備恢復(fù)之用。
?
6.2 寄存器級編程
例:點(diǎn)亮LED的例子轉(zhuǎn)換新的編程方式
第一步,按照上述的文件管理方式,建立一個放置頭文件的文件夾,命名為inc, 在工程文件夾上點(diǎn)擊右鍵,然后點(diǎn)擊NEW中的SOURCE FOLDER。
下一步,在紅圈處輸入inc,點(diǎn)擊finish,完成文件夾建立。
下一步,在這個新建的文件夾下建立一個頭文件,方法如下圖所示,在inc上點(diǎn)擊右鍵,然后點(diǎn)擊NEW中的header file,輸入sopc.h。
打開剛才建立的頭文件,補(bǔ)充完代碼后如下:
#ifndef SOPC_H_ #define SOPC_H_ #include "system.h" #define _LED typedef struct { unsigned long int DATA; unsigned long int DIRECTION; unsigned long int INTERRUPT_MASK;; unsigned long int EDGE_CAPTURE; }PIO_STR; #ifdef _LED #define LED ((PIO_STR *)LED_PIO_BASE) #endif #endif /*SOPC_H_*/
其中定義了一個結(jié)構(gòu)體,這個結(jié)構(gòu)體被指向了LED_PIO_BASE,查相關(guān)手冊, n2cpu_Embedded Peripherals.pdf。
這兩個表格就是PIOCORE寄存器映射,我們這個結(jié)構(gòu)體啊就是根據(jù)它寫出來的,名字不重要,重要的是順序,也就是偏移量。第一項(xiàng)是數(shù)據(jù)DATA,第二項(xiàng)是IO口方向,第三項(xiàng)是中斷控制位,第四項(xiàng)是邊沿控制位。他們每一項(xiàng)都有N位,這個N就是我們在軟件構(gòu)建中的寬度,這個時候我們這里的N等于幾?
-
#define LED ((PIO_STR *)LED_PIO_BASE)
-
它就是怎么把我們定義的結(jié)構(gòu)體給勾上LED設(shè)備的。記得LED_PIO_BASE,它就是我們在SYSTEM.H中特別強(qiáng)調(diào)的。定義了一個宏,命名為LED,它是指向LED_PIO_BASE的結(jié)構(gòu)指針,這個結(jié)構(gòu)就是PIO_STR.
-
#define _LED
-
#ifdef _LED
-
#endif
-
意思是為了控制定義#define LED ((PIO_STR *)LED_PIO_BASE)的,這樣做是為了增強(qiáng)代碼的嚴(yán)謹(jǐn)性和可控制性。
把之前的模板文件hello_world.c名字改為main.c并將它放到main文件夾中,右擊rename后,選中main.c右擊鼠標(biāo)move后,選中main文件夾就ok了。
#include <stdio.h> #include <unistd.h> #include "../inc/sopc.h" int main (void) __attribute__ ((weak, alias ("alt_main"))); int alt_main() { int i; while (1) { for(i=0;i<4;i++){ LED->DATA =1<<i; usleep(500000); } } return 0; }
LED->DATA =1<<i;LED是在SOPC.H中定義的宏,是結(jié)構(gòu)體指針,它的結(jié)構(gòu)體中DATA的內(nèi)容(不是地址)。這里的usleep是微秒級延時的。
總結(jié)一下:
-
文檔的歸類管理。
-
Sopc.h定義來源是相關(guān)外設(shè)的文檔寄存器。
-
操作定義好的外設(shè)結(jié)構(gòu)體變量編程。
并不是,要看什么要的外設(shè),想FLASH這種外設(shè),采用這種方式的話,累死你,我們就直接可以使用API來寫就行了。這種方式對我們了解nios的本質(zhì)是很有幫助的。
?
6.3 定時器應(yīng)用
概覽
該時間計(jì)數(shù)器是一個為諸如NIOS II 等基于Avalon架構(gòu)的處理器設(shè)計(jì)的時間計(jì)數(shù)器。該計(jì)數(shù)器有如下特點(diǎn):
(1)32位和64位計(jì)數(shù);
(2)具有計(jì)數(shù)開始、計(jì)數(shù)停止、和復(fù)位計(jì)數(shù)器功能;
(3)兩種技術(shù)模式:單次計(jì)數(shù)、連續(xù)計(jì)數(shù);
(4)計(jì)數(shù)周期寄存器;
(5)當(dāng)計(jì)數(shù)器計(jì)數(shù)到0時,可以選擇使能或者禁止觸發(fā)中斷(IRQ);
(6)可選作為看門狗,產(chǎn)生系統(tǒng)復(fù)位;
(7)可選產(chǎn)生周期脈沖,當(dāng)計(jì)數(shù)器計(jì)數(shù)到0時;
(8)可用于32位或者16位處理器中。如16位的NIOS和32位的NIOS II。
Interval TimerCore 功能描述
(1)Avalon-MM提供可對6個16位寄存器操作的功能;
(2)可選周期脈沖輸出。
所有的寄存器都是16位寬度的,因此可適應(yīng)于16位或者32位處理器。若該核被配置為一個固定的周期,那么,周期寄存器就不存在。
計(jì)數(shù)周期(Timeout Period)
計(jì)數(shù)周期決定了周期計(jì)數(shù)器值。當(dāng)使能可寫周期(Writeableperiod),處理器可以通過寫周期計(jì)數(shù)器( period registers)改變計(jì)數(shù)器值。或者當(dāng)禁止可寫周期(Writeableperiod),周期計(jì)數(shù)器(period registers)不可經(jīng)過處理器的寫操作而改變;此時周期計(jì)數(shù)器只能是一個不可改變的固定周期計(jì)數(shù)值。Interval Timer Core的計(jì)數(shù)周期是系統(tǒng)時鐘周期的整數(shù)倍。實(shí)際的時鐘周期讀者可以這樣求。
(1)求出系統(tǒng)的時鐘。指驅(qū)動Interval Timer Core的時鐘。一般與NIOS II 時鐘一致。
(2)將周期計(jì)數(shù)器里面高16位和低16位的值乘與時鐘時期即得計(jì)數(shù)周期。
計(jì)數(shù)大小(Counter Size)
該設(shè)定決定了計(jì)數(shù)器的位寬。可以設(shè)定為32位或者64位。32位位寬的計(jì)數(shù)器包含有2個16位的寄存器;而64位位寬的計(jì)數(shù)器包含有4個16位寬的寄存器。該設(shè)定同樣應(yīng)用至snap單元。
硬件選項(xiàng)
(1)Simple periodic interrupt—該設(shè)定用于只需要一個帶有中斷(IRQ)的計(jì)數(shù)器。該方式下,計(jì)數(shù)周期是固定不可軟件更改的,且計(jì)數(shù)不能停止但中斷(IRQ)可禁止。
(2)Full-featured—該配置適用于一個可被處理器更改,可變計(jì)數(shù)周期,且其開始、停止均可被更改的計(jì)數(shù)器。
(3)Watchdog—適用于系統(tǒng)需要看門狗的情況。當(dāng)系統(tǒng)停止響應(yīng),該配置能使系統(tǒng)復(fù)位。
寄存器(registeregister)設(shè)定說明
(1)Writeable period——當(dāng)選中此項(xiàng),則主外設(shè)(NIOS II)可通過寫周期寄存器(period registers)達(dá)到修改計(jì)數(shù)周期的目的。若未選中此項(xiàng),則計(jì)數(shù)周期被確定為(Timeout Period),不可更改;同時周期寄存器(period registers)不再存在。
(2)Readable snapshot——當(dāng)選中此項(xiàng),則主外設(shè)(NIOS II )可以讀取當(dāng)前計(jì)數(shù)值。若未選中此項(xiàng),則主外設(shè)只能依靠查詢狀態(tài)寄存器(status register)或者中斷(IRQ)標(biāo)志來得知計(jì)數(shù)狀態(tài);此時(snap registers)并不存在,讀取該寄存器會有不確定的數(shù)值。
(3)Start/Stop control bits——當(dāng)選中此項(xiàng),則主外設(shè)( NIOS II )可以通過寫控制寄存器(control register)來啟動、停止計(jì)數(shù)器。若未選中此項(xiàng),則計(jì)數(shù)器默認(rèn)為連續(xù)計(jì)數(shù)模式。值得注意的是,當(dāng)系統(tǒng)看門狗復(fù)位(System reset on timeout (watchdog))是使能狀態(tài),則控制寄存器(control register)中的(start)位被置位,而不管Start/Stop 控制位的狀態(tài)。
信號輸出選項(xiàng)
( 1 ) Timeout pulse (1 clock wide) — — 當(dāng)選中該項(xiàng), 則計(jì)數(shù)器產(chǎn)生一個信號端口(timeout_pulse),該信號端口在計(jì)數(shù)器減計(jì)數(shù)至0時產(chǎn)生一個系統(tǒng)時鐘周期的高電平。若未選中該項(xiàng),則計(jì)數(shù)器不產(chǎn)生該信號端口。
(2)System reset on timeout (watchdog)——當(dāng)選中該項(xiàng),則計(jì)數(shù)器產(chǎn)生一個復(fù)位信號端口(resetrequest port)該信號在計(jì)數(shù)器減計(jì)數(shù)至0時產(chǎn)生一個系統(tǒng)時鐘周期的高電平。若未選中該項(xiàng),則該信號端口不存在。
配置計(jì)數(shù)器為看門狗
若要使用看門狗,則應(yīng)作如下選擇。
(1)presets:選擇Watchdog;
(2)Timeout Period修改成所需要的時間
(3)Writeable period禁止;
(4)Readable snapshot禁止;
(5)Start/Stop control bits禁止;
(6)Timeout pulse禁止;
(7)System reset on timeout (watchdog)使能。
復(fù)位之后看門狗是禁止的。隨后,處理器往控制寄存器(control register)的START位寫1。開啟看門狗計(jì)數(shù)器。看門狗一旦開啟,就不能結(jié)束。為了不使系統(tǒng)復(fù)位,處理器應(yīng)該定時地復(fù)位計(jì)數(shù)值。
Interval Timer Core 軟件編寫
狀態(tài)寄存器(status Register Bits)
TO——當(dāng)計(jì)數(shù)器減計(jì)數(shù)到0時,置1。一旦置1,則必須由主外設(shè)(NIOS II)清0;
RUN——當(dāng)計(jì)數(shù)器在計(jì)數(shù)運(yùn)行時,RUN=1;否則RUN=0。寫RUN對值無影響。
控制寄存器(control register)
ITO——當(dāng)ITO=1時,計(jì)數(shù)器會產(chǎn)生中斷。反之則反。
CONT——若COUNT=1則計(jì)數(shù)器計(jì)數(shù)到0連續(xù)計(jì)數(shù),知道STOP=1;若COUNT=0則計(jì)數(shù)器計(jì)數(shù)到0時,停止計(jì)數(shù)。
START——寫1到START則使計(jì)數(shù)器開始計(jì)數(shù)。當(dāng)計(jì)數(shù)器正在計(jì)數(shù)運(yùn)行,則寫START無效。
STOP——寫1到STOP則使計(jì)數(shù)器停止計(jì)數(shù)。若計(jì)數(shù)器已經(jīng)停止計(jì)數(shù),則寫STOP無效。當(dāng)SOPC配置為Start/Stop control bits為關(guān)閉,則寫STOP無效。
中斷(IRQ)
當(dāng)計(jì)數(shù)器減計(jì)數(shù)到0時并且控制寄存器(congtrol register)ITO位被置1,則可產(chǎn)生定時器中斷。
處理中斷應(yīng)用以下兩種方式之一:
(1)清除狀態(tài)寄存器(status register)的TO位;
(2)清除控制寄存器(congtrol register)ITO位,禁止中斷。否則會產(chǎn)生不確定結(jié)果。
實(shí)例程序
/**//************************ 定時器中斷注冊初始化函數(shù)*****************************/ void InitInterrupt() { //----------------------------定時器中斷,系統(tǒng)時鐘66.7MHz-------------------- ------// alt_irq_register(TIMER_IRQ,NULL,Timer_interrupts); //注冊中斷函數(shù) IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_BASE, 0x000A); IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_BASE, 0x2C2A);//修改定時時間10ms IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_BASE, 7); //啟動定時器允許中斷,連續(xù)計(jì)數(shù) } /**//*************************定時器中斷服務(wù)函數(shù)*****************************/ void Timer_interrupts(void* context, alt_u32 id) { /**//***************************服務(wù)代碼**************/ /**//**********************退出時清狀態(tài)寄存器***********/ IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_BASE, 0); //清狀態(tài)寄存器 } typedef struct{ union{ struct{ volatile unsigned long int TO :1; volatile unsigned long int RUN :1; volatile unsigned long int NC :30; }BITS; volatile unsigned long int WORD; }STATUS; union{ struct{ volatile unsigned long int ITO :1; volatile unsigned long int CONT :1; volatile unsigned long int START :1; volatile unsigned long int STOP : 1; volatile unsigned long int NC :28; }BITS; volatile unsigned long int WORD; }CONTROL; volatile unsigned long int PERIODL; volatile unsigned long int PERIODH; volatile unsigned long int SNAPL; volatile unsigned long int SNAPH; }TIMER;
FPGA 之 SOPC 系列第六篇就到這里結(jié)束,下一篇將帶來第七篇,NIOS II 高級技術(shù)等相關(guān)內(nèi)容。
?
【QQ交流群】
群號:173560979,進(jìn)群暗語:FPGA技術(shù)江湖粉絲。
多年的FPGA企業(yè)開發(fā)經(jīng)驗(yàn),各種通俗易懂的學(xué)習(xí)資料以及學(xué)習(xí)方法,濃厚的交流學(xué)習(xí)氛圍,QQ群目前已有1000多名志同道合的小伙伴,無廣告純凈模式,給技術(shù)交流一片凈土,從初學(xué)小白到行業(yè)精英業(yè)界大佬等,從軍工領(lǐng)域到民用企業(yè)等,從通信、圖像處理到人工智能等各個方向應(yīng)有盡有。
?
【微信交流群】
現(xiàn)微信交流群已建立08群,人數(shù)已達(dá)數(shù)千人,歡迎關(guān)注“FPGA技術(shù)江湖”微信公眾號,可獲取進(jìn)群方式。
完
后續(xù)會持續(xù)更新,帶來Vivado、 ISE、Quartus II 、candence等安裝相關(guān)設(shè)計(jì)教程,學(xué)習(xí)資源、項(xiàng)目資源、好文推薦等,希望大俠持續(xù)關(guān)注。
江湖偌大,繼續(xù)闖蕩,愿大俠一切安好,有緣再見!
總結(jié)
以上是生活随笔為你收集整理的FPGA 之 SOPC 系列(六)Nios II 程序开发 II的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编写一个c语言程序 杨辉三角,杨辉三角
- 下一篇: delphi 获取硬盘序列号、cpu号、