中断:ZYNQ

整个中断系统架构中,只包含以下三种中断:

 软件生成中断(Software Generated Interrupts,SGI)

 私有外设中断(Private Peripheral Interrupts,PPI)

 共享外设中断(Shared Peripheral Interrupts,SPI)

        每种中断都各自包含特定的中断源,如: PPI 包括全局定时器(global timer)、 私有看门狗定时器(private timer)、私有定时器(private timer)和 PL 中的 FIQ。

        SGI 则是通过写入通用中断控制器(Generic Interrupt Controller,GIC)中的寄存器 生成。SPI 是由 PS 和 PL 中的各种 I/O 和内存控制器生成的。

        对于一般的中低端 CPU 系统来说,上面的结构就足够实现中断的产生和处 理功能了。但是,我们 zynq 的 PS 可不是一般的处理器系统,它是一个结构复 杂,性能强劲的双核 Cortex-A9 处理器系统。其包含一级缓存 L1 ,二级缓存 L2, 缓存能够提升 CPU 读写总线数据的性能。但是使用不当,也会造成 CPU 读写数 据实时性的下降,甚至因为缓存一致性的问题,把一些已经由其他外设更新但 是缓存中还是旧值的数据取用,从而产生错误。由于中断的实时性和重要性,中断控制器的相关寄存器的读写是不能因为缓存的存在而被延误的,所以 CPU 并不通过 L2 来访问 GIC 中的寄存器,而是通过一个名为窥探控制单元 Snoop Control Unit(简称 SCU),采用私有总线访问 GIC 的寄存器,以此来提升中断 的处理效率。

IRQ和FRQ:普通中断和快中断

        通用中断控制器(GIC)是一种集中式资源,是联系中断和 CPU 的桥梁,也是各 CPU 之间中断互联的通道(也带有管理功能),它负责管理、分发从 PS 和 PL 发送到 CPU 的中断。

        当 CPU 接口接受下一个中断时,控制器启用、禁用、 屏蔽中断源并确定其优先级,然后按照编程设定将它们发送给选定的 CPU。

        当然,并不是说所有的中断请求一发出都能立马被 CPU 处理。所有中断源 都有唯一的中断标识号标识以及自己可配置的优先级和目标 CPU 列表。

        图中的 中断分发器(Interrupt Controller Distributor ,ICD)保存着每个 CPU 的挂起中断列表。它会集中所有的中断源,随后根据其优先级(优先级设置值越大,优先级越小),优先将高优先级的中断源分配给指定 CPU 处理,以确保针对多个 CPU 的中断一次只能由一个 CPU 处理。

        但是优先级逻辑在物理上是重复的,也 就是说不同的中断也可以设置为同一优先级。对于这种情况,中断分发器会优先将中断标识号最低的中断源分配给 CPU 处理。

软中断

        每个 CPU 都可以使用软件生成的中断 (SGI) 来中断自身、另一个 CPU 或两个 CPU。
        有 16 个软件生成的中断(见表 7-2)。通过将 SGI 中断号写入 ICDSGIR 寄存器并指定目标 CPU 来生成 SGI。此写入通过 CPU 自己的专用总线进行。每个 CPU 都有自己的一组 SGI 寄存器,用于生成 16 个软件生成的中断中的一个或多个。通过读取 ICCIAR(中断应答)寄存器或将 1 写入 ICDICPR(中断清除挂起)寄存器的相应位来清除中断。

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

        每个 CPU 专用的一组 16 个中断源,可以路由到最多 16 个公共中断目标,其中每个目标可以是一个或多个 CPU。

私有设备中断

        每个 CPU 连接到一组私有的五个外设中断。 PPI 列于表 7-3 中。
        PPI 的敏感度类型是固定的且无法更改;因此,ICDICFR1 寄存器是只读的,因为它指定了所有 5 个 PPI 的灵敏度类型。请注意,来自 PL 的快速中断 (FIQ) 信号和中断 (IRQ) 信号被反转,然后发送到中断控制器。因此,尽管 ICDICFR1 寄存器将它们反映为低电平有效,但它们在 PS-PL 接口处为高电平有效。

