温度监控模块主要提供的功能比较少,主要以下:
- 当前温度
- 温度告警
- 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); } } } }