上篇文章實現了了PS接受來自PL的中斷,本片文章將在ZYNQ的純PS裏實現私有定時器中斷。每隔一秒中斷一次,在中斷函數裏計數加1,經過串口打印輸出。php
本文所使用的開發板是Miz702 PC 開發環境版本:Vivado 2015.4 Xilinx SDK 2015.4c++
中斷對於保證任務的實時性很是必要,在ZYNQ裏集成了中斷控制器GIC(Generic Interrupt Controller).GIC能夠接受I/O外設中斷IOP和PL中斷,將這些中斷髮給CPU。
中斷體系結構框圖圖下: app
SGI經過寫ICDSGIR寄存器產生SGI.函數
經過PS和PL內各類I/O和存儲器控制器產生。測試
包含:全局定時器,私有看門狗定時器,私有定時器以及來自PL的FIQ/IRQ。本文主要介紹PPI,其它的請參考官方手冊ug585_Zynq_7000_TRM.pdf。
ZYNQ每一個CPU連接5個私有外設中斷,全部中斷的觸發類型都是固定不變的。而且來自PL的快速中斷信號FIQ和中斷信號IRQ反向,而後送到中斷控制器所以儘管在ICDICFR1寄存器內反應的他們是低電平觸發,可是PS-PL接口中爲高電平觸發。如圖所示: this
zynq中每一個ARM core都有本身的私有定時器,私有定時器的工做頻率爲CPU的一半,好比Miz702的ARM工做頻率爲666MHZ,則私有定時器的頻率爲333MHz.
私有定時器的特性以下:
(1)32位計數器,達到零時產生一箇中斷
(2)8位預分頻計數器,能夠更好的控制中斷週期
(3)可配置一次性或者自動重加載模式
(4)定時器時間能夠經過下式計算:
定時時間 = [(預分頻器的值 + 1) (加載值 + 1)]/定時器頻率3d
Step1:新建一個名爲爲Miz702_sys的工程orm
Step2:選擇RTL Project 勾選Do not specify source at this time視頻
Step3:因爲Miz702兼容zedboard 所以選擇zedboard開發包blog
Step4:單擊Finish
Step1:單擊Create Block Design
Step2:輸入system
Step4:搜素單詞z選擇ZYNQ7 Processing System,而後雙擊
Step5:添加進來了ZYNQ CPU IP,而後單擊Run Block Automation
Step6:直接單擊OK
Step7:在你點擊了OK後,你會發現DDR以及FICED_IO自勱的延伸出來。
Step8:連線的做用就是把PS的時鐘能夠接入PL部分,固然這裏咱們暫時用不到PL部分的資源。在Block文件中,咱們進行連線,將鼠標放在引腳處,鼠標變成鉛筆後迚行拖拽,連線以下圖所示:
Step9: 右擊 system.bd, 單擊Generate Output Products
Step10:支部操做會產生執行、仿真、綜合的文件
Step11:右擊system.bd 選擇 Create HDL Wrapper 這步的做用是產生頂層的HDL文件
Step12:選擇Leave Let Vivado manager wrapper and auto-update 而後單擊OK
Step1:File->Export->Export Hardware
Step2:勾選Include bitstream 直接單擊OK
Step3:File->Launch SDK加載到SDK
Step4:單擊OK
創建一個TIMER_INTC空的工程,而且添加main.c 添加以下代碼
#include <stdio.h> #include "xadcps.h" #include "xil_types.h" #include "Xscugic.h" #include "Xil_exception.h" #include "xscutimer.h" //timer info #define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR //#define TIMER_LOAD_VALUE 0x0FFFFFFF #define TIMER_LOAD_VALUE 0x13D92D3F //static XAdcPs XADCMonInst; //XADC static XScuGic Intc; //GIC static XScuTimer Timer;//timer static void SetupInterruptSystem(XScuGic *GicInstancePtr, XScuTimer *TimerInstancePtr, u16 TimerIntrId); static void TimerIntrHandler(void *CallBackRef); int main() { XScuTimer_Config *TMRConfigPtr; //timer config printf("------------START-------------\n"); // init_platform(); // //私有定時器初始化 TMRConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID); XScuTimer_CfgInitialize(&Timer, TMRConfigPtr,TMRConfigPtr->BaseAddr); XScuTimer_SelfTest(&Timer); //加載計數週期,私有定時器的時鐘爲CPU的通常,爲333MHZ,若是計數1S,加載值爲1sx(333x1000x1000)(1/s)-1=0x13D92D3F XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE); //自動裝載 XScuTimer_EnableAutoReload(&Timer); //啓動定時器 XScuTimer_Start(&Timer); //set up the interrupts SetupInterruptSystem(&Intc,&Timer,TIMER_IRPT_INTR); while(1){ } return 0; } void SetupInterruptSystem(XScuGic *GicInstancePtr, XScuTimer *TimerInstancePtr, u16 TimerIntrId) { XScuGic_Config *IntcConfig; //GIC config Xil_ExceptionInit(); //initialise the GIC IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); XScuGic_CfgInitialize(GicInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); //connect to the hardware Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, GicInstancePtr); //set up the timer interrupt XScuGic_Connect(GicInstancePtr, TimerIntrId, (Xil_ExceptionHandler)TimerIntrHandler, (void *)TimerInstancePtr); //enable the interrupt for the Timer at GIC XScuGic_Enable(GicInstancePtr, TimerIntrId); //enable interrupt on the timer XScuTimer_EnableInterrupt(TimerInstancePtr); // Enable interrupts in the Processor. Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); } static void TimerIntrHandler(void *CallBackRef) { static int sec = 0; //計數 XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef; XScuTimer_ClearInterruptStatus(TimerInstancePtr); sec++; printf(" %d Second\n\r",sec); //每秒打印輸出一次 } |
能夠看到串口終端每秒輸出一次,而且值加1遞增。
中斷對於實時系統是很是重要的,能夠說是是實時性的保障吧。本章簡要介紹了ZYNQ的中斷原理和中斷類型,詳細介紹了私有定時器,創建了完整的工程進行測試。
官網論壇:www.osrc.cn
視頻連接:http://www.osrc.cn/forum.php?mod=viewthread&tid=1104
源碼連接:http://pan.baidu.com/s/1bAstrC 密碼:wv3i