FreeRTOS --- 中断使用注意

注意点:

1、首先要将中断的嵌套全部设置为抢占优先级。


2、将freertos系统内核中断(configKERNEL_INTERRUPT_PRIORITY)的优先级设置成最低,用来设置tick中断和PendSV中断的优先级


3、将freertos的最大系统调用中断优先级(configMAX_SYSCALL_INTERRUPT_PRIORITY)设置为合适的优先级,比如11。

根据这个值,中断被分为FreeRTOS可屏蔽中断和FreeRTOS不可屏蔽中断,因为在调用FreeRTOS API时,为了原子操作,需要关中断,为了让特别紧急的中断不被FreeRTOS API关闭,设计了这两种中断。


4、如果有用户中断函数调用到FreeRTOS提供的系统函数,一定要使用带FromISR的FreeRTOS提供的系统函数,并且这个用户中断的优先级一定要在configKERNEL_INTERRUPT_PRIORITY和configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级之间,一般configKERNEL_INTERRUPT_PRIORITY设置为单片机最低优先级,configMAX_SYSCALL_INTERRUPT_PRIORITY是FreeRTOS系统能够屏蔽的最高优先级,规定中断优先级比configMAX_SYSCALL_INTERRUPT_PRIORITY高不能调用FreeRTOS API(如此高中断优先级的中断,已经不在FreeRTOS能屏蔽的范围内)。

 

5、最低优先级的中断可以中断最高优先级的任务,所有任务不能抢占任何中断函数

 

6、tick中断和pendSV中断分开的原因,pendSV的功能是做任务切换,中断优先级需要设置为最低。否则pendSV打断其他中断,而pendSV中断返回其他中断时部分寄存器被改为任务的值,上下文环境被修改,出现预想不到的问题。tick中断的优先级可以设置的高一点。

 

7、pxHigherPriorityTaskWoken 为了保证总是最高优先级的任务被执行,如果中断函数使比被中断打断的任务的优先级更高任务退出阻塞,在portYIELD_FROM_ISR()函数内触发PendSV中断进行任务切换,由于PendSV中断的优先级最低,所以等当前中断执行完后执行PendSV中断。否则这个高优先级任务在CPU回到被打断任务后的下一个tick执行(某些情况可以感到明显的延时,不一定是一个tick)。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if(GPIO_Pin == GPIO_PIN_1)
    {
        debug("2W5500 interup.................");
        xTaskNotifyFromISR( xTaskhandle2W5500, 0x01, eSetBits, &xHigherPriorityTaskWoken );
    }
    if(GPIO_Pin == GPIO_PIN_2)
    {
        debug("1W5500 interup.................");
        xTaskNotifyFromISR( xTaskhandle1W5500, 0x01, eSetBits, &xHigherPriorityTaskWoken );
    }
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );  //没有这句,上面两句的事件响应速度慢
}

 

 

为什么要有 FromISR 后缀的 API:

一般中断函数内无法进行任务切换,因为执行任务切换的PendSV的中断优先级最低。带 FromISR 后缀的 API 是专门给中断函数调用,不会试图进行任务切换;获取信号量等API也不会有和给任务用的API有for(;;)之类的语句,获取不到会立刻返回,即不会有导致阻塞的语句,因为阻塞是居于任务切换。

 

posted @ 2017-05-22 00:06  流水灯  阅读(15770)  评论(0编辑  收藏  举报