典的雙閃燈案例--deepseek)
我想知道如何才是開啟了freertos如何使用freertos您可以使用最簡單最經(jīng)典的一個案例來給小白說明一下嗎可以講細致一點講每一步為啥這么做對應底層是如何運行的謝謝啦老師太棒了這個問題問到點子上了要真正理解 FreeRTOS咱們就拋開那些復雜的網(wǎng)口、DMA用最經(jīng)典的“紅燈停綠燈行”雙閃燈案例來演示。這就好比你要開一家公司運行 FreeRTOS我們一步步來看怎么注冊公司、怎么招人、怎么讓員工干活。第一步怎么才算“開啟了 FreeRTOS”在 Vitis 里開啟 FreeRTOS 不是你在代碼里寫一句#include FreeRTOS.h就行的。它是在底層配置層面完成的也就是你之前看過的 BSP 設置里。操作本質(zhì)底層原理你在 Vitis 里創(chuàng)建了一個 Platform并在 Domain域里選擇了freertos10_xilinx。Vitis 會自動在你的工程里引入 FreeRTOS 的內(nèi)核源碼tasks.c、queue.c等。它會生成一個FreeRTOSConfig.h并在里面配置了心跳時間比如 1000Hz即 1ms 一次。最重要的是它會在底層把 ARM 芯片的硬件定時器比如 Systick和幾個關鍵的異常中斷如 SVC、PendSV綁定到 FreeRTOS 的啟動函數(shù)上。這就是“公司的營業(yè)執(zhí)照”。一旦配置好你的工程在編譯時就會自動把 RTOS 的調(diào)度器代碼幾千行塞進你的可執(zhí)行文件里。第二步最經(jīng)典的雙閃燈案例源碼 拆解你看一下這段極簡的代碼我會在每一行注釋里告訴你“為什么”c#include stdio.h #include xil_printf.h #include FreeRTOS.h #include task.h // 1. 定義 LED 的引腳和寄存器這里是偽代碼代表硬件操作 #define LED_RED 0x01 #define LED_GREEN 0x02 // 2. 紅燈任務員工A void Task_RedLED(void *pvParameters) { while (1) // 為什么要有死循環(huán)因為任務不能退出退出會崩潰 { LED_Write(LED_RED, 1); // 點亮紅燈 vTaskDelay(pdMS_TO_TICKS(500)); // 阻塞 500 毫秒重點見下方解釋 LED_Write(LED_RED, 0); // 熄滅紅燈 vTaskDelay(pdMS_TO_TICKS(500)); // 阻塞 500 毫秒 } } // 3. 綠燈任務員工B void Task_GreenLED(void *pvParameters) { while (1) { LED_Write(LED_GREEN, 1); // 點亮綠燈 vTaskDelay(pdMS_TO_TICKS(1000));// 阻塞 1000 毫秒綠燈亮得更久 LED_Write(LED_GREEN, 0); // 熄滅綠燈 vTaskDelay(pdMS_TO_TICKS(1000)); } } // 4. 主函數(shù)老板 / 包工頭 int main() { // 初始化硬件不需要上系統(tǒng)直接調(diào) LED_Init(); xil_printf(系統(tǒng)啟動開始創(chuàng)建任務...\r\n); // 創(chuàng)建紅燈任務 // 參數(shù)說明任務函數(shù), 任務名字, 棧大小, 參數(shù), 優(yōu)先級, 句柄 xTaskCreate(Task_RedLED, RedLED, 512, NULL, 2, NULL); // 創(chuàng)建綠燈任務 // 注意優(yōu)先級綠燈是 1紅燈是 2。數(shù)字越大優(yōu)先級越高。 xTaskCreate(Task_GreenLED, GreenLED, 512, NULL, 1, NULL); // 開啟調(diào)度器開始干活 // 這一句執(zhí)行后CPU 的控制權完全交給 FreeRTOS vTaskStartScheduler(); // 如果代碼跑到這里說明內(nèi)存不夠了因為沒地方建任務棧了 while (1) { xil_printf(調(diào)度器啟動失敗\r\n); } return 0; }第三步底層到底是怎么運行的微觀視角現(xiàn)在代碼燒進板子Vitis 調(diào)試器按下“運行”。微觀世界里發(fā)生了什么1.main()被執(zhí)行招人階段主程序執(zhí)行到xTaskCreateFreeRTOS 會在內(nèi)存堆區(qū)里給紅燈和綠燈各分配一塊專門的獨立空間棧 Stack。相當于給每個員工發(fā)了個專屬的記事本和辦公桌。此時CPU 只是把這兩個任務登記在“花名冊”就緒列表上但還沒開始執(zhí)行。2.vTaskStartScheduler()被執(zhí)行開工這是極其關鍵的一步。FreeRTOS 啟動第一個硬件定時器Systick。它從“花名冊”里找優(yōu)先級最高的任務紅燈優(yōu)先級2。然后偽造了一個中斷返回的現(xiàn)場直接讓 CPU 跳到Task_RedLED函數(shù)開始執(zhí)行。從此以后main()函數(shù)就“死”了永遠不會再往下執(zhí)行。3. 第一次執(zhí)行紅燈任務CPU 點亮紅燈。遇到vTaskDelay(500)。這是 FreeRTOS 的靈魂底層發(fā)生的事FreeRTOS 把紅燈任務從“花名冊”里劃掉扔進“休息室”阻塞列表并在它的記事本上寫“500 毫秒后叫醒他”。注意此時 CPU 并沒有死等不像裸機的 delay 傻轉(zhuǎn)圈而是立刻去“花名冊”里找下一個能干活的人綠燈任務4. 第一次執(zhí)行綠燈任務綠燈任務被喚醒其實是 CPU 跳過去點亮綠燈。遇到vTaskDelay(1000)。綠燈也被扔進“休息室”。5. 定時器“心跳”上下文切換 / Context Switch重點來了剛才不是啟動了一個定時器嗎假設 1 毫秒跳動一次產(chǎn)生一次中斷。每到 1 毫秒CPU 就被強制打斷一下跳進 FreeRTOS 的中斷服務函數(shù)里。系統(tǒng)一看時間如果紅燈的 500 毫秒到了就把紅燈從“休息室”拽出來放回“花名冊”。此時系統(tǒng)會對比紅燈優(yōu)先級2和正在休息的其他人優(yōu)先級1。發(fā)現(xiàn)紅燈優(yōu)先級高或者大家優(yōu)先級一樣就開始切換現(xiàn)場把當前寄存器里的數(shù)據(jù)保存到綠燈的內(nèi)存Stack里。把紅燈內(nèi)存里的數(shù)據(jù)恢復到寄存器里。讓 CPU 繼續(xù)執(zhí)行紅燈的代碼緊接著上一次延時的地方繼續(xù)跑。第四步為什么必須用vTaskDelay()小白避坑如果你在上面紅燈任務的while(1)里沒寫vTaskDelay()或者寫了delay_ms(500)那種單純死等的裸機延時會發(fā)生什么底層現(xiàn)象紅燈任務一旦開始跑它就在while(1)里瘋狂循環(huán)點亮、死等、熄滅。因為它是最高優(yōu)先級2它絕對不會交出 CPU 的控制權。結果綠燈任務永遠得不到執(zhí)行的機會哪怕它也已經(jīng)被創(chuàng)建了。這就叫“任務餓死”。通俗解釋紅燈員工是個卷王霸占了老板CPU的辦公桌死活不下來。綠燈員工在外面排隊連門都進不去。只要用了vTaskDelay就是在告訴老板“我活干完了我去旁邊喝口水休眠你把桌子讓給別人用吧?!?這樣大家才能和諧共處??偨Y給小白的口訣開 RTOS 在 BSP 里選 FreeRTOS 引入頭文件。建任務xTaskCreate租場地、發(fā)工牌。跑起來vTaskStartScheduler把控制權交出去。防獨裁 任務里必須有vTaskDelay交還 CPU 控制權讓其他任務也能跑。這就是最經(jīng)典的 FreeRTOS 入門。你去 Vitis 里建個空工程把這段代碼換成你板子實際 LED 的引腳敲進去跑一下看看燈是不是交替閃爍體會一下那種“不用寫死循環(huán)延時兩個任務居然能同時跑”的魔法This response is AI-generated, for reference only.