
static void NHS2x34_InterruptHandler(void){BaseType_t xHigherPriorityTaskWoken pdFALSE;xSemaphoreGiveFromISR(s_intSem, xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);NHS2x34_PAL_DisableInterrupts();}第 1 步:初值pdFALSE表示目前還沒(méi)發(fā)現(xiàn)需要切換的任務(wù)。第 2 步:xSemaphoreGiveFromISR會(huì)修改它內(nèi)核在 give 信號(hào)量時(shí)會(huì)檢查:被喚醒的IrqTask(阻塞在這個(gè)信號(hào)量上)的優(yōu)先級(jí),是否嚴(yán)格高于中斷打斷的那個(gè)任務(wù)?是→ 內(nèi)核把這個(gè)變量置為pdTRUE,表示中斷返回后應(yīng)該立刻切到IrqTask。否→ 保持pdFALSE,中斷返回原任務(wù)。為什么要傳入指針?因?yàn)?give 信號(hào)量的 API 不能有返回值(ISR 版本不能返回pdPASS/pdFAIL那套),所以用out 參數(shù)把是否需要切換這個(gè)結(jié)果帶出來(lái)。第 3 步:portYIELD_FROM_ISR(xHigherPriorityTaskWoken)參數(shù)為pdTRUE→ 中斷退出時(shí)強(qiáng)制觸發(fā)一次 PendSV,立刻切到IrqTask。參數(shù)為pdFALSE→ 什么都不做,正常返回被中斷的任務(wù)。為什么需要它考慮一個(gè)場(chǎng)景:中斷發(fā)生時(shí),CPU 正在跑一個(gè)低優(yōu)先級(jí)任務(wù)(比如 Idle 或某個(gè)后臺(tái)任務(wù))。IrqTask的優(yōu)先級(jí)是configMAX_PRIORITIES - 1(最高,見 第23行)。如果不 yield:中斷返回后還會(huì)繼續(xù)跑那個(gè)低優(yōu)先級(jí)任務(wù),直到下一次 tick 才可能切換 →增加延遲。如果 yield:中斷一退出立刻切到IrqTask去處理中斷 →低延遲。反過(guò)來(lái),如果中斷發(fā)生時(shí) CPU 正在跑一個(gè)比IrqTask還高優(yōu)先級(jí)的任務(wù),那xHigherPriorityTaskWoken會(huì)是pdFALSE,不會(huì)打斷那個(gè)高優(yōu)先級(jí)任務(wù)——這正是我們想要的語(yǔ)義。多個(gè)...FromISR的累積如果在同一個(gè) ISR 里調(diào)用了多次...FromISR(比如 give 了多個(gè)信號(hào)量/隊(duì)列),要復(fù)用同一個(gè)xHigherPriorityTaskWoken變量,每次都傳它的地址。任何一次 give 觸發(fā)了更高優(yōu)先級(jí)任務(wù)喚醒,都會(huì)把它置pdTRUE,最后只調(diào)用一次portYIELD_FROM_ISR即可。這是 FreeRTOS 推薦的寫法。簡(jiǎn)單說(shuō):它是 ISR 里是否需要在中斷退出時(shí)立刻切換上下文的開關(guān),由內(nèi)核填寫,由你在最后用portYIELD_FROM_ISR消費(fèi)。