共享设备中断

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

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

        而 AXI GPIO 由于是 PL 逻辑构成的,因此 AXI GPIO 中断属于 PL 中断,中断号为#[91:84]和#[68:61],触发类型为高电平或上升沿。 该中断在使用时需要在 ZYNQ 核中使能对应中断端口。

具体开发情况

开发步骤:

ZYNQ-实现GPIO的中断控制_zynq gpio中断_Vuko-wxh的博客-CSDN博客

  1. 初始化CPU异常功能
  2. 初始化中断控制器
  3. 向CPU注册异常处理回调函数(CPU在中断以后执行的函数)
  4. 向中断控制器中对应的中断ID和中断控制器相连接(并且注册第六步的回调函数)
  5. 设置中断的类型
  6. 设置GPIO中断的回调函数(用户自己设置)
  7. 使能对应引脚的中断
  8. 使能中断控制器
  9. 使能异常处理功能

GIC驱动程序组件。

        中断控制器驱动程序对各种处理程序使用优先级的概念:

        优先级是 1 到 31 范围内的整数,默认值 1 是最高优先级中断源。各种源的优先级可以根据需要通过硬件配置动态更改。
        6通用中断控制器支持以下功能: 特定的单独中断 启用/禁用特定的单独中断确认 附加特定的回调函数来处理中断源 如果默认值不可接受,则为中断源分配所需的优先级。
        有关连接驱动程序中断处理程序的详细信息包含在特定于中断处理的源文件 xscugic_intr.c 中。
        该驱动程序旨在独立于 RTOS 和处理器。它仅适用于物理地址。任何对动态内存管理、线程或线程互斥、虚拟内存或高速缓存控制的需求都必须由该驱动程序之上的层来满足。


中断向量表

        驱动程序使用中断控制器设备的设备 ID 作为配置数据表的直接索引。用户应使用XScuGic_Connect() 和 XScuGic_Disconnect() 函数在运行时使用处理程序和回调填充向量表。
        每个向量表条目对应一个可以产生中断的设备。每个条目都包含一个中断处理程序函数和一个在中断发生时传递给处理程序的参数。当中断处理程序采用基地址以外的参数时,用户必须使用 XScuGic_Connect()。


嵌套中断处理

该驱动程序不支持嵌套中断。
        注意:通用中断控制器不是监听控制单元的一部分,如驱动程序名称中的前缀“scu”所示。它是APU中的一个独立模块。

函数介绍:

步骤1:初始化CPU异常功能

Xil_ExceptionInit

        将中断控制器中断处理程序连接到ARM 处理器中的硬件中断处理逻辑。

        我在新的例子中没有看到这个函数了。

        * @brief 该函数是一个通用 API,用于在所有支持的手臂上初始化异常处理程序 *处理器。对于 ARM Cortex-A53、Cortex-R5、* 和 Cortex-A9,异常处理程序正在静态初始化,并且该函数不执行任何操作。
        * 然而,它仍然存在以解决向后兼容性 * 问题(在早期版本的 BSP 中,此 API 用于 * 初始化异常处理程序)。

/****************************************************************************/
/**
* @brief	The function is a common API used to initialize exception handlers
*			across all supported arm processors. For ARM Cortex-A53, Cortex-R5,
*			and Cortex-A9, the exception handlers are being initialized
*			statically and this function does not do anything.
* 			However, it is still present to take care of backward compatibility
*			issues (in earlier versions of BSPs, this API was being used to
*			initialize exception handlers).
*
* @return	None.
*
*****************************************************************************/
void Xil_ExceptionInit(void)
{return;
}

步骤2:初始化中断控制器

        和配置其他的没什么不同,不详细列举。

	GicConfig = XScuGic_LookupConfig(DeviceId);if (NULL == GicConfig) {return XST_FAILURE;}Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,GicConfig->CpuBaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}

步骤3:向CPU注册异常处理回调函数Xil_ExceptionRegisterHandler()

