狀態(tài))
FreeRTOS 四種任務(wù)狀態(tài)徹底吃透一、前言初學(xué) FreeRTOS90% 的人都卡在任務(wù)狀態(tài)? 分不清 Blocked阻塞 和 Suspended掛起? 以為延時(shí)就是卡住程序? 不理解為什么按鍵直接 Suspend 任務(wù)肉眼看正常工程卻是錯誤寫法今天結(jié)合 韋東山 任務(wù)狀態(tài)音樂播放控制實(shí)戰(zhàn)用純大白話真實(shí)BUG場景一次性徹底講透四種任務(wù)狀態(tài)、流轉(zhuǎn)邏輯、工程禁忌。二、FreeRTOS 四大任務(wù)狀態(tài)FreeRTOS 任務(wù)永遠(yuǎn)只有 4 種狀態(tài)1. Running運(yùn)行態(tài)CPU 此時(shí)此刻正在執(zhí)行該任務(wù)代碼。單核單片機(jī)同一時(shí)間只有 1 個任務(wù)處于 Running。2. Ready就緒態(tài)代碼已經(jīng)準(zhǔn)備完畢、條件全部滿足。只差 CPU 時(shí)間片隨時(shí)可以運(yùn)行。只是優(yōu)先級不夠暫時(shí)沒輪到。3. Blocked阻塞態(tài) —— 重點(diǎn)任務(wù)主動躺平、主動讓出 CPU。觸發(fā)方式只有兩種? vTaskDelay() 等待時(shí)間? xSemaphoreTake() / 隊(duì)列 / 事件組 等待資源特點(diǎn)? 自己等待自己自動復(fù)活? 等待時(shí)間/條件滿足 → 自動回到就緒態(tài)? 不占用 CPU通俗理解我等一會時(shí)間到我自己繼續(xù)干活。4. Suspended掛起態(tài) —— 大坑被動強(qiáng)制凍結(jié)別人把你暫停。觸發(fā)方式? vTaskSuspend(句柄)恢復(fù)方式? 必須別人調(diào)用 vTaskResume(句柄)特點(diǎn)? 自己永遠(yuǎn)醒不過來? 無論你之前是 Running / Ready / Blocked都能直接被強(qiáng)行掛起? 掛起期間計(jì)時(shí)器暫停、邏輯暫停、一切凍結(jié)三、新手最大誤區(qū)Delay 延時(shí) 音樂正在播放徹底糾正播放do();vTaskDelay(300);播放re();1. 播放do()一瞬間執(zhí)行完畢喇叭響一下就結(jié)束。2. vTaskDelay(300)不是播放音樂是 音符之間的靜音間隔、節(jié)奏留白。 Delay 期間音樂不響、代碼暫停、任務(wù)進(jìn)入 Blocked 阻塞關(guān)鍵結(jié)論Blocked 任務(wù)在等節(jié)奏不是在放音樂這是今天所有看不懂、搞混亂的根源。四、實(shí)戰(zhàn)BUG詳解韋東山課程核心難點(diǎn)1. 錯誤寫法按鍵直接 Suspend 音樂任務(wù)vTaskSuspend(音樂任務(wù)句柄); // 直接凍住任務(wù)PassiveBuzzer_Control(0); // 強(qiáng)行關(guān)喇叭2. 為什么肉眼看沒問題因?yàn)榘聪聲和?立刻硬件關(guān)喇叭耳朵看不到時(shí)序錯誤BUG被掩蓋了不是修復(fù)了3. 真實(shí)隱藏BUG完整危險(xiǎn)流程1. 音樂播放 do 完成2. 進(jìn)入 vTaskDelay(300)任務(wù)進(jìn)入 Blocked 阻塞此時(shí)還剩 200tick 靜音間隔沒跑完3. 你此時(shí)按下按鍵 Suspend4. 剩余 200tick 計(jì)時(shí)直接作廢、清零、凍結(jié)5. 恢復(fù) Resume 后直接跳過剩余間隔立刻播放 re最終現(xiàn)象音符粘連、節(jié)奏錯亂、偶發(fā)無聲、時(shí)序崩壞。重點(diǎn)Suspend 可以強(qiáng)行凍結(jié)正在 Blocked 的任務(wù)阻塞中也能被掛起且剩余時(shí)間全部丟失這是本節(jié)課 最重要的狀態(tài)流轉(zhuǎn)知識點(diǎn)。五、Blocked 和 Suspended 終極區(qū)別面試必考Blocked阻塞? 主動等待? 等待時(shí)間/事件完成 → 自動恢復(fù)就緒? 用于延時(shí)、等待信號量、等待數(shù)據(jù)Suspended掛起? 被動凍結(jié)? 不會自動恢復(fù)必須別人 Resume? 會丟失 Delay 剩余計(jì)時(shí)? 嚴(yán)禁用于業(yè)務(wù)暫停? 阻塞自己休息到點(diǎn)自己上班? 掛起被人鎖小黑屋放出來直接跳過之前休息時(shí)間六、工程正確寫法信號量替代 Suspend課程改進(jìn)方案核心思想永遠(yuǎn)不要外部暴力暫停業(yè)務(wù)任務(wù)讓任務(wù) 自己在安全位置主動阻塞while(1){// 在循環(huán)開頭等待許可xSemaphoreTake(sem, portMAX_DELAY);// 完整跑完一輪音樂節(jié)拍播放do();vTaskDelay(300);播放re();vTaskDelay(300);}按鍵只做兩件事1. 暫停拿走信號量2. 繼續(xù)釋放信號量優(yōu)勢? 只會在一輪節(jié)拍完整結(jié)束后暫停? 不會卡在 Delay 中間? 時(shí)序永遠(yuǎn)不亂、無隱藏BUG? 硬件狀態(tài)完全同步七、四種狀態(tài)完整流轉(zhuǎn)圖必記1. Ready ? Running調(diào)度切換2. Running → BlockedDelay/等待資源3. Blocked → Ready條件滿足自動恢復(fù)4. 任意狀態(tài) → Suspended被 Suspend 強(qiáng)行凍結(jié)5. Suspended → Ready被 Resume 解凍重中之重Blocked 依然可以被 Suspend 掛起八、最終工程結(jié)論1. 業(yè)務(wù)啟停禁止使用 Suspend/Resume有偶現(xiàn)時(shí)序BUG2. Suspend 只適合調(diào)試、凍結(jié)任務(wù)不適合產(chǎn)品功能3. 正常延時(shí)是 Blocked 主動等待不浪費(fèi) CPU4. 音樂/LED/電機(jī)等業(yè)務(wù)暫停必須用信號量/事件標(biāo)志5. 不要從外部操作別人任務(wù)的硬件 凍結(jié)任務(wù)極易狀態(tài)錯位九、總結(jié)? 運(yùn)行正在干活? 就緒等著干活? 阻塞主動休息到點(diǎn)自回? 掛起強(qiáng)行停工時(shí)間清零必須人救結(jié)尾這一節(jié)是 FreeRTOS 從入門到進(jìn)階的分水嶺??炊疇顟B(tài)流轉(zhuǎn)、看懂阻塞掛起區(qū)別才算真正入門實(shí)時(shí)操作系統(tǒng)。后續(xù)我會繼續(xù)更新 FreeRTOS 信號量、隊(duì)列、事件組實(shí)戰(zhàn)避坑文章。