• ZYNQ之定时器


    一、定时器简介

    定时器作为 PS 的重要组成部分,可以不受 CPU 的干预,自己独立运行,来完成计时、定时、中断以及计算来自 MIO 或 EMIO 引脚的信号脉冲宽度。

    ZYNQ 嵌入式系统中,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器( GT)。PS 中还有一个 24 位的系统看门狗定时器( SWDT)和两个 TTC( Triple Timer Counters)

    系统看门狗定时器可以在系统发生灾难性的故障时(如 PS 中的 PLL 工作异常)发出信号, 使得系统程序重新启动,保证了系统安全可靠的运行。SWDT可以工作在CPU频率的1/4或1/6(CPU_1x),也可以工作在设备外部或PL提供的时钟下,并向它们输出一个复位信号。

    TTC 用于计算来自 MIO 引脚或 EMIO 引脚的信号脉冲宽度,每个 TTC 都有三个独立的计数器。TTC只能工作在CPU频率的1/4或1/6(CPU_1x)

    定时器的系统框如下图

     图中的定时器连接到中断控制器( Interrupt Controller),可以很方便的使用定时器来完成定时器中断的实验。其中私有定时器( CPU Private Timer)是最为常用的。

    私有定时器的时钟频率为 CPU 时钟频率的一半。如 ARM 的工作时钟频率为 666.666Mhz,则私有定时器的时钟频率为 333.333Mhz。

    私有定时器的特性

    ①32 位计数器,当计数器递减至 0 后产生中断
    ②8 位预分频计数器,可以更好的控制中断周期

    ③可以配置单次定时或者自动重载模式
    ④通过配置起始计数值来设置定时时间

     二、定时器编程

    由于 ARM 处理器自带了私有定时器,所以在定时器方面搭建嵌入式系统时,不需要额外添加定时器,除非使用其他定时器

    定时器初始化

    1. int Status;
    2. //私有定时器初始化
    3. XScuTimer_Config *timer_cfg_ptr;
    4. timer_cfg_ptr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
    5. if (timer_cfg_ptr == NULL)
    6. {
    7. return XST_FAILURE;
    8. }
    9. Status = XScuTimer_CfgInitialize(&Timer, timer_cfg_ptr,timer_cfg_ptr->BaseAddr);
    10. if (Status != XST_SUCCESS) //判断是否初始化成功
    11. {
    12. return XST_FAILURE;
    13. }
    14. XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE); // 加载计数周期
    15. XScuTimer_EnableAutoReload(&Timer); // 设置自动装载模式

    主要是初始化私有定时器和设置自动重装值(定时器溢出时间)以及模式 。

    定时时间计算:

    私有定时器的时钟频率为CPU频率的一半,这里ZYNQ默认工作频率650Mhz,则私有定时器的时钟频率为325Mhz,若定时时间为 T,则写入重装值为 :T /  (1 /325Mhz ) 。 

    一般使用定时器基本上都有使用中断,所以还需要初始化定时器相关中断

    1. //初始化中断控制器
    2. XScuGic_Config *gic_cfg; //中断控制器配置信息
    3. gic_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
    4. if (gic_cfg == NULL)
    5. {
    6. return XST_FAILURE;
    7. }
    8. Status = XScuGic_CfgInitialize(&Intc,gic_cfg,gic_cfg->CpuBaseAddress);
    9. if (Status != XST_SUCCESS) //判断是否初始化成功
    10. {
    11. return XST_FAILURE;
    12. }
    13. //初始化异常处理
    14. Xil_ExceptionInit();
    15. //CPU中断异常注册
    16. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&Intc);
    17. //使能处理器中断
    18. Xil_ExceptionEnable();;
    19. //设置定时器中断: timer_intr_handler 中断处理函数
    20. XScuGic_Connect(&Intc, TIMER_IRPT_INTR,(Xil_ExceptionHandler)timer_intr_handler, &Timer);
    21. XScuGic_Enable(&Intc,TIMER_IRPT_INTR);//使能 GIC 中的定时器中断
    22. XScuTimer_EnableInterrupt(&Timer); //使能定时器中断

    注意:定时器初始化一定要放在中断初始化的前面。

    中断的初始化基本上都是固定的套路。这里设置中断函数为timer_intr_handler()

    1. void timer_intr_handler(void *CallBackRef)
    2. {
    3. XScuTimer *timer_ptr = (XScuTimer *) CallBackRef;
    4. ....
    5. //清除定时器中断标志
    6. XScuTimer_ClearInterruptStatus(timer_ptr);
    7. }

     


     

  • 相关阅读:
    insightface实战:画出嘴巴和眼睛的mask
    【CSS】H5_css美化
    Mavenir融合分组核心解决方案将为德国电信在德国的5G独立组网(SA)网络提供支持
    spring---第五篇
    Java-IO流学习
    python-0009-django对数据的增删改
    「直播回放」电子会计档案管理,让数字化成果深度利用、可查可验
    VEX —— Quaternion|Euler Angle
    匿名类为什么不可以使用非final变量
    python多线程获取返回值
  • 原文地址:https://blog.csdn.net/qq_53144843/article/details/126799903