void Xil_ExceptionRegisterHandler(u32 Exception_id,
                    Xil_ExceptionHandler Handler,
                    void *Data)

/******************************************************** **************************/ 
/** * @brief 为特定异常注册处理程序。当处理器遇到指定的异常时,将调用此处理程序。
* * @param Exception_id 包含异常源的 ID,并且应该 
* 在 0 到 XIL_EXCEPTION_ID_LAST 的范围内。
* 有关更多信息,请参阅 xil_exception.h。
* @param Handler 到该异常的处理程序。
* @param Data 是对数据的引用,当处理程序被调用时,该数据将被传递给处理程序。
* * @返回无。
********************************************************* **************************/ 
/*****************************************************************************/
/**
* @brief	Register a handler for a specific exception. This handler is being
*			called when the processor encounters the specified exception.
*
* @param	Exception_id contains the ID of the exception source and should
*			be in the range of 0 to XIL_EXCEPTION_ID_LAST.
*			See xil_exception.h for further information.
* @param	Handler to the Handler for that exception.
* @param	Data is a reference to Data that will be passed to the
*			Handler when it gets called.
*
* @return	None.
*
****************************************************************************/
void Xil_ExceptionRegisterHandler(u32 Exception_id,Xil_ExceptionHandler Handler,void *Data)
{
#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52)if ( XIL_EXCEPTION_ID_IRQ_INT == Exception_id ){/** Cortexa72 processor in versal is coupled with GIC-500, and* GIC-500 supports only FIQ at EL3. Hence, tweaking this API* to act on IRQ, if Exception_id is pointing to IRQ*/Exception_id = XIL_EXCEPTION_ID_FIQ_INT;}
#endifXExc_VectorTable[Exception_id].Handler = Handler;XExc_VectorTable[Exception_id].Data = Data;
}

步骤4:连接GPIO中断信号并注册GPIO回调函数:XScuGic_Connect()

s32  XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,
                Xil_InterruptHandler Handler, void *CallBackRef)

/******************************************************** ****************************/ 
/** * * 在中断源的 Int_Id 和关联的处理程序之间建立连接是在识别到中断时运行。 
* 在此调用中作为 Callbackref 提供的参数在调用处理程序时用作处理程序的参数。
* * @param InstancePtr 是指向 XScuGic 实例的指针。
* @param Int_Id 包含中断源的 ID,并且应在 0 到 XSCUGIC_MAX_NUM_INTR_INPUTS - 1 的范围内 
* @param Handler 指向该中断的处理程序。
* @param CallBackRef 是回调引用,通常是连接驱动程序的实例指针。
* * @return * * - XST_SUCCESS 如果处理程序连接正确。
* * @note * 
* 警告:作为参数提供的处理程序将覆盖之前连接的任何处理程序。
********************************************************* ****************************/
/*****************************************************************************/
/**
*
* Makes the connection between the Int_Id of the interrupt source and the
* associated handler that is to run when the interrupt is recognized. The
* argument provided in this call as the Callbackref is used as the argument
* for the handler when it is called.
*
* @param	InstancePtr is a pointer to the XScuGic instance.
* @param	Int_Id contains the ID of the interrupt source and should be
*		in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
* @param	Handler to the handler for that interrupt.
* @param	CallBackRef is the callback reference, usually the instance
*		pointer of the connecting driver.
*
* @return
*
*		- XST_SUCCESS if the handler was connected correctly.
*
* @note
*
* WARNING: The handler provided as an argument will overwrite any handler
* that was previously connected.
*
****************************************************************************/
s32  XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,Xil_InterruptHandler Handler, void *CallBackRef)
{/** Assert the arguments*/Xil_AssertNonvoid(InstancePtr != NULL);Xil_AssertNonvoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);Xil_AssertNonvoid(Handler != NULL);Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);/** The Int_Id is used as an index into the table to select the proper* handler*/InstancePtr->Config->HandlerTable[Int_Id].Handler = (Xil_InterruptHandler)Handler;InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef;return XST_SUCCESS;
}

