前言:本文参考,韦东山老师开发文档,连接放在最后。
为什么需要中断管理函数?
在FreeRtos操作系统中,需要实时响应性,也就是随时随地必须保证正常多任务的运行,如果有中断发生,因为中断的优先级是最高的,这就导致了,中断中不能有大量执行的任务函数,或者在中断中不能有大量的任务进行切换调用,保证中断的执行是一瞬间,保证RTOS的,实时响应性。否则多任务就不能并发运行。
这就导致了,在中断里面调用函数是不能有延迟等待的,和不能有更高优先级的任务进行切换的,如果有切换因为,中断函数的优先级始终是最高的,被切换的普通函数始终是执行不了的。
同时因为中断内不能有延时函数,所以就常用函数都有中断版本,专门用在中断函数内执行的函数,这些函数没有阻塞延时时间,有参数会记录是否有更高优先级的任务发生,如果有在中断结束后,进行任务切换执行,实际执行是在中断结束之后由任务调度器完成。
到这里,我们知道了,函数有中断版本,是为了保证中断中没有延时,同时在函数内没有函数调用,以及中断版本多出来的参数就是为了,记录是否有更高优先级的任务被调用,如果有在中断执行结束后,由任务调度器调用任务。
函数比较
FreeRtos操作系统的 队列 信号量 事件组 软件定时器 任务通知 都有两套版本的函数,一套用来调用在普通任务上下文,一套被用在中断任务上下文,具体表格如下。
类型 | 普通任务上下文 | 中断任务上下文 |
队列(queue) | xQueueSendToBack | xQueueSendToBackFromISR |
队列(queue) | xQueueSendToFront | xQueueSendToFrontFromISR |
队列(queue) | xQueueReceive | xQueueReceiveFromISR |
队列(queue) | xQueueOverwrite | xQueueOverwriteFromISR |
队列(queue) | xQueuePeek | xQueuePeekFromISR |
信号量(semaphore) | xSemaphoreGive | xSemaphoreGiveFromISR |
信号量(semaphore) | xSemaphoreTake | xSemaphoreTakeFromISR |
事件组(event group) | xEventGroupSetBits | xEventGroupSetBitsFromISR |
事件组(event group) | xEventGroupGetBits | xEventGroupGetBitsFromISR |
任务通知(task notification | xTaskNotifyGive | vTaskNotifyGiveFromISR |
任务通知(task notification | xTaskNotify | xTaskNotifyFromISR |
软件定时器(software timer) | xTimerStart | xTimerStartFromISR |
软件定时器(software timer) | xTimerStop | xTimerStopFromISR |
软件定时器(software timer) | xTimerReset | xTimerResetFromISR |
软件定时器(software timer) | xTimerChangePeriod | xTimerChangePeriodFromISR |
这两套函数参数区别只有,最后以为,在普通任务版本中的,最后一位参数是,如有阻塞愿意等待的时间,中断版本参数是,是否记录有更高优先级的任务发生,并在中断函数结束后是否调用。
BaseType_t xQueueOverwrite(QueueHandle_t xQueue,const void * pvItemToQueue);
BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue,const void * pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);
xHigherPriorityTaskWoken参数
中断函数里面,这个是最后的参数,作用是记录是否在中断的过程,中是否有更高优先级的任务被唤醒了 ,这里需要弄清楚的一点是,在中断函数执行过程中被唤醒的函数的比较对象不是中断函数,而是在中断函数之前被中断函数打断执行的普通任务函数,这两个任务相互比较优先级的大小。
xHigherPriorityTaskWoken这个参数最重要的是,这个参数首先有用户调用时传递给程序,但是它的具体值(pdTRUE或pdFALSE)在函数运行过程中可以由程序去修改。
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(myQueue, &data, &xHigherPriorityTaskWoken);
在上面事例程序里面,FreeRtos会检查在中断运行的过程中,是否有比中断发生前执行函数的优先级更高优先级的任务被唤醒,如有 xHigherPriorityTaskWoken 这个参数将被程序设置改变pdTRUE。
所以当我们在ISR里面调用这些中断函数的时候,只需要将 xHigherPriorityTaskWoken 这个参数设置为 pdFALSE,剩下的FreeRtos在运行的时候会自己设置,如果最后为pdTRUE就代表在中断结束后需要切换任务运行,如有依然是pdFALSE,就继续执行被中断打断的任务。
到这里,我们知道了, xHigherPriorityTaskWoken的值虽然是通过参数手动传递的,但是在FreeRtos运行的过程中,会根据任务唤醒情况去设置 xHigherPriorityTaskWoken的值。当值被设定之后,通过调用 portYIELD_FROM_ISR() 在中断响应函数最后,来完成任务的切换。
中断的延迟处理定义
如果在ISR中,中断函数的响应本身就是耗时的,可以使用 中断的延时处理(Deferring interrupt processing)
·ISR :中清除中断标志位,清理,记录工作。
·任务:将更加复杂的事情放在任务重处理。
欢迎指正,希望对你,有所帮助!!!
[10-1]_事件组的本质_哔哩哔哩_bilibili