• Zynq学习笔记--了解中断配置方式


    目录

    1. 简介

    2. 工程与代码解析

    2.1 Vivado 工程

    2.2 Vitis 裸机代码

    2.3 关键代码解析

    3. 总结


    1. 简介

    Zynq 中的中断可以分为以下几种类型:

    软件中断(Software Generated Interrupt, SGI):由软件触发,通常用于CPU之间的通信。
    私有外设中断(Private Peripheral Interrupt, PPI):与每个CPU相关的中断,如定时器和看门狗。
    共享外设中断(Shared Peripheral Interrupt, SPI):由多个设备共享,可以被路由到任何一个CPU。

    中断控制器(GIC)是Zynq中管理中断的核心组件,负责中断的使能、屏蔽、优先级设置以及将中断信号发送到CPU1。

    本文展示是一个中断处理示例,记录如何在PS(处理系统)和PL(可编程逻辑)之间使用GPIO(通用输入输出)和中断。

    2. 工程与代码解析

    2.1 Vivado 工程

    系统中断由多个系统元素生成,并通过GIC代理(GICPx_IRQ 寄存器)广播到GICs、PMU以及PL中的输出信号。

    我们重点关注PL中的输出信号:

     UG1085: System Interrupts

    Datasheet 中的描述的两组中断寄存器,对于到 Zynq 配置页面示意图如下:

    如果查看 "xparameters.h" 文件,可以看到 IRQ 对应的中断号:

    //AXI GPIO 中断号 121

    #define AXI_GPIO_INTERRUPT_ID  XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR

     

    2.2 Vitis 裸机代码

    代码的主要功能包括:

    • 初始化:配置PS端和PL端的GPIO设备,包括设置方向和输出使能。
    • 中断系统设置:初始化GIC(通用中断控制器),注册中断处理函数,并设置中断优先级和触发类型。
    • 中断处理:定义了一个中断处理函数IntrHandler,当检测到AXI GPIO中断时,会打印一条消息。
    1. #include "stdio.h"
    2. #include "xparameters.h"
    3. #include "xgpiops.h"
    4. #include "xgpio.h"
    5. #include "sleep.h"
    6. #include "xil_exception.h"
    7. #include "xscugic.h"
    8. #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
    9. #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
    10. #define AXI_GPIO_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
    11. //AXI GPIO 中断号 121
    12. #define AXI_GPIO_INTERRUPT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
    13. //AXI GPIO 通道
    14. #define GPIO_CHANNEL1 1
    15. #define MIO7_LED 7
    16. #define MIO36_KEY 36
    17. static void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,
    18. u16 AXI_GpioIntrId);
    19. static void IntrHandler();
    20. XGpioPs Gpio; /* The driver instance for GPIO Device. */
    21. XScuGic Intc; /* The Instance of the Interrupt Controller Driver */
    22. XGpio AXI_Gpio; /* The Instance of the GPIO Driver */
    23. static XGpioPs_Config *ConfigPtr;
    24. static XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
    25. int main() {
    26. u32 keyval;
    27. printf("AXI GPIO INTERRUPT TEST!\n\r");
    28. //由 ID 查找 PS 端器件,并初始化
    29. ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    30. XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
    31. //PS 端 GPIO 方向设置, 0 - Input, 1 - Output
    32. XGpioPs_SetDirectionPin(&Gpio, MIO7_LED, 1);
    33. XGpioPs_SetDirectionPin(&Gpio, MIO36_KEY, 0);
    34. //PS 端设置输出使能,0 - Disable, 1 - Enable
    35. XGpioPs_SetOutputEnablePin(&Gpio, MIO7_LED, 1);
    36. //由 ID 查找 PL 端器件,并初始化
    37. XGpio_Initialize(&AXI_Gpio, AXI_GPIO_DEVICE_ID);
    38. //PL 端 GPIO 方向设置, 0 - Output, 1 - Input
    39. XGpio_SetDataDirection(&AXI_Gpio, GPIO_CHANNEL1, 0x00000001);
    40. //设置中断系统
    41. SetupInterruptSystem(&Intc, &AXI_Gpio, AXI_GPIO_INTERRUPT_ID);
    42. while(1){
    43. keyval = XGpioPs_ReadPin(&Gpio, MIO36_KEY);
    44. XGpioPs_WritePin(&Gpio, MIO7_LED, ~keyval);
    45. }
    46. return 0;
    47. }
    48. static void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,
    49. u16 AXI_GpioIntrId)
    50. {
    51. //根据GIC器件ID,查找器件的配置信息,并初始化
    52. IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
    53. XScuGic_CfgInitialize(GicInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);
    54. //初始化ARM处理器异常句柄
    55. Xil_ExceptionInit();
    56. //注册IRQ异常处理程序
    57. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    58. (Xil_ExceptionHandler)XScuGic_InterruptHandler,
    59. GicInstancePtr);
    60. //使能处理器中断
    61. Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
    62. //关联中断处理函数
    63. XScuGic_Connect(GicInstancePtr, AXI_GpioIntrId,
    64. (Xil_ExceptionHandler)IntrHandler,
    65. (void *)AXI_Gpio);
    66. //使能GIC器件中断
    67. XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);
    68. //0xA0:中断源的优先级, 0x01:中断类型为高电平有效,电平敏感类型
    69. XScuGic_SetPriorityTriggerType(GicInstancePtr, AXI_GpioIntrId, 0xA0, 0x01);
    70. //全局中断使能
    71. XGpio_InterruptGlobalEnable(AXI_Gpio);
    72. //通道中的信号对应的中断使能
    73. XGpio_InterruptEnable(AXI_Gpio, 0x00000001);
    74. }
    75. void IntrHandler() {
    76. if (XGpio_DiscreteRead(&AXI_Gpio, GPIO_CHANNEL1) == 0x00000000){
    77. printf("AXI interrupt detected!\n\r");
    78. }
    79. XGpio_InterruptClear(&AXI_Gpio, 0x00000001);
    80. }

    2.3 关键代码解析

    为了直观地理解代码的结构和功能,参照图片进行理解:

    • 步骤划分和流程图:图片将代码分为几个关键步骤,并以流程图形式展示每个步骤的调用顺序和逻辑关系,帮助读者更好地理解代码的整体流程和各个部分之间的关系。
    • 关键代码高亮:图片中标注了关键代码行,例如初始化、GPIO方向设置和中断处理,帮助读者快速定位和理解代码中的重要部分。
    • 代码与注释结合:图片将代码与相应的注释结合展示,详细解释了每一行代码的作用和意义,帮助读者更深入地理解代码的实现细节。

    3. 总结

    在本文中,我们探讨了Zynq平台上中断的概念和分类,包括软件中断、私有外设中断和共享外设中断。我们还介绍了中断控制器(GIC)的作用,它是中断管理的核心。通过一个实际的示例,我们展示了如何在处理系统(PS)和可编程逻辑(PL)之间使用通用输入输出(GPIO)来处理中断。示例代码包括初始化GPIO设备、设置中断系统和定义中断处理函数。

  • 相关阅读:
    Python用若干列的数据多条件筛选、去除Excel数据并批量绘制直方图
    TRC丨艾美捷 TRC 3-氯-1,2-丙二醇-二棕榈酸酯说明书
    (附源码)计算机毕业设计SSM敬老院信息管理系统
    黑马-Jenkins篇
    Python Selenium 之数据驱动测试的实现!
    知识产权评估方法有哪些?
    13.Jenkins的使用
    Chrome浏览器删除网站cookies的解决方案
    必备基础算法
    GAMES101复习:光栅化
  • 原文地址:https://blog.csdn.net/DongDong314/article/details/139728751