步骤5:设置GPIO中断类型XGpioPs_SetIntrType()

void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,

              u32 IntrPolarity, u32 IntrOnAny)

/******************************************************** **************************/ 
/** * * 该函数用于设置中断类型、中断极性和 * Interrupt On Any对于指定的 GPIO Bank 引脚。
* * @param InstancePtr 是指向 XGpioPs 实例的指针。
* @param Bank 是要操作的 GPIO 的 Bank 号。
* Zynq 中的有效值为 0-3,Zynq Ultrascale+ MP 中的有效值为 0-5。
* @param IntrType 是中断类型的 32 位掩码。
* 0 表示电平敏感,1 表示边缘敏感。
* @param IntrPolarity 是中断极性的 32 位掩码。
* 0 表示低电平有效或下降沿,1 表示高电平有效或 * 上升沿。
* @param IntrOnAny 是边沿触发中断的中断触发的 32 位掩码。 
* 0 表示使用配置的中断极性在单边沿触发,1 表示在双边沿触发。
* * @返回无。
* * @note 该函数用于设置指定bank中所有引脚的中断相关属性。引脚之前的 * 状态不会保持。
* 要更改单个 GPIO 引脚的中断属性,请使用函数 XGpioPs_SetPinIntrType()。
********************************************************* ****************************/
/****************************************************************************/
/**
*
* This function is used for setting the Interrupt Type, Interrupt Polarity and
* Interrupt On Any for the specified GPIO Bank pins.
*
* @param	InstancePtr is a pointer to an XGpioPs instance.
* @param	Bank is the bank number of the GPIO to operate on.
*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param	IntrType is the 32 bit mask of the interrupt type.
*		0 means Level Sensitive and 1 means Edge Sensitive.
* @param	IntrPolarity is the 32 bit mask of the interrupt polarity.
*		0 means Active Low or Falling Edge and 1 means Active High or
*		Rising Edge.
* @param	IntrOnAny is the 32 bit mask of the interrupt trigger for
*		edge triggered interrupts. 0 means trigger on single edge using
*		the configured interrupt polarity and 1 means  trigger on both
*		edges.
*
* @return	None.
*
* @note		This function is used for setting the interrupt related
*		properties of all the pins in the specified bank. The previous
*		state of the pins is not maintained.
*		To change the Interrupt properties of a single GPIO pin, use the
*		function XGpioPs_SetPinIntrType().
*
*****************************************************************************/
void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,u32 IntrPolarity, u32 IntrOnAny)
{Xil_AssertVoid(InstancePtr != NULL);Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versalif(InstancePtr->PmcGpio == (u32)TRUE) {Xil_AssertVoid(Bank != XGPIOPS_TWO);} else {Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));}
#endifXGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +XGPIOPS_INTTYPE_OFFSET, IntrType);XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +XGPIOPS_INTPOL_OFFSET, IntrPolarity);XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +XGPIOPS_INTANY_OFFSET, IntrOnAny);
}

步骤6:设置GPIO的回调函数XGpioPs_SetCallbackHandler()

void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef,

                 XGpioPs_Handler FuncPointer)

/******************************************************** **************************/ 
/** * * 该函数设置状态回调函数。当中断发生时,回调函数由 XGpioPs_IntrHandler 调用。
* * @param InstancePtr 是指向 XGpioPs 实例的指针。
* @param CallBackRef 是调用回调函数时传回的上层回调引用。
* @param FuncPointer 是回调函数的指针。
* * * @return 无。
* 
* @note 处理程序是在中断上下文中调用的,因此它应该快速完成其工作,
* 并将可能耗时的工作排队到任务级线程。
********************************************************* *****************************/
/*****************************************************************************/
/**
*
* This function sets the status callback function. The callback function is
* called by the  XGpioPs_IntrHandler when an interrupt occurs.
*
* @param	InstancePtr is a pointer to the XGpioPs instance.
* @param	CallBackRef is the upper layer callback reference passed back
*		when the callback function is invoked.
* @param	FuncPointer is the pointer to the callback function.
*
*
* @return	None.
*
* @note		The handler is called within interrupt context, so it should do
*		its work quickly and queue potentially time-consuming work to a
*		task-level thread.
*
******************************************************************************/
void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef,XGpioPs_Handler FuncPointer)
{Xil_AssertVoid(InstancePtr != NULL);Xil_AssertVoid(FuncPointer != NULL);Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);InstancePtr->Handler = FuncPointer;InstancePtr->CallBackRef = CallBackRef;
}

