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