【ZYNQ】ZYNQ7000 私有定时器及其驱动应用示例

简介: 【ZYNQ】ZYNQ7000 私有定时器及其驱动应用示例

定时器简介

ZYNQ 嵌入式系统中,定时器的资源是非常丰富的,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器和 32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器(GT)。


系统框图

私有定时器

特点
  • 32 位计数器,当计数器递减至 0 时产生中断
  • 8 位预分频计数器,可以更好的控制中断周期
  • 可以配置单次定时或者自动重载模式
  • 通过配置起始计数值来设置定时时间
时钟
  • 私有定时器时钟为 CPU 频率(CPU_3x2x)的一半,如 ARM 的工作时钟频率为 666.666Mhz,则私有定时器的时钟频率为 333.333Mhz。
寄存器表

驱动示例

  • timer.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "timer.h"

int TimerInit(XScuTimer *TimerInstancePtr, uint16_t TimerDeviceId, 
                            uint32_t TimerLoadValue)
{
    int Status;
    XScuTimer_Config *ConfigPtr;

    ConfigPtr = XScuTimer_LookupConfig(TimerDeviceId);

    Status = XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr,
                    ConfigPtr->BaseAddr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    Status = XScuTimer_SelfTest(TimerInstancePtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    XScuTimer_EnableAutoReload(TimerInstancePtr);

    XScuTimer_LoadTimer(TimerInstancePtr, TimerLoadValue);

    return Status;
}

int TimerIntrInit(XScuGic *IntcInstancePtr, XScuTimer *TimerInstancePtr, 
        uint32_t TimerIntrId, void(* CallBack)(void *))
{
    int Status;

    XScuGic_Config *IntcConfig;

    IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
    if (NULL == IntcConfig) {
        return XST_FAILURE;
    }

    Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
                    IntcConfig->CpuBaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    Xil_ExceptionInit();

    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
            (Xil_ExceptionHandler)XScuGic_InterruptHandler,
            IntcInstancePtr);

    Xil_ExceptionEnable();

    Status = XScuGic_Connect(IntcInstancePtr, TimerIntrId,
          (Xil_ExceptionHandler)CallBack, (void *)TimerInstancePtr);
    if (Status != XST_SUCCESS) {
        return Status;
    }

    XScuGic_Enable(IntcInstancePtr, TimerIntrId);

    XScuTimer_EnableInterrupt(TimerInstancePtr);

    return XST_SUCCESS;
}


  • timer.h
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __TIMER_H__
#define __TIMER_H__

#include "xscutimer.h"
#include "xscugic.h"

/* CPU时钟频率 */
#ifndef CPU_CLK_FREQ_HZ
#define CPU_CLK_FREQ_HZ     XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ
#endif

/* 私有定时器的时钟频率 = CPU时钟频率/2 = 333MHz */
#define TIMER_HZ            CPU_CLK_FREQ_HZ/2

#ifndef INTC_DEVICE_ID
#define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID
#endif

#define TIMER_DEVICE_ID     XPAR_XSCUTIMER_0_DEVICE_ID
#define TIMER_IRPT_INTR     XPAR_SCUTIMER_INTR

/*
 * Function declaration
 */
int TimerInit(XScuTimer *TimerInstancePtr, uint16_t TimerDeviceId, 
                            uint32_t TimerLoadValue);
int TimerIntrInit(XScuGic *IntcInstancePtr, XScuTimer *TimerInstancePtr, 
        uint32_t TimerIntrId, void(* CallBack)(void *));

#endif

应用示例

  • app_timer.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "app_timer.h"

#define USING_ULOG
#include "ulog.h"

extern XScuGic IntcInstPtr;

/**
 * @brief 定时器中断处理,中断时间 50ms
 */