步骤7:使能对应pin的中断XGpioPs_IntrEnable()

void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask)

/******************************************************** **************************/ 
/** * * 该函数启用指定* Bank 中指定引脚的中断。
* * @param InstancePtr 是指向 XGpioPs 实例的指针。
* @param Bank 是要操作的 GPIO 的 Bank 号。
* Zynq 中的有效值为 0-3,Zynq Ultrascale+ MP 中的有效值为 0-5。
* @param Mask 是要启用中断的引脚的位掩码。位位置 1 将被启用。位位置 
* 为 0 将保留先前的设置。
* * @返回无。
* * @note 无。
********************************************************* **************************/
/****************************************************************************/
/**
*
* This function enables the interrupts for the specified pins in the specified
* bank.
*
* @param	InstancePtr is a pointer to the XGpioPs instance.
* @param	Bank is the bank number of the GPIO to operate on.
*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param	Mask is the bit mask of the pins for which interrupts are to
*		be enabled. Bit positions of 1 will be enabled. Bit positions
*		of 0 will keep the previous setting.
*
* @return	None.
*
* @note		None.
*
*****************************************************************************/
void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask)
{Xil_AssertVoid(InstancePtr != NULL);Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versalif(InstancePtr->PmcGpio == (u32)TRUE) {Xil_AssertVoid(Bank != XGPIOPS_TWO);} else {Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));}
#endifXGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +XGPIOPS_INTEN_OFFSET, Mask);
}

步骤8:使能中断控制器中的gpio中断XScuGic_Enable()

void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id)

/******************************************************** **************************/ 
/** * * 启用作为参数 Int_Id 提供的中断源。 
* 调用此函数后,将发生指定 Int_Id 的任何未决中断条件。
* 该 API 还将中断映射到请求的 CPU。
* * @param InstancePtr 是指向 XScuGic 实例的指针。
* @param Int_Id 包含中断源的 ID,并且应该 * 在 0 到 XSCUGIC_MAX_NUM_INTR_INPUTS - 1 的范围内 * * @return None。
* * @note 无。
********************************************************* **************************/
/*****************************************************************************/
/**
*
* Enables the interrupt source provided as the argument Int_Id. Any pending
* interrupt condition for the specified Int_Id will occur after this function is
* called.
* This API also maps the interrupt to the requesting CPU.
*
* @param	InstancePtr is a pointer to the XScuGic instance.
* @param	Int_Id contains the ID of the interrupt source and should be
*		in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id)
{u32 Mask;u8 Cpu_Identifier = (u8)CpuId;#if defined (GICv3)u32 Temp;
#endif/** Assert the arguments*/Xil_AssertVoid(InstancePtr != NULL);Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);#if defined (GICv3)if (Int_Id < XSCUGIC_SPI_INT_ID_START) {Int_Id &= 0x1f;Int_Id = 1 << Int_Id;Temp = XScuGic_ReDistSGIPPIReadReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET);Temp |= Int_Id;XScuGic_ReDistSGIPPIWriteReg(InstancePtr,XSCUGIC_RDIST_ISENABLE_OFFSET,Temp);return;}
#endifXScuGic_InterruptMaptoCpu(InstancePtr, Cpu_Identifier, Int_Id);/** Call spinlock to protect multiple applications running at separate* CPUs to write to the same register. This macro also ensures that* the spinlock mechanism is used only if spinlock is enabled by* user.*/XIL_SPINLOCK();/** The Int_Id is used to create the appropriate mask for the* desired bit position.*/Mask = (u32)0x00000001U << (Int_Id % 32U);/** Enable the selected interrupt source by setting the* corresponding bit in the Enable Set register.*/XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET +((Int_Id / 32U) * 4U), Mask);/** Release the lock previously taken. This macro ensures that the lock* is given only if spinlock mechanism is enabled by the user.*/XIL_SPINUNLOCK();
}

