原文地址:http://www.cnblogs.com/god-of-death/p/6886823.html
注意點:
1、首先要將中斷的嵌套全部設置為搶占優先級。
2、將freertos系統內核中斷(configKERNEL_INTERRUPT_PRIORITY)的優先級設置成最低。
3、將freertos的最大系統調用中斷優先級(configMAX_SYSCALL_INTERRUPT_PRIORITY)設置為合適的優先級,比如11。
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、pxHigherPriorityTaskWoken 為了保證總是最高優先級的任務被執行,如果中斷函數使比被中斷打斷的任務的優先級更高的任務退出阻塞,在中斷函數結束之前進行一次上下文切換,退出中斷后執行這個更高優先級的任務,否則這個任務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:
1、中斷函數里面不允許任務切換等待,比如在任務中調用xTimerStart(XXXtimerHandle,pdMS_TO_TICKS( 100 )),可能使任務阻塞100ms,但是中斷中不會阻塞100ms。所以xSemaphoreGiveFromISR()最好不要在中斷函數中調用,因為不會阻塞,直接返回結果。
2、中斷里面不能自動進行上下文切換,所以FromISR函數里面不能自動進行上下文切換(“161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide”文檔186頁有介紹,主要原因是高效、避免不確定性、FreeRTOS移植簡單),而在任務中調用的沒有FromISR的函數是要自動進行上下文切換(保證最高優先級任務被執行)