void TimerIntrHandler(void *CallBackRef)
{
    XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
    struct timer_flag *_timer_flag = &g_timer_flag;
    static uint16_t count = 0;
    
    /* 标志位触发 */
//  XScuTimer_IsExpired(TimerInstancePtr);
    ULOG("--- timer handle --- \r\n");

    count++;

    if(count == 101)
    {
        count = 0;
    }

    ULOG("count: %d\r\n", count);

    _timer_flag->timer_flag_50ms = 1;

    if(count % 10 == 0)
    {
        _timer_flag->timer_flag_500ms = 1;
        ULOG("--- 500 MS --- \r\n");

    }
    if(count % 20 == 0)
    {
        _timer_flag->timer_flag_1s = 1;
        ULOG("---  1 S --- \r\n");
    }

    XScuTimer_ClearInterruptStatus(TimerInstancePtr);
    /* 关闭自动重装载值 关闭中断 */
    // XScuTimer_DisableAutoReload(TimerInstancePtr);
}

int app_timer_init(void)
{
    int Status;

    Status = TimerInit(&Timer, TIMER_DEVICE_ID, TIMER_LOAD_VALUE);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    Status = TimerIntrInit(&IntcInstPtr, &Timer, TIMER_IRPT_INTR, TimerIntrHandler);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    XScuTimer_Start(&Timer);

    return Status;
}
  • app_timer.h
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __APP_TIMER_H__
#define __APP_TIMER_H__

#include "timer.h"

/* CPU时钟频率 */
#ifndef CPU_CLK_FREQ_HZ
#define CPU_CLK_FREQ_HZ   XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ
#endif

/* 私有定时器的时钟频率 = CPU时钟频率/2 = 333MHz */
#define TIMER_HZ      CPU_CLK_FREQ_HZ/2

/*
 * 精确计算 装载值 = 定时时间(单位:秒)* 333333333
 * 0.5s 166,666,666.5 0x9EF21AA
 * 0.1s  333,333,33.3 0x1FCA055
 * 0.05s 16,666,666,65 0xFE502A
 */
#define TIMER_LOAD_VALUE 0xFE502A

XScuTimer Timer;

struct timer_flag
{
    char timer_flag_50ms;
    char timer_flag_500ms;
    char timer_flag_1s;
};

typedef struct timer_flag timer_flag_t;

timer_flag_t g_timer_flag;

int app_timer_init(void);

#endif


测试平台:黑金 AC7Z035B

芯片型号:XC7Z035-2FFG676

参考来源:UG585



相关文章
|
5月前
stm32f407探索者开发板(九)——寄存器地址名称映射
stm32f407探索者开发板(九)——寄存器地址名称映射
|
7月前
|
安全 测试技术
【ZYNQ】ZYNQ7000 全局定时器及其驱动示例
【ZYNQ】ZYNQ7000 全局定时器及其驱动示例
188 0
|
7月前
|
传感器 开发工具 芯片
【ZYNQ】ZYNQ7000 XADC 及其驱动示例
【ZYNQ】ZYNQ7000 XADC 及其驱动示例
195 0
|
7月前
|
测试技术 Perl
【ZYNQ】ZYNQ7000 UART 控制器及驱动应用示例
【ZYNQ】ZYNQ7000 UART 控制器及驱动应用示例
300 0
|
7月前
|
Perl
【ZYNQ】IIC 简介及 EMIO 模拟 IIC 驱动示例
【ZYNQ】IIC 简介及 EMIO 模拟 IIC 驱动示例
296 0
LED模板驱动程序的改造:总线设备驱动模型
LED模板驱动程序的改造:总线设备驱动模型
116 0
|
XML 传感器 芯片
可编程 USB 转串口适配器开发板可编程的含义
可编程USB转UART/I2C/SMBusS/SPI/CAN/1-Wire适配器USB2S(USB To Serial ports)是多种数字接口物理层协议转发器,广泛应用于电子设备开发测试、工业数字接口转换、数字接口学习验证等领域。
可编程 USB 转串口适配器开发板参数设置
前述各种指令在参数修改完成后仅可当时生效,修改后的参数断电不保存。使用[SAVE]关键字可将当前参数保存至 EEPROM,使参数永久保存。
可编程 USB 转串口适配器开发板参数设置
|
XML 传感器 数据格式
可编程 USB 转串口适配器开发板主要开发测试作用
上面写的东西不少,其实这个模块用法特别简单,拿到套件和专门的工具软件后一分钟都不需要就完全明白了,如果想编写自己的xml驱动,随便打开一个照葫芦画瓢,然后另存就行。