步骤9:使能异常处理Xil_ExceptionEnableMask()

/****************************************************************************/
/**
* @brief	Enable the IRQ exception.
*
* @return   None.
*
* @note     None.
*
******************************************************************************/
#if (defined (versal) && !defined(ARMR5) && EL3) || defined(ARMR52)
#define Xil_ExceptionEnable() \Xil_ExceptionEnableMask(XIL_EXCEPTION_FIQ)
#else
#define Xil_ExceptionEnable() \Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ)
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/149539.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue-img-cutter 实现图片裁剪[vue 组件库]

借助 vue-img-cutter 可以在网页端实现图片裁剪功能&#xff0c;最终功能效果如下&#xff1a; 组件 npm 安装 npm install vue-img-cutter2 --save-dev # for vue2 npm install vue-img-cutter3 --save-dev # for vue3vue-img-cutter使用 template模板标签模块&#xff0c…

JavaScript系列从入门到精通系列第十七篇:JavaScript中的全局作用域

文章目录 前言 1&#xff1a;什么叫作用域 一&#xff1a;全局作用域 1&#xff1a;全局变量的声明 2&#xff1a;变量声明和使用的顺序 3&#xff1a;方法声明和使用的顺序 前言 1&#xff1a;什么叫作用域 可以起作用的范围 function fun(){var a 1; } fun();consol…

MFC ExtTextOut函数学习

ExtTextOut - 扩展的文本输出&#xff1b; win32 api的声明如下&#xff1b; ExtTextOut( DC: HDC; {设备环境句柄} X, Y: Integer; {起点坐标} Options: Longint; {选项} Rect: PRect; {指定显示范围; 0 表示限制范围} Str: PChar; {字符串…

论文笔记:TMN: Trajectory Matching Networks for PredictingSimilarity

2022 ICDE 1 intro 1.1 背景 轨迹相似度可以划分为&#xff1a; 非学习度量方法 通常是为一两个特定的轨迹距离度量设计的&#xff0c;因此不能与其他度量一起使用通常需要二次时间&#xff08;O(n^2)&#xff09;来计算轨迹之间的精确距离基于学习的度量方法 利用机器学习…

伟大不能被计划

假期清理书单&#xff0c;把这个书读完了&#xff0c;结果发现出奇的好&#xff0c;可以说是值得亲身去读的书&#xff0c;中间的一些论述提供了人工智能专业方面的视角来论证这这个通识观点&#xff0c;可信度很不错&#xff1b; 这篇blog也不是对书的总结&#xff0c;更多的是…

Python(八十八)函数的参数传递

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

【进阶C语言】排序函数(qsort)与模拟实现(回调函数的实例)

本章大致内容目录&#xff1a; 1.认识回调函数 2.排序函数qsort 3.模拟实现qsort 回调函数为C语言重要知识点&#xff0c;以函数指针为主要知识&#xff1b;下面介绍回调函数的定义、回调函数的库函数举例即库函数模拟实现。 一、回调函数 1.回调函数定义 回调函数就是一…

华为MateBook13 2021款(WRTD-WFE9)原装出厂Win10系统工厂模式安装包(含F10智能还原)

下载链接&#xff1a;https://pan.baidu.com/s/1yL7jFbklrln0UqWqxQ7fcw?pwd9nm1 系统自带一键智能还原功能、带有指纹、声卡、显卡、网卡等所有驱动、出厂主题壁纸、系统属性华为专属LOGO标志、Office办公软件、华为电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U…

