这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 行业应用 » 汽车电子 » 【S32K3XX】INTM 模块配置使用

共1条 1/1 1 跳转至

【S32K3XX】INTM 模块配置使用

高工
2026-05-21 17:26:06     打赏

【简介】

S32K3 系列芯片中集成了 INTM 的IP 模块,该模块可以用来监测中断的响应时间,对应的IP的框图如下:

image.png

以下是INTM 模块的功能概述和配置流程说明。

image.png

image.png

结合以上的框图和功能描述可知,INTM 的使用也比较简单,只需要简单的配置几个寄存器通过INTM->IRQSELX 寄存器配置要监测的IRQ index 信息,选择好要监测的IRQ 信号后,通过INTM->LATENCYX 寄存器来配置允许的最大的中断延迟,当对应的IRQ 中断信号被拉起时INTM->TIMERX 开始计数,当中断函数响应的时候通过INTM->IACK 寄存器写1 停止INTM->TIMERX 的计数器,此时如果INTM->TIMERX 数值 大于INTM->IRQSELX 寄存器就会触发异常状态。

原理我们介绍的差不多了,我们在S32DS 的 config tool 中加载INTM IP 就会把对应的驱动程序加入到工程中。

image.png

image.png

   更新代码后INTM 的驱动代码就被加入到工程中了。

image.png

以下是INTM 的驱动代码,从驱动代码配置也可以看出这个IP的功能还是很精简的没有复杂的寄存器配置,驱动接口只是对寄存器进行了一层封装。

**
 * @brief         Enables interrupt monitoring feature.
 *
 * @details       This function is non-reentrant and enables the interrupt monitors.
 *
 * @return        void
 *
 * @api
 *
 * @implements    Intm_Ip_EnableMonitor_Activity
 *
 * */
static inline void Intm_Ip_EnableMonitor(void)
{
IP_INTM->INTM_MM |= INTM_INTM_MM_MM_MASK;
}

/**
 * @brief         Disables interrupt monitoring feature.
 *
 * @details       This function is non-reentrant and disables the interrupt monitors.
 *
 * @return        void
 *
 * @api
 *
 * @implements    Intm_Ip_DisableMonitor_Activity
 *
 * */
static inline void Intm_Ip_DisableMonitor(void)
{
IP_INTM->INTM_MM &= ~(INTM_INTM_MM_MM_MASK);
}

/**
 * @brief         Acknowledges a monitored interrupt.
 *
 * @details       This function is reentrant; it acknowledges that a monitored interrupt
 *                has been been served.
 *
 * @param[in]     eIrqNumber: The interrupt vector acknowledged.
 * @return void
 *
 * @api
 *
 * @implements    Intm_Ip_AckIrq_Activity
 *
 * */
static inline void Intm_Ip_AckIrq(IRQn_Type eIrqNumber)
{
#if (INTM_IP_DEV_ERROR_DETECT == STD_ON)
sint32 s32DevIrqNumber = (sint32)eIrqNumber;

DevAssert((sint32)INTM_IP_MIN_IRQ <= s32DevIrqNumber);
DevAssert(s32DevIrqNumber <= (sint32)INTM_IP_MAX_IRQ);
#endif /*(INTM_IP_DEV_ERROR_DETECT == STD_ON) */
IP_INTM->INTM_IACK = ((uint32)eIrqNumber) & INTM_INTM_IACK_IRQ_MASK;
}

/**
 * @brief         Selects an interrupt to monitor.
 *
 * @details       This function is reentrant; it selects which interrupt is monitored on
 *                a specific interrupt monitor.
 *
 * @param[in]     eMonitorIdx: The index of the interrupt monitor used.
 * @param[in]     eIrqNumber: The interrupt vector to be monitored.
 * @return void
 *
 * @api
 *
 * @implements    Intm_Ip_SelectMonitoredIrq_Activity
 *
 * */
static inline void Intm_Ip_SelectMonitoredIrq(Intm_Ip_MonitorType eMonitorIdx, IRQn_Type eIrqNumber)
{
#if (INTM_IP_DEV_ERROR_DETECT == STD_ON)
sint32 s32DevIrqNumber = (sint32)eIrqNumber;

DevAssert((sint32)INTM_IP_MIN_IRQ <= s32DevIrqNumber);
DevAssert(s32DevIrqNumber <= (sint32)INTM_IP_MAX_IRQ);
#endif /*(INTM_IP_DEV_ERROR_DETECT == STD_ON) */
IP_INTM->MON[(uint8)eMonitorIdx].INTM_IRQSEL = ((uint32)eIrqNumber) & INTM_INTM_IRQSEL_IRQ_MASK;
}

