IMXRT学习记录 – 温度监控

温度监控模块主要提供的功能比较少,主要以下:

  • 当前温度
  • 温度告警
    • kTEMPMON_HighAlarmMode – 温度过高报警
    • kTEMPMON_PanicAlarmMode – 温度严重过高报警
    • kTEMPMON_LowAlarmMode – 温度过低报警

外设试用RTC时钟,可分频,节约功耗,毕竟温度变化没有那么快的.

如果温度太高,我没可以将CPU降频(在电脑CPU上叫撞墙).温度过低也可以告警,这时候可以把频率重新提上来.(也可以理解成故障恢复),如果采取措施后依然不能降低温度,那可以发起Panic(另一个中断发起,可以进行更紧急的保护措施.)

注意:修改Core频率,可能会引起程序执行时间的不确定性,所以要谨慎考虑.

/* 温度太高,应该降频来降低温度. */
#define TEMP_HIGHALARMTEMP 50U
/* 温度恢复正常了,可以把时钟调回去. */
#define TEMP_LOWALARMTEMP 45U
/* 温度高得太离谱,建议立即停止任何操作. */
#define TEMP_PANICTEMP 60U

/* 当前温度 */
float temperature = 0U;
/* 用于交互的信号量 */
volatile SemaphoreHandle_t temperatureReach;

void TEMP_LOW_HIGH_IRQHandler(void)
{
    static BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(temperatureReach, &xHigherPriorityTaskWoken);

/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
#endif

    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void TEMP_PANIC_IRQHandler(void)
{
    static BaseType_t xHigherPriorityTaskWoken;
    xSemaphoreGiveFromISR(temperatureReach, &xHigherPriorityTaskWoken);

/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
#endif

    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

static void MainTask(void *pvParameters)
{
    tempmon_config_t config;

    /* 先创建信号量,用于中断上下文. */
    temperatureReach = xSemaphoreCreateBinary();

    /* 中断优先级必须小于configMAX_SYSCALL_INTERRUPT_PRIORITY,才可以在中断调用RTOS函数. */
    NVIC_SetPriority(TEMP_LOW_HIGH_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1);
    NVIC_SetPriority(TEMP_PANIC_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1);

    NVIC_ClearPendingIRQ(TEMP_LOW_HIGH_IRQn);
    NVIC_ClearPendingIRQ(TEMP_PANIC_IRQn);

    EnableIRQ(TEMP_LOW_HIGH_IRQn);
    EnableIRQ(TEMP_PANIC_IRQn);

    /* 配置温度监控,采样间隔为RTC/(3+1)时钟,并且设置警报数值. */
    TEMPMON_GetDefaultConfig(&config);
    config.frequency = 0x03U;
    config.highAlarmTemp = TEMP_HIGHALARMTEMP;
    config.lowAlarmTemp = TEMP_LOWALARMTEMP;
    config.panicAlarmTemp = TEMP_PANICTEMP;
    TEMPMON_Init(TEMPMON, &config);
    TEMPMON_StartMeasure(TEMPMON);

    for (;;)
    {
        /* 有信号量来了,说明温度出现了超过阈值的变化. */
        if (xSemaphoreTake(temperatureReach, portMAX_DELAY) == pdTRUE)
        {
            temperature = TEMPMON_GetCurrentTemperature(TEMPMON);
            if (temperature - TEMP_PANICTEMP > 0)
            {
                /* 温度高的离谱,切换系统到62.5MHz,并且把系统置于强制休眠. */
                CLOCK_SetDiv(kCLOCK_AhbDiv, 0x07);
                while (1)
                {
                    __WFI();
                }
            }
            else if (temperature - TEMP_HIGHALARMTEMP > 0)
            {
                /* 温度过高,切换系统到62.5MHz. */
                CLOCK_SetDiv(kCLOCK_AhbDiv, 0x07);
            }
            else if (temperature - TEMP_LOWALARMTEMP < 0)
            {
                /* 温度恢复正常,切换系统到500MHz. */
                CLOCK_SetDiv(kCLOCK_AhbDiv, 0x0);
            }
        }
    }
}

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注