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