ポイントはXTC_CSR_ENABLE_PWM_MASKとXTC_CSR_EXT_GENERATE_MASKを入れてやること
(後者に気づかずにハマった)
PWMがONになる立ち上がりとOFFになる立ち下がりでハンドラが呼ばれる
どちらのエッジかを検出するステータスフラグを用意してやれば、COMPA_vectとOVF_vectのような割込ハンドラが実装できそう
#include <stdio.h> #include "platform.h" #include "xil_types.h" #include "xtmrctr.h" #include "xparameters.h" #include "xil_io.h" #include "xil_exception.h" #include "xscugic.h" #include <stdbool.h> #define XTC_CSR_ENABLE_PWM_MASK 0x00000200 #define XTC_CSR_EXT_GENERATE_MASK 0x00000004 XScuGic InterruptController; /* Instance of the Interrupt Controller */ static XScuGic_Config *GicConfig;/* The configuration parameters of the controller */ void Timer_InterruptHandler(void *data, u8 TmrCtrNumber) { print(" Interrupt acknowledged\n\r"); } void Timer_InterruptHandler2(void *data, u8 TmrCtrNumber) { print(" Interrupt 2 acknowledged\n\r"); } int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr) { Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, XScuGicInstancePtr); Xil_ExceptionEnable(); return XST_SUCCESS; } int ScuGicInterrupt_Init(u16 DeviceId,XTmrCtr *TimerInstancePtr, XTmrCtr *TimerInstancePtr2) { int Status; GicConfig = XScuGic_LookupConfig(DeviceId); if (NULL == GicConfig) { return XST_FAILURE; } Status = XScuGic_CfgInitialize(&InterruptController, GicConfig, GicConfig->CpuBaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = SetUpInterruptSystem(&InterruptController); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = XScuGic_Connect(&InterruptController, 61U, (Xil_ExceptionHandler)XTmrCtr_InterruptHandler, (void *)TimerInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } XScuGic_Enable(&InterruptController, 61U); return XST_SUCCESS; } int main() { XTmrCtr TimerInstancePtr; XTmrCtr TimerInstancePtr2; int xStatus; print("##### Application Starts #####\n\r"); print("\r\n"); xStatus = XTmrCtr_Initialize(&TimerInstancePtr,XPAR_AXI_TIMER_0_DEVICE_ID); if(XST_SUCCESS != xStatus) print("TIMER INIT FAILED \n\r"); xStatus = XTmrCtr_Initialize(&TimerInstancePtr2,XPAR_AXI_TIMER_0_DEVICE_ID); if(XST_SUCCESS != xStatus) print("TIMER INIT FAILED \n\r"); XTmrCtr_SetHandler(&TimerInstancePtr, Timer_InterruptHandler, &TimerInstancePtr); XTmrCtr_SetHandler(&TimerInstancePtr2, Timer_InterruptHandler2, &TimerInstancePtr2); //enable interrupt & auto reload XTmrCtr_SetOptions(&TimerInstancePtr, 0, (XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION)); u32 CounterControlReg = Xil_In32(TimerInstancePtr.BaseAddress + XTmrCtr_Offsets[0] + XTC_TCSR_OFFSET); CounterControlReg = CounterControlReg | XTC_CSR_ENABLE_PWM_MASK | XTC_CSR_EXT_GENERATE_MASK; Xil_Out32(TimerInstancePtr.BaseAddress + XTmrCtr_Offsets[0] + XTC_TCSR_OFFSET, CounterControlReg); XTmrCtr_SetOptions(&TimerInstancePtr2, 1, (XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION)); CounterControlReg = Xil_In32(TimerInstancePtr2.BaseAddress + XTmrCtr_Offsets[1] + XTC_TCSR_OFFSET); CounterControlReg = CounterControlReg | XTC_CSR_ENABLE_PWM_MASK | XTC_CSR_EXT_GENERATE_MASK; Xil_Out32(TimerInstancePtr2.BaseAddress + XTmrCtr_Offsets[1] + XTC_TCSR_OFFSET, CounterControlReg); XTmrCtr_SetResetValue(&TimerInstancePtr, 0, //Change with generic value 0x5f5e100); XTmrCtr_SetResetValue(&TimerInstancePtr2, 1, //Change with generic value 0x1f78a40); xStatus=ScuGicInterrupt_Init(XPAR_PS7_SCUGIC_0_DEVICE_ID,&TimerInstancePtr,&TimerInstancePtr2); if(XST_SUCCESS != xStatus) print(" :( SCUGIC INIT FAILED \n\r"); XTmrCtr_Start(&TimerInstancePtr,0); print("timer start \n\r"); XTmrCtr_Start(&TimerInstancePtr2,1); print("timer 2 start \n\r"); print("Wait for the Timer interrupt to tigger \r\n"); print("########################################\r\n"); print(" \r\n"); while(1) { } cleanup_platform(); return 0; }