?版本:Vivado2020.2(Vitis)
任務:使用定時器 (私有定時器) 中斷 實現 LED(PS端) 定時1s亮滅翻轉
目錄
一、介紹
二、硬件設計
三、軟件設計
四、效果
一、介紹
????????Zynq系列是Xilinx(現為AMD)推出的集成了ARM Cortex-A9雙核處理器和FPGA的可編程SoC器件。在Zynq中,定時器是重要的外設模塊,用于時間測量、延時控制和周期性中斷觸發等。
Zynq主要有以下幾種定時器:
-
私有定時器(Private Timer)?- 每個ARM核都有一個私有定時器
-
全局定時器(Global Timer)?- 雙核共享的64位定時器
-
看門狗定時器(Watchdog Timer、WDT)?- 用于系統監控和復位
-
三重定時器計數器(TTC)?- FPGA側提供的定時器
像 PS 端延時可以用定時器中斷方式進行操作,以讓cpu執行其他重要操作。
二、硬件設計
????????ZYNQ 的配置使用到了 MIO(LED燈)、UART(用于Debug)、DDR(存儲器),跟之前的工程案例相比沒有額外的特殊配置,下面這幅圖是CPU的工作頻率,保持默認666.666MHz,定時器驅動時鐘是其二分之一,也就是333.333MHz(后面會用到)
? ? ? ? 最后整體 bd 設計部分如圖所示:設計檢查、Generate Output Products、 Create HDL Wrapper、(管腳約束、Gnerate Bitstream、(無PL端設計這兩部忽略))、Export Hardware(不用包含比特流文件)、啟動Vitis
三、軟件設計
? ? ? ? 可以打開官方提供的私有定時器的示例工程,這里可以選定時器中斷的示例工程,方便在設計時進行對照參考。
#include "xparameters.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "xscutimer.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "sleep.h"//===========================自定義宏=========================//#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID //宏定義GPIO器件ID
#define MIO_LED 7 //宏定義LED管腳(PS端LED,根據開發板設值,這里對應GPIO MIO 7)#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //宏定義中斷控制器(GIC)ID
#define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID //宏定義TIMER器件ID
#define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR //宏定義TIMER中斷號(中斷ID)#define TIMER_LOAD_VALUE 0x13DE4354 //定時器計數值(定時器驅動時鐘333.333MHz為CPU時鐘(默認666.66MHz)一半,周期約3ns,定時1s計數333_333_333 -1 次)//===========================實例化===========================//XGpioPs Gpio; //GPIO示例
XScuGic Intc; //中斷控制器實例
XScuTimer Timer; //定時器實例//=======================函數、變量聲明=======================//static void Gpio_Init(); //GPIO初始化
static void Timer_Intr_Init(); //定時器中斷初始化
static void LED_blink(); //LED閃爍測試
static void Timer_IntrHandler(void *CallBackRef); //定時器中斷處理函數
static void Setup_Intr_System(XScuGic *intr, XScuTimer *timer, u16 timer_intr_id); //建立中斷系統//===========================主函數===========================//int main()
{xil_printf("SCU Timer Interrupt Test! \r\n");Gpio_Init(); //GPIO初始化LED_blink(); //LED閃爍測試Timer_Intr_Init(); //定時器中斷初始化while(1)return 0;
}//=====================定時器中斷處理函數=====================//
// @param CallBackRef 用戶自定義回調參數(對應TIMER實例指針)void Timer_IntrHandler(void *CallBackRef)
{static int led_state = 0;//將回調參數轉為TIMER實例指針,用于操作硬件(例規范化設計)XScuTimer *TimerInstPtr = (XScuTimer *) CallBackRef;//打印Debug信息xil_printf("Interrupt Detected! \r\n");//清除定時器中斷標志位XScuTimer_ClearInterruptStatus(TimerInstPtr);//翻轉LED狀態值led_state = ~led_state;//寫數據到GPIO引腳(PS端LED)XGpioPs_WritePin(&Gpio, MIO_LED, led_state);}//=========================GPIO初始化========================//
void Gpio_Init()
{//定義器件ID(指針類型)XGpioPs_Config * ConfigPtr;//根據器件ID,查找器件配置信息ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);//初始化GPIO的驅動XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);//GPIO方向設置(0輸入/1輸出)XGpioPs_SetDirectionPin(&Gpio, MIO_LED, 1);//設置輸出使能(1使能)XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED, 1);
}//======================定時器中斷初始化======================//
void Timer_Intr_Init()
{//定義器件ID(指針類型)XScuTimer_Config *ConfigPtr;//根據器件ID,查找器件配置信息ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);//初始化定時器的驅動XScuTimer_CfgInitialize(&Timer, ConfigPtr,ConfigPtr->BaseAddr);//(可選)定時器自檢int Status = XScuTimer_SelfTest(&Timer);if (Status != XST_SUCCESS) { xil_printf("Timer Self Test Error! \r\n"); }//建立中斷系統(調用函數)Setup_Intr_System(&Intc, &Timer, TIMER_IRPT_INTR);//加載計數值(計數上限)XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);//使能自動加載模式(計完自動加載計數值,不啟用計完一次結束)XScuTimer_EnableAutoReload(&Timer);//啟動定時器XScuTimer_Start(&Timer);
}//=======================建立中斷系統=======================//
/* 建立中斷系統,UART接收到數據時產生中斷* @param intr 是指向 XScuGic驅動實例的指針* @param timer 是指向 XScuTimer驅動實例的指針* @param timer_intr_id 是TIMER中斷ID*/
void Setup_Intr_System(XScuGic *intr, XScuTimer *timer, u16 timer_intr_id)
{//定義中斷控制器配置信息(指針)XScuGic_Config * IntcConfig;//根據中斷控制器ID,查找GIC配置信息IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);//初始化中斷控制器驅動XScuGic_CfgInitialize(intr, IntcConfig, IntcConfig->CpuBaseAddress);//設置中斷異常處理功能Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler) XScuGic_InterruptHandler,(void *) intr);//使能處理器中斷Xil_ExceptionEnable();//關聯中斷處理函數XScuGic_Connect(intr, timer_intr_id,(Xil_ExceptionHandler) Timer_IntrHandler,(void *) timer);//使能GIC中的定時器中斷XScuGic_Enable(intr, timer_intr_id);//使能定時器中斷XScuTimer_EnableInterrupt(timer);
}//========================LED閃爍測試========================//
void LED_blink()
{for(int i=0; i<3; i++)//閃爍3次{//向GPIO寫1 、延時200ms、寫0、延時XGpioPs_WritePin(&Gpio, MIO_LED, 1); usleep(200000);XGpioPs_WritePin(&Gpio, MIO_LED, 0); usleep(200000);}
}
四、效果
? ? ? ? 上板后會先打印測試信息,然后LED燈快速閃爍3次(說明MIO配置無誤),此后每秒定時器會產生中斷,并將LED的狀態翻轉,效果為每兩秒閃爍一次