Shared Peripheral Interrupts (SPI)
SPI 可以接收来自PL的中断,这里使用PL模块 AXI Timer 的中断模式,并连接到CPU。
AXI TIMER
定时器,内部有两个完全相同的TIMER模块。
特性:
在手册里可以找到详细的参数和寄存器信息。
硬件系统
需要zynq核和一个AXI Timer,PL的clock可以在zynq核内部设置。
软件部分
这里会使用到xilinx提供的函数库
- 中断 xscugic.h
- 定时器 xtmrctr.h
因为使用了PS端的GPIO,所以还需要另一个库
- GPIO xgpiops.h
大致流程与私有定时器相似:
- 定义定时器、中断控制器和GPIO的结构体
- 初始化定时器、终端控制器和GPIO,以及私有定时器自检
- ARM异常处理初始化,连接系统中断处理程序
- 连接定时器中断程序
- 使能GIC、使能定时器中断、使能ARM中断
- 配置重载、计数器初值,然后开始定时器,等中断
- 废弃这个定时器,通知处理器、通知GIC废弃
code:
//*****************2018/11/27 封装******************
1 #include <stdio.h> 2 #include "xil_printf.h" 3 4 #include "xparameters.h" 5 #include "xgpiops.h" 6 7 #include "sleep.h" 8 9 #include "xtmrctr.h" 10 #include "xil_exception.h" 11 #include "xscugic.h" 12 13 #define GpioPsDeviceId XPAR_PS7_GPIO_0_DEVICE_ID 14 #define AxiTmrCtrDeviceId XPAR_TMRCTR_0_DEVICE_ID 15 #define XScuGic_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID 16 #define TMRCTR_INTERRUPT_ID XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR 17 18 #define pinLed1 0 19 #define pinLed2 9 20 21 #define TIMER_CNTR_0 0 22 #define RESET_VALUE 0xFFFFFFFF-(0x5F5E100-1) //1s 23 24 int XGpioPsInit(XGpioPs *XGpioPsPtr); 25 int XIntrSysInit(XTmrCtr *XTmrCtrInstancePtr, 26 XScuGic *IntcInstancePtr, 27 u16 DeviceId, 28 u16 IntrId); 29 void XTmrCtrIntrHandler(void *CallBackRef, u8 TmrCtrNumber); 30 void TmrCtrDisableIntr(XScuGic *IntcInstancePtr, u16 IntrId); 31 32 static XGpioPs GpioPs; 33 static XTmrCtr XTmrCtrInstance; 34 static XScuGic IntcInstance; 35 36 int valueWriteLed2 = 0x01; 37 int valueWriteLed1 = 0x00; 38 39 int main() 40 { 41 int Status; 42 43 xil_printf(" Hello,world! " 44 "AXI Timer Test "); 45 46 /* Initialize the Gpio driver */ 47 Status = XGpioPsInit(&GpioPs); 48 if (Status != XST_SUCCESS) { 49 xil_printf("GPIOPS Initial Failed "); 50 return XST_FAILURE; 51 } 52 53 /* initialize & connect & enable interrupt system */ 54 Status = XIntrSysInit(&XTmrCtrInstance, 55 &IntcInstance, 56 AxiTmrCtrDeviceId, 57 TMRCTR_INTERRUPT_ID); 58 if (Status != XST_SUCCESS) { 59 xil_printf("Interrupt System Initial Failed "); 60 return XST_FAILURE; 61 } 62 63 /* set interrupt handler */ 64 XTmrCtr_SetHandler(&XTmrCtrInstance, 65 XTmrCtrIntrHandler,&XTmrCtrInstance); 66 67 /* Setting the timer counter option 68 * interrupt Mode and Auto Reload And Up Counter*/ 69 XTmrCtr_SetOptions(&XTmrCtrInstance, TIMER_CNTR_0, 70 XTC_INT_MODE_OPTION );//| XTC_AUTO_RELOAD_OPTION); 71 72 /* Set a reset value */ 73 XTmrCtr_SetResetValue(&XTmrCtrInstance, 74 TIMER_CNTR_0, // 75 RESET_VALUE); // 76 77 78 /* Start the timer counter */ 79 XTmrCtr_Start(&XTmrCtrInstance, TIMER_CNTR_0); 80 81 while(1){ 82 XGpioPs_WritePin(&GpioPs, pinLed1, valueWriteLed1); 83 // XGpioPs_WritePin(&Gpio, pinLed2, valueWriteLed2); 84 sleep(1); 85 xil_printf("--Write Led1: %d-- ",valueWriteLed1); 86 // xil_printf("--Write Led2: %d-- ",valueWriteLed2); 87 valueWriteLed1 = valueWriteLed1 & (0x01) ? 88 0x00 :0x01;//~valueWriteLed1; 89 // valueWriteLed2 = valueWriteLed2 & (0x01) ? 90 // 0x00 :0x01;//~valueWriteLed2; 91 92 xil_printf(" -- Do Again -- "); 93 } 94 95 96 /* never reached */ 97 xil_printf(" test end "); 98 99 /* Disconnect the interrupt */ 100 TmrCtrDisableIntr(&IntcInstance, TMRCTR_INTERRUPT_ID); 101 102 return 0; 103 } 104 105 /* Initialize the timer And GIC device driver , 106 * Connect the Interrupt to GIC And Enable the Interrupt */ 107 int XIntrSysInit(XTmrCtr *XTmrCtrInstancePtr,XScuGic *IntcInstancePtr, 108 u16 DeviceId, u16 IntrId) 109 { 110 XScuGic_Config *IntcConfig; 111 int Status; 112 113 /* Initialize the timer counter*/ 114 Status = XTmrCtr_Initialize(XTmrCtrInstancePtr, DeviceId); 115 if (Status != XST_SUCCESS) { 116 xil_printf("AXI TIMER INITIAL FAILED! "); 117 return XST_FAILURE; 118 } 119 120 /* Initialize the interrupt controller driver */ 121 IntcConfig = XScuGic_LookupConfig(XScuGic_DEVICE_ID); 122 if (NULL == IntcConfig) { 123 return XST_FAILURE; 124 } 125 Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, 126 IntcConfig->CpuBaseAddress); 127 if (Status != XST_SUCCESS) { 128 return XST_FAILURE; 129 } 130 131 /* Sets the interrupt priority & trigger type 132 * for the specified IRQ source */ 133 XScuGic_SetPriorityTriggerType(IntcInstancePtr, IntrId, 134 0xA0, 0x3); 135 136 /* Initialize the exception table. */ 137 Xil_ExceptionInit(); 138 139 /* Register the interrupt controller handler with the exception table. */ 140 Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, 141 (Xil_ExceptionHandler) 142 XScuGic_InterruptHandler, 143 IntcInstancePtr); 144 145 /* Connect the interrupt handler */ 146 Status = XScuGic_Connect(&IntcInstance, IntrId, 147 (Xil_ExceptionHandler)XTmrCtr_InterruptHandler, 148 XTmrCtrInstancePtr); 149 if (Status != XST_SUCCESS) { 150 return Status; 151 } 152 153 /* Enable the interrupt for the Timer device. */ 154 XScuGic_Enable(IntcInstancePtr, IntrId); 155 156 /* Enable non-critical exceptions. */ 157 Xil_ExceptionEnable(); 158 159 160 return XST_SUCCESS; 161 } 162 163 void XTmrCtrIntrHandler(void *CallBackRef, u8 TmrCtrNumber) 164 { 165 // XTmrCtr *InstancePtr = (XTmrCtr *)CallBackRef; 166 167 XGpioPs_WritePin(&GpioPs, pinLed2, valueWriteLed2); 168 xil_printf("--Write Led2: %d-- ",valueWriteLed2); 169 valueWriteLed2 = valueWriteLed2 & (0x01) ? 170 0x00 :0x01;//~valueWriteLed2; 171 return; 172 } 173 174 int XGpioPsInit(XGpioPs *GpioPsPtr) 175 { 176 XGpioPs_Config *ConfigPtr; 177 178 int Status; 179 /* Initialize the Gpio driver. */ 180 ConfigPtr = XGpioPs_LookupConfig(GpioPsDeviceId); 181 if (ConfigPtr == NULL) { 182 xil_printf("ERROR "); 183 return XST_FAILURE; 184 } 185 Status = XGpioPs_CfgInitialize(GpioPsPtr,ConfigPtr, 186 ConfigPtr->BaseAddr); 187 if (Status != XST_SUCCESS) { 188 print("cfg init err "); 189 return XST_FAILURE; 190 } 191 192 //set pin direction 193 //value 0 -> input 1 -> output 194 XGpioPs_SetDirectionPin(GpioPsPtr, pinLed1, 1); 195 XGpioPs_SetDirectionPin(GpioPsPtr, pinLed2, 1); 196 //value 0 -> disable 1 -> enable 197 XGpioPs_SetOutputEnablePin(GpioPsPtr, pinLed1, 1); 198 XGpioPs_SetOutputEnablePin(GpioPsPtr, pinLed2, 1); 199 200 return XST_SUCCESS; 201 } 202 void TmrCtrDisableIntr(XScuGic* IntcInstancePtr, u16 IntrId) 203 { 204 /* Disconnect the interrupt */ 205 XScuGic_Disable(IntcInstancePtr, IntrId); 206 XScuGic_Disconnect(IntcInstancePtr, IntrId); 207 208 return; 209 }
via
https://blog.csdn.net/u014485485/article/details/79069445