基于Java的企业人事管理系统设计与实现(源码+lw+ppt+部署文档+视频讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

【C语言】利用数组处理批量数据(字符数组)

前言:前面已经介绍了&#xff0c;字符数据是以字符的ASCII代码存储在存储单元中的&#xff0c;一般占一个字节。由于ASCII代码也属于整数形式&#xff0c;因此在C99标准中&#xff0c;把字符类型归纳为整型类型中的一种。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x…

【linux进程(二)】如何创建子进程?--fork函数深度剖析

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; 进程状态管理 1. 前言2. 查看…

linux常见命令以及jdk,tomcat环境搭建

目录 Is pwd cd touch cat echo vim 复制粘贴 mkdir rm cp jdk部署 1. yum list | grep jdk进行查找​编辑 2.安装​编辑 3.再次确认 4.判断是否安装成功 tomcat安装 1.下载压缩包&#xff0c;把压缩包上传至linux(可能需要yum install lrzsz) 2.解压缩unzip 压缩包名&…

【16】c++设计模式——>建造者(生成器)模式

什么是建造者模式? 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许你构造复杂对象步骤分解。你可以不同的步骤中使用不同的方式创建对象&#xff0c;且对象的创建与表示是分离的。这样&#xff0c;同样的构建过程可以创建不同的表…

[论文工具] LaTeX论文撰写常见用法及实战技巧归纳(持续更新)

祝大家中秋国庆双节快乐&#xff01; 回过头来&#xff0c;我们在编程过程中&#xff0c;经常会遇到各种各样的问题。然而&#xff0c;很多问题都无法解决&#xff0c;网上夹杂着各种冗余的回答&#xff0c;也缺乏系统的实战技巧归纳。为更好地从事科学研究和编程学习&#xff…

自动驾驶:未来的道路上的挑战与机遇

自动驾驶&#xff1a;未来的道路上的挑战与机遇 文章目录 引言安全与道路事故的减少交通拥堵的缓解城市规划的变革技术和法律挑战结语 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;…

Mac上protobuf环境构建-java

参考文献 getting-started 官网pb java介绍 maven protobuf插件 简单入门1 简单入门2 1. protoc编译器下载安装 https://github.com/protocolbuffers/protobuf/releases?page10 放入.zshrc中配置环境变量  ~/IdeaProjects/test2/ protoc --version libprotoc 3.12.1  …

Spring基础以及核心概念(IoC和DIQ)

1.Spring是什么 Spring是包含了众多工具方法的IoC容器 2.loC&#xff08;Inversion of Control &#xff09;是什么 IoC:控制反转,Spring是一个控制反转容器(控制反转对象的生命周期) Spring是一个loC容器&#xff0c;我们之前学过的List/Map就是数据存储的容器&#xff0c;to…

数据结构—栈、队列、链表

一、栈 Stack&#xff08;存取O(1)&#xff09; 先进后出&#xff0c;进去123&#xff0c;出来321。 基于数组&#xff1a;最后一位为栈尾&#xff0c;用于取操作。 基于链表&#xff1a;第一位为栈尾&#xff0c;用于取操作。 1.1、数组栈 /*** 基于数组实现的顺序栈&#…

【C++】运算符重载 ⑧ ( 左移运算符重载 | 友元函数 / 成员函数 实现运算符重载 | 类对象 使用 左移运算符 )

文章目录 一、左移运算符重载1、友元函数 / 成员函数 实现运算符重载2、类对象 使用 左移运算符3、左移运算符 << 重载 二、完整代码示例 一、左移运算符重载 1、友元函数 / 成员函数 实现运算符重载 运算符重载 的正规写法一般都是 使用 成员函数 的形式 实现的 ; 加法…

Android笔记:Android 组件化方案探索与思考

组件化项目&#xff0c;通过gradle脚本&#xff0c;实现module在编译期隔离&#xff0c;运行期按需加载&#xff0c;实现组件间解耦&#xff0c;高效单独调试。 先来一张效果图 组件化初衷 APP版本不断的迭代&#xff0c;新功能的不断增加&#xff0c;业务也会变的越来越复杂…