第十四章 ZYNQ TIMER定時器中斷

 

上篇文章實現了了PS接受來自PL的中斷,本片文章將在ZYNQ的純PS裏實現私有定時器中斷。每隔一秒中斷一次,在中斷函數裏計數加1,經過串口打印輸出。php

本文所使用的開發板是Miz702 PC 開發環境版本:Vivado 2015.4 Xilinx SDK 2015.4c++

14.0本章難度係數★★☆☆☆☆☆

14.1中斷原理

中斷對於保證任務的實時性很是必要,在ZYNQ裏集成了中斷控制器GIC(Generic Interrupt Controller).GIC能夠接受I/O外設中斷IOP和PL中斷,將這些中斷髮給CPU。 
中斷體系結構框圖圖下:
wps949F.tmpapp

14.1.1軟件中斷(SGI)

SGI經過寫ICDSGIR寄存器產生SGI.函數

14.1.2共享中斷SPI

經過PS和PL內各類I/O和存儲器控制器產生。測試

14.1.3私有中斷(PPI)

包含:全局定時器,私有看門狗定時器,私有定時器以及來自PL的FIQ/IRQ。本文主要介紹PPI,其它的請參考官方手冊ug585_Zynq_7000_TRM.pdf。 
ZYNQ每一個CPU連接5個私有外設中斷,全部中斷的觸發類型都是固定不變的。而且來自PL的快速中斷信號FIQ和中斷信號IRQ反向,而後送到中斷控制器所以儘管在ICDICFR1寄存器內反應的他們是低電平觸發,可是PS-PL接口中爲高電平觸發。如圖所示: 
wps94A0.tmpthis

14.1.4私有定時器

zynq中每一個ARM core都有本身的私有定時器,私有定時器的工做頻率爲CPU的一半,好比Miz702的ARM工做頻率爲666MHZ,則私有定時器的頻率爲333MHz. 
私有定時器的特性以下:
(1)32位計數器,達到零時產生一箇中斷 
(2)8位預分頻計數器,能夠更好的控制中斷週期 
(3)可配置一次性或者自動重加載模式 
(4)定時器時間能夠經過下式計算: 
定時時間 = [(預分頻器的值 + 1) (加載值 + 1)]/定時器頻率3d

14.2 搭建硬件工程

Step1:新建一個名爲爲Miz702_sys的工程orm

wps94A1.tmp

Step2:選擇RTL Project 勾選Do not specify source at this time視頻

wps94B2.tmp

Step3:因爲Miz702兼容zedboard 所以選擇zedboard開發包blog

wps94B3.tmp

Step4:單擊Finish

wps94B4.tmp

14.3使用IP Integrator建立硬件系統

Step1:單擊Create Block Design

Step2:輸入system

wps94B5.tmp

Step3:單擊下圖中wps94C5.tmp添加IP按鈕

wps94C6.tmp

Step4:搜素單詞z選擇ZYNQ7 Processing System,而後雙擊

wps94C7.tmp

Step5:添加進來了ZYNQ CPU IP,而後單擊Run Block Automation

wps94C8.tmp

Step6:直接單擊OK

wps94D9.tmp

Step7:在你點擊了OK後,你會發現DDR以及FICED_IO自勱的延伸出來。

wps94DA.tmp

Step8:連線的做用就是把PS的時鐘能夠接入PL部分,固然這裏咱們暫時用不到PL部分的資源。在Block文件中,咱們進行連線,將鼠標放在引腳處,鼠標變成鉛筆後迚行拖拽,連線以下圖所示:

wps94DB.tmp

Step9: 右擊 system.bd, 單擊Generate Output Products

wps94DC.tmp

Step10:支部操做會產生執行、仿真、綜合的文件

wps94EC.tmp

Step11:右擊system.bd 選擇 Create HDL Wrapper 這步的做用是產生頂層的HDL文件

wps94ED.tmp

Step12:選擇Leave Let Vivado manager wrapper and auto-update 而後單擊OK

Step13:執行->產生bit文件wps94EE.tmp

14.4導出SOC硬件到SDK

Step1:File->Export->Export Hardware

wps94EF.tmp

Step2:勾選Include bitstream 直接單擊OK

wps9500.tmp

Step3:File->Launch SDK加載到SDK

wps9501.tmp

Step4:單擊OK

wps9502.tmp

14.5 創建軟件工程

創建一個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);  //每秒打印輸出一次

}

14.6測試結果

能夠看到串口終端每秒輸出一次,而且值加1遞增。

14.7本章小結

中斷對於實時系統是很是重要的,能夠說是是實時性的保障吧。本章簡要介紹了ZYNQ的中斷原理和中斷類型,詳細介紹了私有定時器,創建了完整的工程進行測試。

淘寶店鋪:https://osrc.taobao.com

官網論壇:www.osrc.cn

視頻連接:http://www.osrc.cn/forum.php?mod=viewthread&tid=1104

源碼連接:http://pan.baidu.com/s/1bAstrC 密碼:wv3i

相關文章
相關標籤/搜索