中断管理
中断管理相比非中断的优势
1,简洁和效率。
2,同步和安全。提供了中断安全的操作,确保在中断上下文中执行时不会引发竞态条件或破坏系统状态。
3,通过配置中断的优先级,可以确保高优先级的中断能够立即响应,而低优先级的中断则可以在需要时等待
4,系统稳定性:非管理的中断通常直接将中断服务程序挂到中断向量表上,这需要用户自己处理上下文的保存与恢复。如果处理不当,可能会导致堆栈错误。相比之下,通过FreeRTOS进行中断管理可以确保这些操作的正确性和一致性,从而提高系统的稳定性。
FreeRTOS 中很多 API 函数都有两套,
为什么不使用同一套函数,在函数里面判断用任务还是ISR
使用同一套函数的话,需要增加额外的判断代码、增加额外的分支,是的
函数更长、更复杂、难以测试
在任务、ISR 中调用时,需要的参数不一样,
如果强行把两套函数揉在一起,会导致参数臃肿、无效
任务中使用 | ISR 中使用 | |
API函数会导致任务进入阻塞 | ISR不是任务,ISR不能进入阻塞 | |
需要指定超时时间,表示如果不成功就阻塞一会 | 不需要指定超时时间,无论是否成功都要即刻返回 | |
队列(queue) | xQueueSendToBack | xQueueSendToBackFromISR |
xQueueSendToFront | xQueueSendToFrontFromISR | |
xQueueReceive | xQueueReceiveFromISR | |
xQueueOverwrite | xQueueOverwriteFromISR | |
xQueuePeek | xQueuePeekFromISR | |
信号量(semaphore) | xSemaphoreGive | xSemaphoreGiveFromISR |
xSemaphoreTake | xSemaphoreTakeFromISR | |
事件组(event group) | xEventGroupSetBits | xEventGroupSetBitsFromISR |
xEventGroupGetBits | xEventGroupGetBitsFromISR | |
任务通知(task notification) | xTaskNotifyGive | vTaskNotifyGiveFromISR |
xTaskNotify | xTaskNotifyFromISR | |
软件定时器(software timer) | xTimerStart | xTimerStartFromISR |
xTimerStop | xTimerStopFromISR | |
xTimerReset | xTimerResetFromISR | |
xTimerChangePeriod | xTimerChangePeriodFromISR | |
xHigherPriorityTaskWoken 含义是:是否有更高优先级的任务被唤醒了。 如为pdTRUE,则意味着后面要进行任务切换。 *pxHigherPriorityTaskWoken 等于 pdTRUE:函数的操作导致更高优先级的任务就绪了,ISR 应该进行任务切换 *pxHigherPriorityTaskWoken 等于 pdFALSE:没有进行任务切换的必要 不在"FromISR"函数内部进行任务切换,而只是标记一下而已呢 这些带ISR后缀的函数,不会发起调度,会唤醒任务,但不会引起调度,会在xHigherPriorityTaskWoken记录是否需要调度 portYIELD_FROM_ISR(xHigherPriorityTaskWoken); 这条代码根据上面的变量来切换是否需要调度 这条代码是触发调度,不是即刻引起调度 |
//更改上诉的按键中断管理的代码
void EXTI0_IRQHandler(void)
{static int cnt = 0;BaseType_t xHigherPriorityTaskWoken;if(EXTI_GetITStatus(EXTI_Line0) != RESET){printf("EXTI0_IRQHandler cnt = %d\r\n", cnt++);/* 使用定时器消除抖动 */// xTimerReset(xMyTimerHandle, 0); /* Tcur + 2000 */ //按键触发后,复位定时器,如果有多次抖动,会多次复位,直至最后一次进入按键中断后,开始记录2000ms,这里的2000ms为了调试方便,实际运用20ms即可xTimerResetFromISR(xMyTimerHandle, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken);key_start = xTaskGetTickCount() ;printf("key_start = %d\r\n",key_start);EXTI_ClearITPendingBit(EXTI_Line0); //清除中断}
}