• 中断:PL硬中断,基地址,优先级。


    行动步骤:

    1.编写RTL文件,设置中断的触发条件和频率,将其封装成IP;

    2.配置BD,为上述IP提供CLK和RST,注意敏感列表;

    3.在zynq processor中配置中断号,分配中断号:

            PL终端号可选:#61 至 #68 和 #84 至 #91

    4.启动Vitis,在C文件中绑定CPUID,并使能硬中断的中断号,连接,配置优先级和灵敏度类型。

    使用的几个函数:

    XScuGic_SetPriTrigTypeByDistAddr

    XScuGic_InterruptMaptoCpu

    1. int GIC_init(){
    2. int Status;
    3. Xil_ExceptionInit();
    4. GIC_SGI_ConFig = XScuGic_LookupConfig(GIC_DECIVE_ID_INT);
    5. if (NULL == GIC_SGI_ConFig) {
    6. return XST_FAILURE;
    7. }
    8. Status = XScuGic_CfgInitialize(&GIC_SGI_instance_point,
    9. GIC_SGI_ConFig,
    10. GIC_SGI_ConFig->CpuBaseAddress);
    11. if (Status != XST_SUCCESS) {
    12. return XST_FAILURE;
    13. }
    14. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    15. (Xil_ExceptionHandler) XScuGic_InterruptHandler,
    16. &GIC_SGI_instance_point);
    17. //SGI
    18. Status = XScuGic_Connect(&GIC_SGI_instance_point,
    19. Interrupt_ID_SGI_14,
    20. (Xil_InterruptHandler )SGI_IntrHandler,
    21. (void *)&GIC_SGI_instance_point
    22. );
    23. if (Status != XST_SUCCESS) {
    24. return XST_FAILURE;
    25. }
    26. XScuGic_Enable(&GIC_SGI_instance_point,
    27. Interrupt_ID_SGI_14);
    28. //HGI
    29. Status = XScuGic_Connect(&GIC_SGI_instance_point,
    30. Interrupt_ID_Hardware_0,
    31. (Xil_InterruptHandler )Hardware_IntrHandler,
    32. (void *)&GIC_SGI_instance_point
    33. );
    34. if (Status != XST_SUCCESS) {
    35. return XST_FAILURE;
    36. }
    37. // XScuGic_SetPriorityTriggerType();
    38. XScuGic_SetPriTrigTypeByDistAddr(DistBaseAddress,
    39. Interrupt_ID_Hardware_0,
    40. 0x20,
    41. 0x03);
    42. XScuGic_InterruptMaptoCpu(&GIC_SGI_instance_point,
    43. CPU_id_0,
    44. Interrupt_ID_Hardware_0);
    45. XScuGic_Enable(&GIC_SGI_instance_point,
    46. Interrupt_ID_Hardware_0);
    47. Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
    48. return XST_SUCCESS;
    49. }

    SPI:UG585原文

            来自各个模块的一组大约 60 个中断可以路由到一个或两个 CPU 或 PL。中断控制器管理 CPU 的这些中断的优先级和接收。
            除了 IRQ #61 至 #68 和 #84 至 #91 之外,所有中断敏感度类型均由请求源固定且无法更改。 GIC 必须进行编程以适应这种情况。引导 ROM 不会对这些寄存器进行编程;因此,SDK 设备驱动程序必须对 GIC 进行编程以适应这些敏感度类型。

    比较SGI:ICDICFR0可以不用太关心,因为不可配。

            所有 SGI 都是边沿触发的。 SGI 的灵敏度类型是固定的且无法更改; ICDICFR0 寄存器是只读的,因为它指定了所有 16 个 SGI 的灵敏度类型。

    需要注意的问题:

    ZYNQ AMP模式下CPU1响应外部中断_zynq core 1 中断-CSDN博客

            对于电平敏感类型的中断,请求源必须提供一种机制,以便中断处理程序在中断被应答后清除中断。此要求适用于任何具有高级别灵敏度类型的 IRQF2P[n](来自 PL)。
            对于上升沿敏感的中断,请求源必须提供足够宽的脉冲供 GIC 捕获。这通常至少是 2 个 CPU_2x3x 周期。此要求适用于任何具有上升沿敏感类型的 IRQF2P[n](来自 PL)。
            ICDICFR2 至 ICDICFR5 寄存器配置所有 SPI 的中断类型。每个中断都有一个 2 位字段,指定敏感类型和处理模型。

    ICFR 0

            ICD ICFR 0 寄存器控制 16 个软件生成中断 (SGI)、IRQ ID #0 至 ID #15 的中断灵敏度。该只读寄存器每个中断有两位,始终指示每个 SGI 中断是边沿敏感的,并且必须由 ICD IPTR [3:0] 寄存器中指示的所有目标 CPU 进行处理。

    ICDICFR 2

            ICDICFR 2寄存器控制共享外设中断 (SPI)、IRQ ID #32 至 ID #47(IRQ 36 被保留)的中断灵敏度。该寄存器每个中断有两位。该两位字段要么等于 01(高电平有效),要么等于 11(上升沿敏感)。 LSB 始终为 1,因为无论目标 CPU 数量如何,只有一个 CPU 会处理 SPI 中断。
    请参阅 UG585 TRM 第 7.2.3 节共享外设中断 (SPI),了解 SPI 中断所需的灵敏度类型。 SPI 中断必须符合预期的灵敏度。

            来自 PL 的中断可能是高电平或上升沿敏感的;这必须与 PL 硬件和软件相协调。

    本次使用的PL端只用了两个中断输入,只看61和62吧。

    ICDICFR3

            ICDICFR 3 寄存器控制共享外设中断 (SPI)、IRQ ID #48 至 ID #63 的中断灵敏度。该寄存器每个中断有两位。该两位字段要么等于 01(高电平有效),要么等于 11(上升沿敏感)。 LSB 始终为 1,因为无论目标 CPU 数量如何,只有一个 CPU 会处理 SPI 中断。
            请参阅 UG585 TRM 第 7.2.3 节共享外设中断 (SPI),了解 SPI 中断所需的灵敏度类型。 SPI 中断必须符合预期的灵敏度。来自 PL 的中断可能是高电平或上升沿敏感的;这必须与 PL 硬件和软件相协调。

    中断 ID#61 配置 01:高电平有效 11:上升沿 低位只读,始终为 1

    中断 ID#62 配置 01:高电平有效 11:上升沿 低位只读,始终为 1。

    基地址:GIC的DistBaseAddress

    ZYNQ的中断设置都有一个基地址,对各个中断号的中断的响应,可以通过中断号来进行偏移。

    Name ICDDCR

    Software Name GIC_DIST_EN

    Relative Address 0x00001000

    Absolute Address 0xF8F01000

    Width 32 bits

    Access Type rw

    Reset Value 0x00000000

    Description Distributor Control Register

    细节:注册中断的时候需要错开两个核内的注册时间。

    设置硬中断优先级和基地址的函数:XScuGic_SetPriTrigTypeByDistAddr

    void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id,
                        u8 Priority, u8 Trigger)

    DistBaseAddress根据UG585需要填入

    DistBaseAddress = XPAR_PS7_SCUGIC_0_DIST_BASEADDR=0xF8F01000

    Int_Id填入中断号

    Priority填入优先级

    Trigger根据ICDICFR中的需求填入

    1. /****************************************************************************/
    2. /**
    3. * Sets the interrupt priority and trigger type for the specificd IRQ source.
    4. *
    5. * @param DistBaseAddress is the distributor base address
    6. * @param Int_Id is the IRQ source number to modify
    7. * @param Priority is the new priority for the IRQ source. 0 is highest
    8. * priority, 0xF8(248) is lowest. There are 32 priority
    9. * levels supported with a step of 8. Hence the supported
    10. * priorities are 0, 8, 16, 32, 40 ..., 248.
    11. * @param Trigger is the new trigger type for the IRQ source.
    12. * Each bit pair describes the configuration for an INT_ID.
    13. * SFI Read Only b10 always
    14. * PPI Read Only depending on how the PPIs are configured.
    15. * b01 Active HIGH level sensitive
    16. * b11 Rising edge sensitive
    17. * SPI LSB is read only.
    18. * b01 Active HIGH level sensitive
    19. * b11 Rising edge sensitive/
    20. *
    21. * @return None.
    22. *
    23. * @note This API has the similar functionality of XScuGic_SetPriority
    24. * TriggerType() and should be used when there is no InstancePtr.
    25. *
    26. *****************************************************************************/
    27. void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id,
    28. u8 Priority, u8 Trigger)
    29. {
    30. u32 RegValue;
    31. #if defined (GICv3)
    32. u32 Temp;
    33. u32 Index;
    34. #endif
    35. u8 LocalPriority = Priority;
    36. Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
    37. Xil_AssertVoid(Trigger <= XSCUGIC_INT_CFG_MASK);
    38. Xil_AssertVoid(LocalPriority <= XSCUGIC_MAX_INTR_PRIO_VAL);
    39. #if defined (GICv3)
    40. if (Int_Id < XSCUGIC_SPI_INT_ID_START )
    41. {
    42. XScuGic_WriteReg(DistBaseAddress + XSCUGIC_RDIST_SGI_PPI_OFFSET,
    43. XSCUGIC_RDIST_INT_PRIORITY_OFFSET_CALC(Int_Id),Priority);
    44. Temp = XScuGic_ReadReg(DistBaseAddress + XSCUGIC_RDIST_SGI_PPI_OFFSET,
    45. XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id));
    46. Index = XScuGic_Get_Rdist_Int_Trigger_Index(Int_Id);
    47. Temp |= (Trigger << Index);
    48. XScuGic_WriteReg(DistBaseAddress + XSCUGIC_RDIST_SGI_PPI_OFFSET,
    49. XSCUGIC_RDIST_INT_CONFIG_OFFSET_CALC(Int_Id),Temp);
    50. return;
    51. }
    52. #endif
    53. /*
    54. * Call spinlock to protect multiple applications running at separate
    55. * CPUs to write to the same register. This macro also ensures that
    56. * the spinlock mechanism is used only if spinlock is enabled by
    57. * user.
    58. */
    59. XIL_SPINLOCK();
    60. /*
    61. * Determine the register to write to using the Int_Id.
    62. */
    63. RegValue = XScuGic_ReadReg(DistBaseAddress,
    64. XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
    65. /*
    66. * The priority bits are Bits 7 to 3 in GIC Priority Register. This
    67. * means the number of priority levels supported are 32 and they are
    68. * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc.
    69. * The lower order 3 bits are masked before putting it in the register.
    70. */
    71. LocalPriority = LocalPriority & XSCUGIC_INTR_PRIO_MASK;
    72. /*
    73. * Shift and Mask the correct bits for the priority and trigger in the
    74. * register
    75. */
    76. RegValue &= ~((u32)XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U));
    77. RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U);
    78. /*
    79. * Write the value back to the register.
    80. */
    81. XScuGic_WriteReg(DistBaseAddress, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
    82. RegValue);
    83. /*
    84. * Determine the register to write to using the Int_Id.
    85. */
    86. RegValue = XScuGic_ReadReg(DistBaseAddress,
    87. XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id));
    88. /*
    89. * Shift and Mask the correct bits for the priority and trigger in the
    90. * register
    91. */
    92. RegValue &= ~((u32)XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U));
    93. RegValue |= (u32)Trigger << ((Int_Id%16U)*2U);
    94. /*
    95. * Write the value back to the register.
    96. */
    97. XScuGic_WriteReg(DistBaseAddress, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id),
    98. RegValue);
    99. /*
    100. * Release the lock previously taken. This macro ensures that the lock
    101. * is given only if spinlock mechanism is enabled by the user.
    102. */
    103. XIL_SPINUNLOCK();
    104. }

     绑定依赖的CPU:XScuGic_InterruptMaptoCpu

    1. /****************************************************************************/
    2. /**
    3. * Sets the target CPU for the interrupt of a peripheral
    4. *
    5. * @param InstancePtr is a pointer to the instance to be worked on.
    6. * @param Cpu_Identifier is a CPU number for which the interrupt has to be targeted
    7. * @param Int_Id is the IRQ source number to modify
    8. *
    9. * @return None.
    10. *
    11. * @note None
    12. *
    13. *****************************************************************************/
    14. void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Identifier, u32 Int_Id)
    15. {
    16. u32 RegValue;
    17. if (Int_Id >= XSCUGIC_SPI_INT_ID_START) {
    18. #if defined (GICv3)
    19. Xil_AssertVoid(InstancePtr != NULL);
    20. RegValue = XScuGic_DistReadReg(InstancePtr,
    21. XSCUGIC_IROUTER_OFFSET_CALC(Int_Id));
    22. RegValue |= Cpu_Identifier;
    23. XScuGic_DistWriteReg(InstancePtr, XSCUGIC_IROUTER_OFFSET_CALC(Int_Id),
    24. RegValue);
    25. #else
    26. u8 Cpu_CoreId;
    27. u32 Offset;
    28. Xil_AssertVoid(InstancePtr != NULL);
    29. /*
    30. * Call spinlock to protect multiple applications running at separate
    31. * CPUs to write to the same register. This macro also ensures that
    32. * the spinlock mechanism is used only if spinlock is enabled by
    33. * user.
    34. */
    35. XIL_SPINLOCK();
    36. RegValue = XScuGic_DistReadReg(InstancePtr,
    37. XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id));
    38. Offset = (Int_Id & 0x3U);
    39. Cpu_CoreId = (0x1U << Cpu_Identifier);
    40. RegValue |= (u32)(Cpu_CoreId) << (Offset*8U);
    41. XScuGic_DistWriteReg(InstancePtr,
    42. XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
    43. RegValue);
    44. /*
    45. * Release the lock previously taken. This macro ensures that the lock
    46. * is given only if spinlock mechanism is enabled by the user.
    47. */
    48. XIL_SPINUNLOCK();
    49. #endif
    50. }
    51. }

  • 相关阅读:
    企业内训app源码,在线培训小程序,随时随地想学就学
    516. 最长回文子序列
    程序员保密协议
    MATLAB算法实战应用案例精讲-【图像处理】机器视觉(基础篇)(十)
    Amazon图片下载器:利用Scrapy库完成图像下载任务
    0 upgraded, 0 newly installed, 0 to remove and 112 not upgraded解决方法
    [2022-11-02] MacBook M1安装部署PyMuPDF教程
    【性能优化】单一接口优化过程全记录(主要涉及Redis)
    react原理及合成事件原理
    容器运行时 笔记 / CRI-O / CRI-O 安装说明
  • 原文地址:https://blog.csdn.net/NoNoUnknow/article/details/133811578