/**
 * @brief         Sets the latency for a monitored interrupt.
 *
 * @details       This function is reentrant; it sets the accepted latency for the
 *                monitored interrupt.
 *
 * @param[in]     eMonitorIdx: The index of the interrupt monitor used.
 * @param[in]     u32Latency: The accepted latency for the monitored interrupt.
 * @return void
 *
 * @api
 *
 * @implements    Intm_Ip_SetLatency_Activity
 *
 * */
static inline void Intm_Ip_SetLatency(Intm_Ip_MonitorType eMonitorIdx, uint32 u32Latency)
{
IP_INTM->MON[(uint8)eMonitorIdx].INTM_LATENCY = (u32Latency & INTM_INTM_LATENCY_LAT_MASK);
}

/**
 * @brief         Resets the timer for an interrupt monitor.
 *
 * @details       This function is reentrant; it resets the timer for the interrupt monitor.
 *
 * @param[in]     eMonitorIdx: The index of the interrupt monitor used.
 * @return void
 *
 * @api
 *
 * @implements    Intm_Ip_ResetTimer_Activity
 *
 * */
static inline void Intm_Ip_ResetTimer(Intm_Ip_MonitorType eMonitorIdx)
{
IP_INTM->MON[(uint8)eMonitorIdx].INTM_TIMER = 0UL;
}

/**
 * @brief         Returns the status of an interrupt monitor.
 *
 * @details       This function is reentrant; it returns the status of an interrupt monitor:
 *                0 - latency not exceeded; 1 - timer exceeded latency.
 *
 * @param[in]     eMonitorIdx: The index of the interrupt monitor used.
 * @return        uint8: 0 - latency not exceeded; 1 - timer exceeded latency.
 *
 * @api
 *
 * @implements    Intm_Ip_GetStatus_Activity
 *
 * */
static inline uint8 Intm_Ip_GetStatus(Intm_Ip_MonitorType eMonitorIdx)
{
return (uint8)(IP_INTM->MON[(uint8)eMonitorIdx].INTM_STATUS & INTM_INTM_STATUS_STATUS_MASK);
}

本地添加如下的测试代码来监测I2C 中断的延迟,在中断中打印中断的延迟周期及是否超时的状态。

static int i2c_init(void)
{
    /* Init i2c master */
    Lpi2c_Ip_MasterInit(LPI2C_CHANNEL_0,&I2c_Lpi2cMaster_HwChannel1_Channel0);
    LOG_I("I2C init.");
#ifdef CFG_I2C1_IRQ_INTM_CHANNEL
    Intm_Ip_SelectMonitoredIrq(CFG_I2C1_IRQ_INTM_CHANNEL,LPI2C1_IRQn);
    Intm_Ip_SetLatency(CFG_I2C1_IRQ_INTM_CHANNEL,0X1000);
    Intm_Ip_EnableMonitor();
    LOG_I("I2C1 INTM");
#endif
    return 1;
}

/* LPI2C1 master and slave handler named in startup code. */
ISR(LPI2C1_Master_Slave_IRQHandler)
{
#ifdef CFG_I2C1_IRQ_INTM_CHANNEL
    Intm_Ip_AckIrq(LPI2C1_IRQn);
    printf("i2c1 %ld.status %d\r\n",
            Intm_Ip_GetTimer(CFG_I2C1_IRQ_INTM_CHANNEL),
            Intm_Ip_GetStatus(CFG_I2C1_IRQ_INTM_CHANNEL));
    Intm_Ip_ResetTimer(CFG_I2C1_IRQ_INTM_CHANNEL);
#endif
    Lpi2c_Ip_ModuleIRQHandler(1U - (uint8)(LPI2C_IP_OFFSET_INSTANCE));
    EXIT_INTERRUPT();
}

被你的触发I2C 中断打印数据如下,测试代码设置的最大latency 为0x1000 未触发异常状态。

image.png

 修改测试代码将最大latency 为20来验证是否会触发异常状态。

image.png

配置为20后在此测试发现latency  > 20 时对应的状态打印已经为1了跟预期的一致

image.png


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]