• 第十三章 ZYNQ-MIZ701 TIMER定时器中断


     

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

    本文所使用的开发板是Miz701 PC 开发环境版本:Vivado 2015.4 Xilinx SDK 2015.4

    13.0本章难度系数★★☆☆☆☆☆

    13.1中断原理

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

    13.1.1软件中断(SGI)

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

    13.1.2共享中断SPI

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

    13.1.3私有中断(PPI)

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

    13.1.4私有定时器

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

    13.2 搭建硬件工程

    Step1:新建一个名为为Miz701_sys的工程

    wpsC417.tmp

    Step2:选择RTL Project 勾选Do not specify source at this time

    wpsC427.tmp

    Step3:选择xc7z010clg400-1作为开发器件。

    wpsC428.tmp

    Step4:单击Finish

    wpsC429.tmp

    13.3使用IP Integrator创建硬件系统

    Step1:单击Create Block Design

    Step2:输入system

    wpsC42A.tmp

    Step3:单击下图中wpsC42B.tmp添加IP按钮

    wpsC43C.tmp

    Step4:搜素单词z选择ZYNQ7 Processing System,然后双击

    wpsC43D.tmp

    Step5:添加进来了ZYNQ CPU IP,然后单击双击对其进行配置。

    wpsC43E.tmp

    Step6:修改输入频率为50MHZ,PL端频率为100MHZ。

    wpsC43F.tmp

    Step7:修改内存类型为MT41K256M16 RE-125。

    wpsC440.tmp

    Step8:在Mio configuration选项中,勾选添加UART1接口,单击OK完成配置。

    wpsC451.tmp

    Step9:单击Run Block Automation进行智能布线。

    wpsC452.tmp

    Step10:直接单击OK

    wpsC453.tmp

    Step11:在你点击了OK后,你会发现DDR以及FICED_IO自动的延伸出来。

    wpsC454.tmp

    Step12:连线的作用就是把PS的时钟可以接入PL部分,当然这里我们暂时用不到PL部分的资源。在Block文件中,我们进行连线,将鼠标放在引脚处,鼠标变成铅笔后迚行拖拽,连线如下图所示:

    wpsC455.tmp

    Step13: 右击 system.bd, 单击Generate Output Products

    wpsC465.tmp

    Step14:支部操作会产生执行、仿真、综合的文件

    wpsC466.tmp

    Step15:右击system.bd 选择 Create HDL Wrapper 这步的作用是产生顶层的HDL文件

    wpsC467.tmp

    Step16:选择Leave Let Vivado manager wrapper and auto-update 然后单击OK

    Step17:执行->产生bit文件wpsC468.tmp

    13.4导出SOC硬件到SDK

    Step1:File->Export->Export Hardware

    wpsC469.tmp

    Step2:勾选Include bitstream 直接单击OK

    wpsC47A.tmp

    Step3:File->Launch SDK加载到SDK

    wpsC47B.tmp

    Step4:单击OK

    wpsC47C.tmp

    13.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------------- ");

       //  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 ",sec);  //每秒打印输出一次

    }

    13.6测试结果

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

    13.7本章小结

    中断对于实时系统是非常重要的,可以说是是实时性的保障吧。本章简要介绍了ZYNQ的中断原理和中断类型,详细介绍了私有定时器,建立了完整的工程进行测试。

    淘宝店铺:https://osrc.taobao.com

    官网论坛:www.osrc.cn

    源码链接:http://pan.baidu.com/s/1skC582T 密码:eyhp

  • 相关阅读:
    Docker学习笔记
    SpringMVC学习笔记
    机器学习预测2022年考研成绩、考研分数线
    代码随想录贪心算法
    给定两个序列src,dst,src为入栈顺序,判断dst是否为src的一个出栈顺序(c++)
    代码随想录回溯算法
    代码随想录动态规划
    代码随想录二叉树
    Docker安装memcached
    OpenEuler镜像配置
  • 原文地址:https://www.cnblogs.com/milinker/p/5905938.html
Copyright © 2020-2023  润新知