在RTOS
中,需要应对各类事件。这些事件很多时候是通过硬件中断产生。
假设当前系统正在运行Task1
任务,用户按下了按键,触发了按键中断。触发中断后:
硬件负责:
CPU跳到固定地址去执行代码,这个固定地址通常被称为中断向量。
软件负责:
Task1
被打断,需要先保存Task1
的运行环境,比如各类寄存器的值;Task1
,或者运行其他优先级更高的任务。本章主要涉及
提示:以下是本篇文章正文内容,下面案例可供参考
FreeRTOS中很多API函数都有两套:一套在任务中使用,另一套在ISR中使用。因为很多API函数会导致任务计入阻塞状态,但是ISR不能进入阻塞状态,所以需要另一套函数。
类型 | 在任务中 | 在ISR中 |
---|---|---|
队列(queue) | xQueueSendToBack | xQueueSendToBackFromISR |
xQueueSendToFront | xQueueSendToFrontFromISR | |
xQueueReceive | xQueueReceiveFromISR | |
xQueueOverwrite | xQueueOverwriteFromISR | |
xQueuePeek | xQueuePeekFromISR | |
信号量(semaphore) | xSemaphoreGive | xSemaphoreGiveFromISR |
xSemaphoreTake | xSemaphoreTakeFromISR | |
事件组(event group) | xEventGroupSetBits | xEventGroupSetBitsFromISR |
xQueueSendToBack | xQueueSendToBackFromISR | |
---|---|---|
参数不同 | xTicksToWait: 队列满阻塞时间 | 没有xTicksToWait |
唤醒等待的任务 | 写队列后,会唤醒等待数据的任务,如果唤醒任务优先级高会发起调度 | 写队列后,会唤醒等待数据的任务但不调度,只会记录是否需要发起调度 |
阻塞 | 如果队列满,可以阻塞 也可以即刻返回 | 如果队列满,即刻返回 |
我们希望中断处理要快,那当我们处理比较耗时的中断就需要中断的延迟处理:
void XXX_ISR()
{
int i;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
for (i = 0; i < N; i++)
{
xQueueSendToBackFromISR(..., &xHigherPriorityTaskWoken); /* 被多次调用 */
}
/* 最后再决定是否进行任务切换
* xHigherPriorityTaskWoken为pdTRUE时才切换
*/
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}