八、MCMCAN中断配置

张开发
2026/4/11 23:29:19 15 分钟阅读

分享文章

八、MCMCAN中断配置
对MCMCAN进行初始化时要对CAN node的中断相关功能进行初始化配置MCMCAN的作用就是当CAN控制器发生了需要软件立即处理的事情比如收发、错误、状态变化、缓存异常等事件时硬件主动通知CPU而不是让CPU一直轮询寄存器。比如Rx收到了新的报文如果没有中断的话就需要一直轮询有没有收到新的报文这样会浪费CPU有了中断机制的话CPU可以做其他的事情只有当事件发生了以后才进入中断服务请求。typedef struct { boolean rxFifo0NewMessageEnabled; /** \brief Rx FIFO 0 New Message Interrupt enable/Disable */ boolean rxFifo0WatermarkEnabled; /** \brief Rx Fifo 0 Watermark Interrupt enable/Disable */ boolean rxFifo0FullEnabled; /** \brief Rx Fifo 0 Full Interrupt enable/Disable */ boolean rxFifo0MessageLostEnabled; /** \brief Rx FIFO 0 Message Lost Interrupt enable/Disable */ boolean rxFifo1NewMessageEnabled; /** \brief Rx FIFO 1 New Message Interrupt enable/Disable */ boolean rxFifo1WatermarkEnabled; /** \brief Rx FIFO 1 Watermark Reached Interrupt enable/Disable */ boolean rxFifo1FullEnabled; /** \brief Rx FIFO 1 Full Interrupt enable/Disable */ boolean rxFifo1MessageLostEnabled; /** \brief Rx FIFO 1 Message Lost Interrupt enable/Disable */ boolean highPriorityMessageEnabled; /** \brief High Priority Message Interrupt enable/Disable */ boolean transmissionCompletedEnabled; /** \brief Transmission Completed Interrupt enable/Disable */ boolean transmissionCancellationFinishedEnabled; /** \brief Transmission Cancellation Finished Interrupt enable/Disable */ boolean txFifoEmptyEnabled; /** \brief Tx FIFO Empty Interrupt enable/Disable */ boolean txEventFifoNewEntryEnabled; /** \brief Tx Event FIFO New Entry Interrupt enable/Disable */ boolean txEventFifoWatermarkEnabled; /** \brief Tx Event FIFO Watermark Reached Interrupt enable/Disable */ boolean txEventFifoFullEnabled; /** \brief Tx Event FIFO Full Interrupt enable/Disable */ boolean txEventFifoEventLostEnabled; /** \brief Tx Event FIFO Event Lost Interrupt enable/Disable */ boolean timestampWraparoundEnabled; /** \brief Timestamp Wraparound Interrupt enable/Disable */ boolean messageRAMAccessFailureEnabled; /** \brief Message RAM Access Failure Interrupt enable/Disable */ boolean timeoutOccurredEnabled; /** \brief Timeout Occurred Interrupt enable/Disable */ boolean messageStoredToDedicatedRxBufferEnabled; /** \brief Message stored to Dedicated Rx Buffer Interrupt enable/Disable */ boolean errorLoggingOverflowEnabled; /** \brief Error Logging Overflow Interrupt enable/Disable */ boolean errorPassiveEnabled; /** \brief Error Passive Interrupt enable/Disable */ boolean warningStatusEnabled; /** \brief Warning Status Interrupt enable/Disable */ boolean busOffStatusEnabled; /** \brief Bus_Off Status Interrupt enable/Disable */ boolean watchdogEnabled; /** \brief Watchdog Interrupt enable/Disable */ boolean protocolErrorArbitrationEnabled; /** \brief Protocol Error in Arbitration phase Interrupt enable/Disable */ boolean protocolErrorDataEnabled; /** \brief Protocol Error in Data phase Interrupt enable/Disable */ IfxCan_GroupInterruptConfig tefifo; /** \brief Configuration for Transmit Event FIFO Incidents interrupts */ IfxCan_GroupInterruptConfig hpe; /** \brief Configuration for High Priority Events interrupts */ IfxCan_GroupInterruptConfig wati; /** \brief Configuration for Watermark interrupts */ IfxCan_GroupInterruptConfig alrt; /** \brief Configuration for Alerts interrupts */ IfxCan_GroupInterruptConfig moer; /** \brief Configuration for Module errors interrupts */ IfxCan_GroupInterruptConfig safe; /** \brief Configuration for Safety counter overflow interrupt */ IfxCan_GroupInterruptConfig boff; /** \brief Configuration for Bus Off interrupt */ IfxCan_GroupInterruptConfig loi; /** \brief Configuration for Last Error interrupts */ IfxCan_GroupInterruptConfig reint; /** \brief Configuration for iMessage stored in dedicated receive buffer interrupts */ IfxCan_GroupInterruptConfig rxf1f; /** \brief Configuration for Receive FIFO1 full interrupts */ IfxCan_GroupInterruptConfig rxf0f; /** \brief Configuration for Receive FIFO0 full interrupts */ IfxCan_GroupInterruptConfig rxf1n; /** \brief Configuration for Receive FIFO1 new message interrupts */ IfxCan_GroupInterruptConfig rxf0n; /** \brief Configuration for Receive FIFO0 new message interrupts */ IfxCan_GroupInterruptConfig reti; /** \brief Configuration for Receive Timeouts interrupts */ IfxCan_GroupInterruptConfig traq; /** \brief Configuration for Transmission Queue Events interrupts */ IfxCan_GroupInterruptConfig traco; /** \brief Configuration for interrupts of the transmission control */ } IfxCan_Can_InterruptConfig;以上是MCMCAN的中断配置的结构体包含了所有的中断位和中断组。所谓中断位就是对应IR寄存器的不同bit代表的中断标记位当产生对应的硬件中断时IR寄存器对应中断类型的bit位置1。上面结构体当中的前27项一一对应IR寄存器的27个有实际意义的bit位。中断组所谓中断组就是把32个中断源或者说中断bit位按照功能归类为16个group。因为MCMCAN内部的原始事件有很多不适合把每个事件都单独占一条输出线所以最好就是把这些事件按照功能分类比如接收类、发送类、watermark类、错误处理类等。下图为中断标志位的大致分组情况黑色方框中的第一行为分组名称一共16个分组每个分组都可以对应上面结构体当中的一个IfxCan_GroupInterruptConfig类型尘缘第二行为该分组包含的中断标记位有的中断组只包含了一个中断标记位有的包含多个都是按功能进行分组的。比如第一个Receive Interrupt组对应结构体中的IfxCan_GroupInterruptConfig reint成员分量包含的中断标记位仅有一个为DRX表示报文被存到了Dedicated Rx Buffer中还有Alert组是多个“告警类”源合并对应结构体中的IfxCan_GroupInterruptConfig alrt成员分量包含多个标记位有EW:Error WarningRF0L:Rx FIFO0 Message LostTSWTimeStamp Wraparound等中断标记位。图中组别旁边还有“1”的字样代表逻辑或的意思只要这一个中断组有一个中断标志位被置为1那么一个组的输出就为1。这就意味着组内的任意一个中断事件触发对于硬件来说都是触发同一个中断信号。从软件层面讲进入这组中断组对应的中断处理函数当中还必须继续去读IR寄存器来判断究竟是组内的哪一个中断标志位触发了中断。就如上图中所示Transmission Control触发了断进入了ISR中断处理函数还得继续判断是TCF触发的还是TC触发的。每一组中断组都对应一条interrupt router/line对于AURIX TC3XX系列芯片有16条这样的中断输出通道在进行中断相关配置的时候用户需要明确使用的中断的类型要将中断组结构体中的interruptline字段配好如下代码段所示。typedef struct { IfxCan_InterruptLine interruptLine; /** \brief Intterupt line to which this interruipt has to be connetced to */ Ifx_Priority priority; /** \brief Priority of the interrupt */ IfxSrc_Tos typeOfService; /** \brief Type of Service */ } IfxCan_GroupInterruptConfig; g_mcmcan.canNodeConfig.interruptConfig.transmissionCompletedEnabled TRUE; g_mcmcan.canNodeConfig.interruptConfig.traco.priority ISR_PRIORITY_CAN_TX; g_mcmcan.canNodeConfig.interruptConfig.traco.interruptLine IfxCan_InterruptLine_0; g_mcmcan.canNodeConfig.interruptConfig.traco.typeOfService IfxSrc_Tos_cpu0;Interruptline不是外部的16根中断线而是16个芯片内部的硬件路由通道MCMCAN模块对中断控制系统暴露了16个可编号的中断请求出口。在软件里就用IfxCan_InterruptLine_0~15来选择。选择了InterruptLine之后如果该line关联的中断组产生了中断那么该line会继续送到对应的Service Request ControlSRC。SRC是中断请求交给系统处理前的“控制与分发单元”它的作用简单而言就是判断这路中断请求是否使能、优先级是多少、该送给CPU哪个核处理还是交给DMA去处理类似一个中断总机前台一样的角色它解决的问题是这个请求能不能送出去送给谁优先级是多少SRC里通常控制1SRPN------中断优先级也就是上面代码里体现的priority2TOS 目标服务对象通常是CPU几或DMA3SRE 是否使能这个service request。所以SRC也会做“门控”即便前面的IR位置了IE使能也打开了硬件中断确实产生了也通过InterruptLine找到了SRC但如果SRC没有打开SRE这个中断也无法让CPU响应中断去处理进入后续的ISR中断处理函数。当SRC成功请求CPU处理中断以后CPU会进入Interrupt Service RequestISR路径是中断组的请求通过InterruptLine发送到SRCSRC根据优先级和目前处理单元发起中断处理目标处理单元跳进对应的ISRISR实际就是我们C代码当中的中断处理函数。进了ISR以后要先查IR看是中断组的哪个中断标志位置1了要把它清掉防止一直捅中断请求上来然后要根据中断类型做软件想要做的事情。以上就是大致的CAN中断处理流程。接下来以具体的iLLD代码示例来学习MCMCAN中断的具体配置方式首先在初始化阶段要根据具体实现的功能的进行中断初始化如下/* 中断配置, TX 完成中断 */ g_mcmcan.canNodeConfig.interruptConfig.transmissionCompletedEnabled TRUE; g_mcmcan.canNodeConfig.interruptConfig.traco.priority ISR_PRIORITY_CAN_TX; g_mcmcan.canNodeConfig.interruptConfig.traco.interruptLine IfxCan_InterruptLine_0; g_mcmcan.canNodeConfig.interruptConfig.traco.typeOfService IfxSrc_Tos_cpu0; /* 中断配置, RX 中断 */ g_mcmcan.canNodeConfig.interruptConfig.messageStoredToDedicatedRxBufferEnabled TRUE; g_mcmcan.canNodeConfig.interruptConfig.reint.priority ISR_PRIORITY_CAN_RX; g_mcmcan.canNodeConfig.interruptConfig.reint.interruptLine IfxCan_InterruptLine_1; g_mcmcan.canNodeConfig.interruptConfig.reint.typeOfService IfxSrc_Tos_cpu0;本例要对通过dedicated buffer做发送以及期望本CAN节点可以对外发送CAN报文那么就要使能传输完成中断以及消息dedicated buffer有新的报文存入的中断且对应中断组的优先级和中断路由、想由哪一个处理单元来处理中断都要进行初始化的配置Tx发送由cpu0响应走路由1Rx专用buffer接收到消息使用路由1也由cpu0处理中断。初始化完成后要针对初始化好的中断组进行具体的配置如下// interrupt groups configuration volatile Ifx_SRC_SRCR *srcPointer; if ((config-interruptConfig.tefifo.priority 0) || (config-interruptConfig.tefifo.typeOfService IfxSrc_Tos_dma)) { IfxCan_Node_setGroupInterruptLine(nodeSfr, IfxCan_InterruptGroup_tefifo, config-interruptConfig.tefifo.interruptLine); srcPointer IfxCan_getSrcPointer(config-can, config-interruptConfig.tefifo.interruptLine); IfxSrc_init(srcPointer, config-interruptConfig.tefifo.typeOfService, config-interruptConfig.tefifo.priority); IfxSrc_enable(srcPointer); } if ((config-interruptConfig.hpe.priority 0) || (config-interruptConfig.hpe.typeOfService IfxSrc_Tos_dma)) { IfxCan_Node_setGroupInterruptLine(nodeSfr, IfxCan_InterruptGroup_hpe, config-interruptConfig.hpe.interruptLine); srcPointer IfxCan_getSrcPointer(config-can, config-interruptConfig.hpe.interruptLine); IfxSrc_init(srcPointer, config-interruptConfig.hpe.typeOfService, config-interruptConfig.hpe.priority); IfxSrc_enable(srcPointer); } ... // 16组中断group均在这里进行判断和配置以上代码段所示为iLLD库对中断组的配置片段由于MCMCAN由16个中断组所以这样的配置会有16个以上片段仅节选用于说明对于每个中断组均进行了priority是否大于0的判断。priority对应芯片SRC寄存器的SRPN字段通过上图对优先级数字的字段SRPN的描述可以知道对于服务类型为CPU处理的中断priority最小是0x1而如果你的TOS是CPU中断链路都配通了但是priority配的是0CPU一样不会去响应该中断请求的。priority为0仅针对服务类型为DMA服务的场景有意义如果服务类型配置为DMA那么**priority 0**它表示的是触发DMA的channel 0。但是也需要注意当配置为DMA模式时SRPN字段的值代表的是使用DMA的哪个channel来处理。所以当为DMA模式时SRPN配的数值不可以大于芯片最大的DMA通道数。所以这就解释了上面的代码为什么进入对应中断组的配置之前要判断priority 0 || TOS DMA如果是CPU处理中断的话必要求priority 0但是如果是DMA处理的话就不作这个要求。进入中断配置以后先进行中断组对应的interruptLine的配置。IfxCan_Node_setGroupInterruptLine(nodeSfr, IfxCan_InterruptGroup_tefifo, config-interruptConfig.tefifo.interruptLine); void IfxCan_Node_setGroupInterruptLine(Ifx_CAN_N *node, IfxCan_InterruptGroup interruptGroup, IfxCan_InterruptLine interruptLine) { if (interruptGroup IfxCan_InterruptGroup_loi) { node-GRINT1.U | (interruptLine) (interruptGroup * 4); } else { node-GRINT2.U | (interruptLine) ((interruptGroup % 8) * 4); } }配置的是GRINT1和GRINT2两个寄存器Interrupt routing for Groups以GRINT2为例由于中断组有16个每个中断组可能分配到的InterruptLine的编号为0~15也就是0xF共占4个bit一个寄存器存放32个bit所以一个寄存器最多只能配置8个中断组的路由编号。所以这里分两个寄存器GRINT1和GRINT2来配置16个组如上述代码段中以第8个中断组LOI为分界线它以前的就配在GRINT1否则配在GRINT2。并且根据group的索引序号×4bit进行移位把InterruptLine配置到对应的中断组的4bit地址空间中。接下来根据interruptLine来获取对应的SRC。srcPointer IfxCan_getSrcPointer(config-can, config-interruptConfig.tefifo.interruptLine); volatile Ifx_SRC_SRCR *IfxCan_getSrcPointer(Ifx_CAN *can, IfxCan_InterruptLine interruptLine) { IfxCan_Index canIndex IfxCan_getIndex(can); Ifx_SRC_CAN_CAN *const srcCanBaseAddress[IFXCAN_NUM_MODULES] { MODULE_SRC.CAN.CAN[0], MODULE_SRC.CAN.CAN[1], }; return (srcCanBaseAddress[canIndex]-INT[interruptLine]); }传入的can就是最开始初始化的can控制器的基地址TC3XX系列芯片有两个CAN控制器其实就是初始化CAN模块时传入的MUDULE_CAN0/* 初始化CAN 模块 */ IfxCan_Can_initModuleConfig(g_mcmcan.canConfig, MODULE_CAN0);MODULE_SRC.CAN.CAN[0]、MODULE_SRC.CAN.CAN[1]这个分别代表的是CAN控制器0和1对应的SRC的基地址。因为每个 CAN 模块在SRC里都有自己的一组 INT[0…15] 服务请求寄存器。然后以interruptLine为索引找到对应的SRC。简而言之先用参数can确定是哪一个 CAN控制器的SRC块再用interruptLine直接索引该模块的**INT[line]**寄存器。IFX_INLINE void IfxSrc_init(volatile Ifx_SRC_SRCR *src, IfxSrc_Tos typOfService, Ifx_Priority priority) { src-B.SRPN priority; src-B.TOS typOfService; IfxSrc_clearRequest(src); }通过地址计算和interruptLine作为索引拿到对应的SRC寄存器之后就需要执行IfxSrc_init来对该中断组的优先级和TOS服务类型进行真正的配置。IfxSrc_clearRequest(src);这里的清除request是指清除掉当前SRC当中可能处于pending状态的残留中断请求防止SRC配置好以后控制器响应残留挂起的中断请求具体就是写了对应SRC的CLRR寄存器IFX_INLINE void IfxSrc_clearRequest(volatile Ifx_SRC_SRCR *src) { src-B.CLRR 1; }清除完成以后最后执行IfxSrc_enable(srcPointer);完成一个中断SRC的配置如上所述16个中断组会依次按priority和TOS来判断满足条件则进行SRC的配置。IFX_INLINE void IfxSrc_enable(volatile Ifx_SRC_SRCR *src) { src-B.SRE 1; }通过配置SRE寄存器可以使能该SRC使能过后SRC就可以把中断请求送发给CPU或者DMA处理否则上来的中断请求只能在SRC当中pending无法交给CPU处理。最后将SRC配置好后根据用户初始化的情况使能具体的中断使能位对应上文中的IR寄存器的27个BIT位/* enable the selected interrupts */ if (config-interruptConfig.rxFifo0NewMessageEnabled) { IfxCan_Node_enableInterrupt(nodeSfr, IfxCan_Interrupt_rxFifo0NewMessage); } if (config-interruptConfig.rxFifo0WatermarkEnabled) { IfxCan_Node_enableInterrupt(nodeSfr, IfxCan_Interrupt_rxFifo0WatermarkReached); } if (config-interruptConfig.rxFifo0FullEnabled) { IfxCan_Node_enableInterrupt(nodeSfr, IfxCan_Interrupt_rxFifo0Full); } if (config-interruptConfig.rxFifo0MessageLostEnabled) { IfxCan_Node_enableInterrupt(nodeSfr, IfxCan_Interrupt_rxFifo0MessageLost); } ...... // 对应IR寄存器的的27个中断使能位根据用户CAN中断配置结构体中设定的哪些中断需要enable依次进行IE寄存器配置配置函数如下 IFX_INLINE void IfxCan_Node_enableInterrupt(Ifx_CAN_N *node, IfxCan_Interrupt interrupt) { uint32 mask (1U interrupt); node-IE.U node-IE.U | (mask); }以上就是MCMCAN中断相关配置的介绍可根据本文内容进行基本的MCMCAN中断配置如需深入理解还需要继续对芯片有用户手册的16章中断IR部分进行深入学习和理解才可对整体的中断流程融会贯通。

更多文章