zoukankan      html  css  js  c++  java
  • 79.ZYNQ内部私有定时器中断

    上篇文章实现了了PS接受来自PL的中断,本片文章将在ZYNQ的纯PS里实现私有定时器中断。每个一秒中断一次,在中断函数里计数加1,通过串口打印输出。

    *本文所使用的开发板是Miz702(兼容zedboard) 
    PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2*

    中断原理

    中断对于保证任务的实时性非常必要,在ZYNQ里集成了中断控制器GIC(Generic Interrupt Controller).GIC可以接受I/O外设中断IOP和PL中断,将这些中断发给CPU。 
    中断体系结构框图图下: 
    这里写图片描述

    软件中断(SGI)

    SGI通过写ICDSGIR寄存器产生SGI.

    共享中断SPI

    通过PS和PL内各种I/O和存储器控制器产生。

    私有中断(PPI)

    包含:全局定时器,私有看门狗定时器,私有定时器以及来自PL的FIQ/IRQ。本文主要介绍PPI,其它的请参考官方手册ug585_Zynq_7000_TRM.pdf。 
    ZYNQ每个CPU链接5个私有外设中断,所有中断的触发类型都是固定不变的。并且来自PL的快速中断信号FIQ和中断信号IRQ反向,然后送到中断控制器因此尽管在ICDICFR1寄存器内反应的他们是低电平触发,但是PS-PL接口中为高电平触发。如图所示: 
    这里写图片描述

    私有定时器

    zynq中每个ARM core都有自己的私有定时器,私有定时器的工作频率为CPU的一半,比如Miz702或者zedboard的ARM工作频率为666MHZ,则私有定时器的频率为333MHz. 
    私有定时器的特性如下: 
    (1)32为计数器,达到零时产生一个中断 
    (2)8位预分频计数器,可以更好的控制中断周期 
    (3)可配置一次性或者自动重加载模式 
    (4)定时器时间可以通过下式计算: 
    定时时间 = [(预分频器的值 + 1) (加载值 + 1)]/定时器频率

    搭建硬件系统工程:

    配置ZYNQ PS

    把ZYNQ配置为只保留UART1,然后点击OK如图所示 
    这里写图片描述
    点击Run Connection Automation,取消掉Apply Board Preset,如图 
    这里写图片描述
    最终的框图很简洁,如图: 
    这里写图片描述

    建立软件工程

    建立一个Hello World工程 
    把Helloworld.c的代码修改如下:

     1 #include <stdio.h>
     2 #include "platform.h"
     3 #include "xadcps.h"
     4 
     5 #include "xil_types.h"
     6 #include "Xscugic.h"
     7 #include "Xil_exception.h"
     8 #include "xscutimer.h"
     9 
    10 //timer info
    11 #define TIMER_DEVICE_ID     XPAR_XSCUTIMER_0_DEVICE_ID
    12 #define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID
    13 #define TIMER_IRPT_INTR     XPAR_SCUTIMER_INTR
    14 
    15 //#define TIMER_LOAD_VALUE  0x0FFFFFFF
    16 #define TIMER_LOAD_VALUE    0x13D92D3F
    17 
    18 static XAdcPs  XADCMonInst; //XADC
    19 static XScuGic Intc; //GIC
    20 static XScuTimer Timer;//timer
    21 
    22 static void SetupInterruptSystem(XScuGic *GicInstancePtr,
    23         XScuTimer *TimerInstancePtr, u16 TimerIntrId);
    24 
    25 static void TimerIntrHandler(void *CallBackRef);
    26 
    27 int main()
    28 {
    29      XScuTimer_Config *TMRConfigPtr;     //timer config
    30      printf("------------START-------------
    ");
    31      init_platform();
    32      //
    33      //私有定时器初始化
    34      TMRConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
    35      XScuTimer_CfgInitialize(&Timer, TMRConfigPtr,TMRConfigPtr->BaseAddr);
    36      XScuTimer_SelfTest(&Timer);
    37      //加载计数周期,私有定时器的时钟为CPU的一般,为333MHZ,如果计数1S,加载值为1sx(333x1000x1000)(1/s)-1=0x13D92D3F
    38      XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);
    39      //自动装载
    40      XScuTimer_EnableAutoReload(&Timer);
    41      //启动定时器
    42      XScuTimer_Start(&Timer);
    43 
    44 
    45      //set up the interrupts
    46      SetupInterruptSystem(&Intc,&Timer,TIMER_IRPT_INTR);
    47 
    48      while(1){
    49      }
    50 
    51      return 0;
    52 }
    53 
    54 void SetupInterruptSystem(XScuGic *GicInstancePtr,
    55         XScuTimer *TimerInstancePtr, u16 TimerIntrId)
    56 {
    57 
    58         XScuGic_Config *IntcConfig; //GIC config
    59         Xil_ExceptionInit();
    60         //initialise the GIC
    61         IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
    62         XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
    63                         IntcConfig->CpuBaseAddress);
    64         //connect to the hardware
    65         Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    66                     (Xil_ExceptionHandler)XScuGic_InterruptHandler,
    67                     GicInstancePtr);
    68         //set up the timer interrupt
    69         XScuGic_Connect(GicInstancePtr, TimerIntrId,
    70                         (Xil_ExceptionHandler)TimerIntrHandler,
    71                         (void *)TimerInstancePtr);
    72         //enable the interrupt for the Timer at GIC
    73         XScuGic_Enable(GicInstancePtr, TimerIntrId);
    74         //enable interrupt on the timer
    75         XScuTimer_EnableInterrupt(TimerInstancePtr);
    76         // Enable interrupts in the Processor.
    77         Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
    78     }
    79 
    80 static void TimerIntrHandler(void *CallBackRef)
    81 {
    82 
    83     static int sec = 0;   //计数
    84     XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
    85     XScuTimer_ClearInterruptStatus(TimerInstancePtr);
    86     sec++;
    87     printf(" %d Second
    
    ",sec);  //每秒打印输出一次
    88 
    89 }

    上电测试

    可以看到串口终端每秒输出一次,并且值加1递增

  • 相关阅读:
    fedora 24 使用扇贝网页版没有声音
    Fedora 23安装 NS2 (network simulator 2)
    如何扩大LVM 逻辑分区的大小?
    code::blocks编译出错
    Fedora 23 忘记root密码
    u盘安装Fedora23
    Derived 派生类
    移动点的坐标
    进栈 出栈
    C和C++语言&
  • 原文地址:https://www.cnblogs.com/geekite/p/5572582.html
Copyright © 2011-2022 走看看