#if ( INCLUDE_vTaskDelay == 1 ) //延時(shí)特定時(shí)間xTicksToDelay,這個(gè)時(shí)間需要轉(zhuǎn)換為喚醒絕對(duì)時(shí)間xTimeToWake, //這樣才能在與vTaskIncrementTick函數(shù)中操作的數(shù)值是一致的xTicksToDelay:延時(shí)的節(jié)拍數(shù) void vTaskDelay( const TickType_t xTicksToDelay ) { TickType_t xTimeToWake; BaseType_t xAlreadyYielded = pdFALSE; if( xTicksToDelay > ( TickType_t ) 0U )//若延遲的時(shí)間是0,就是調(diào)度器的重新啟動(dòng)。若延時(shí)時(shí)間大于0,執(zhí)行延時(shí)操作。 { configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll();//系統(tǒng)維護(hù)一個(gè)uxSchedulerSuspended計(jì)數(shù)值,當(dāng)其大于0時(shí)表示禁止調(diào)度;等于0時(shí)則表示允許調(diào)度。 { traceTASK_DELAY(); //計(jì)算喚醒時(shí)間--這可能會(huì)溢出,但不會(huì)有問(wèn)題 ,大家會(huì)問(wèn)為什么 //大家可以自己做個(gè)試驗(yàn),兩個(gè)uCHAR型數(shù)據(jù)相加,如果超過(guò)255,則等于多少? xTimeToWake = xTickCount + xTicksToDelay;//任務(wù)的喚醒時(shí)間更新。 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )//若刪除完后鏈表中沒(méi)有任務(wù) //把任務(wù)從當(dāng)前運(yùn)行鏈表中移除出去,然后把它添加到阻塞鏈表里面 { //當(dāng)前任務(wù)必須在就緒鏈表中,所以其是不必檢查的,下面的宏定義可以直接調(diào)用 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); } else { mtCOVERAGE_TEST_MARKER(); } prvAddCurrentTaskToDelayedList( xTimeToWake ); //prvAddCurrentTaskToDelayedList是一個(gè)函數(shù),它是把當(dāng)前的任務(wù)控制塊, //放進(jìn)DelayedList鏈表中,而DelayedList有兩個(gè)鏈表,一個(gè)是溢出的,一個(gè)是正在應(yīng)用的, //所以要根據(jù)傳遞進(jìn)的參數(shù)xTimeToWake進(jìn)行分別設(shè)置,如果是在當(dāng)前的延時(shí)鏈表里就添加進(jìn)現(xiàn)在的延時(shí)鏈表, //如果計(jì)算出來(lái)后是溢出鏈表,則添加進(jìn)溢出鏈表里面 } xAlreadyYielded = xTaskResumeAll();//得到任務(wù)切換的具體情況,pdTRUE切換成功否則切換失敗。 } else { mtCOVERAGE_TEST_MARKER(); } if( xAlreadyYielded == pdFALSE )//若上面的切換失敗,或不需要延遲。直接進(jìn)行切換。 { portYIELD_WITHIN_API(); //實(shí)際就是終端控制及狀態(tài)寄存器ICSR,寫位28為1懸起PendSV,進(jìn)入到xPortPendSVHandler。 } else { mtCOVERAGE_TEST_MARKER(); } } #endif #if ( INCLUDE_vTaskDelayUntil == 1 ) void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) //參數(shù):pxPreviousWakeTime---上一次調(diào)用本函數(shù)的時(shí)間 // xTimeIncrement---相對(duì)于pxPreviousWakeTime本次延時(shí)的節(jié)拍數(shù) //由于調(diào)用此函數(shù)的任務(wù)解除阻塞的時(shí)間是絕對(duì)時(shí)刻,比起相對(duì)于調(diào)用時(shí)刻的相對(duì)時(shí)間更精確(即比調(diào)用vTaskDelay()可以實(shí)現(xiàn)更精確的周期性)。 //pxPreviousWakeTime: 此參數(shù)命名時(shí)假定vTaskDelayUntil()用于實(shí)現(xiàn)某個(gè)任務(wù)以固定頻率周期性執(zhí)行。這種情況下pxPreviousWakeTime // 保存了任務(wù)上一次離開(kāi)阻塞態(tài)(被喚醒)的時(shí)刻。這個(gè)時(shí)刻被用作一個(gè)參考點(diǎn)來(lái)計(jì)算該任務(wù)下一次離開(kāi)阻塞態(tài)的時(shí)刻。 //xTimeIncrement: 此參數(shù)命名時(shí)同樣是假定vTaskDelayUntil()用于實(shí)現(xiàn)某個(gè)任務(wù)以固定頻率周期性執(zhí)行 —— 這個(gè)頻率就是由xTimeIncrement 指定的。 // *xTimeIncrement 的單位是心跳周期, 可以使用常量portTICK_RATE_MS 將毫秒轉(zhuǎn)換為心跳周期 { TickType_t xTimeToWake;//和vTaskDelay函數(shù)中一樣定義,最終得到xTimeToWake賦值給xGenericListItem .xItemValue BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll();//調(diào)度器掛起 { const TickType_t xConstTickCount = xTickCount;//xTickCount在這個(gè)函數(shù)里面不能改變,所以采用另外一個(gè)變量做優(yōu)化。 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; //計(jì)算下次喚醒的時(shí)刻. if( xConstTickCount < *pxPreviousWakeTime )//說(shuō)明 xTickCount 溢出了 { //pxPreviousWakeTime指向上一次的喚醒時(shí)間,這個(gè)地方有點(diǎn)難理解,可以這樣說(shuō)明:時(shí)間軸是一個(gè)往前的軸, //是不會(huì)有溢出之說(shuō)法,也就是說(shuō)xTickCount永遠(yuǎn)都是大于喚醒時(shí)間的而不管哪一次的喚醒時(shí)間都是大于, //但由于溢出的存在,所以有時(shí)候xTickCount會(huì)小于喚醒時(shí)間,這里就說(shuō)明是小于上一次設(shè)置的喚醒時(shí)間,如果是就說(shuō)明是溢出了 //::T3::::::T2:::::::::::::::::::::T1:::::::::::::::::::::::::::::::::::::T2:::::::::::::::::T3:::::::::*/ // xTickCount *pxPreviousWakeTime xTickCount xTimeToWake*/ //T1對(duì)應(yīng)*pxPreviousWakeTime ,T2對(duì)應(yīng)xTickCount,T3對(duì)應(yīng)xTimeToWake*/ //因?yàn)樵谶\(yùn)行這個(gè)程序時(shí),任務(wù)因?yàn)檫\(yùn)行了其它程序,造成了xTickCount和喚醒時(shí)間不是在同一個(gè)點(diǎn)上,要么大于*pxPreviousWakeTime, //要么小于*pxPreviousWakeTime,就像T2一樣,如果運(yùn)行到T第一個(gè)T0處,那么,就相當(dāng)于xTickCount已經(jīng)溢出了,那么需要不 //需要延時(shí),就要看xTimeToWake所處的位置了,如果沒(méi)溢出,則說(shuō)明不需要延時(shí)就可以調(diào)度任務(wù) //,如果溢出了,還要看是否大于xTickCount,如果是才能算的上是真正的需要放入延時(shí)鏈表里面 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) //這時(shí)只有 xTimeToWake 也溢出了,并且 xTimeToWake > xConstTickCount 才需要休眠 { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { //下面兩種情況才需要休眠 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } //為下一次 Delay 更新 pxPreviousWakeTime. *pxPreviousWakeTime = xTimeToWake;//把需要喚醒的絕對(duì)時(shí)間保存起來(lái),保存到pxPreviousWakeTime指針變量里面 if( xShouldDelay != pdFALSE )//這時(shí)需要休眠,由上面的判斷任務(wù)是否進(jìn)入延時(shí)鏈表,如果不需要,則仍是當(dāng)前運(yùn)行的任務(wù) { traceTASK_DELAY_UNTIL(); //從 Ready 鏈表中刪除,加入 Blocked List if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) { portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); } else { mtCOVERAGE_TEST_MARKER(); } prvAddCurrentTaskToDelayedList( xTimeToWake ); } else { mtCOVERAGE_TEST_MARKER(); } } xAlreadyYielded = xTaskResumeAll(); //在運(yùn)行上面臨界區(qū)的程序時(shí),可能有任務(wù)需要調(diào)度,但因?yàn)檎{(diào)度器的掛起而沒(méi)有被調(diào)度,只是給出了登記, //而這個(gè)xTaskResumeAll函數(shù)就是要把放進(jìn)xPendingReadyList鏈表中的任務(wù)節(jié)點(diǎn)轉(zhuǎn)移到真正的就緒鏈表pxReadyTasksLists里面, //如果任務(wù)是因?yàn)閠ick缺失或者因?yàn)樵诨謴?fù)實(shí)際走過(guò)的滴答數(shù)時(shí)有任務(wù)需要搶占CPU,則 xAlreadyYielded 都為真, //從而導(dǎo)致下面不會(huì)運(yùn)行,如果沒(méi)有被搶占也就是說(shuō)當(dāng)前還是處于最高級(jí)任務(wù),但是上面的延時(shí)已經(jīng)使其阻塞,從而在下面發(fā)生搶占 if( xAlreadyYielded == pdFALSE ) //強(qiáng)制自己交出CPU,使自身進(jìn)入等待延時(shí)。個(gè)人認(rèn)為:此處并不需要強(qiáng)制交出,如果上面并不需要加入延時(shí)鏈表, //表示還是運(yùn)行的當(dāng)前任務(wù),如果這個(gè)任務(wù)仍然是最高級(jí)的,則并不需要切換 { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif 原文鏈接:
FreeRTOS(V8.0.1)系統(tǒng)之vTaskDelay()和vTaskDelayUntil()
相關(guān)推薦
FreeRTOS嵌入式實(shí)時(shí)操作系統(tǒng)
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file1.elecfans.com//web2/M00/A5/B2/wKgZomUMOaiABurJAAH1RuVQWuQ285.jpg)
FreeRTOS 9.0 vTaskDelayUntil( )函數(shù)源碼問(wèn)題如何解決
FreeRTOS V9.0.0 的相關(guān)資料推薦
FreeRTOS與RISC-V——適用于RISC-V的FreeRTOS概述
FreeRTOS兩種延時(shí)函數(shù)的區(qū)別是什么?
FreeRTOS創(chuàng)建任務(wù)操作Flash運(yùn)行時(shí)系統(tǒng)調(diào)度出現(xiàn)錯(cuò)誤
FreeRTOS學(xué)習(xí)筆記(三)——FreeRTOS內(nèi)核配置說(shuō)明
FreeRTOS操作系統(tǒng)實(shí)用教程分享?
FreeRTOS有何功能
FreeRTOS退出中斷函數(shù)后系統(tǒng)切換到串口通信任務(wù)中
FreeRtos如何進(jìn)行任務(wù)切換
freeRTOS里面vTaskDelay的輸入?yún)?shù)是什么?
freeRtos和裸機(jī) 跑同樣一個(gè)程序,效率不一樣
freertos中的任務(wù)執(zhí)行時(shí)間問(wèn)題求解
freertos多任務(wù)運(yùn)行,為什么只能跑一個(gè)任務(wù)
vTaskDelay系統(tǒng)延時(shí)函數(shù)時(shí)間到后是否為調(diào)用此函數(shù)的任務(wù)重新執(zhí)行?
vTaskDelay延時(shí)不準(zhǔn)怎么解決?
vTaskDelayUntil絕對(duì)延時(shí),vTaskDelay相對(duì)延時(shí)有什么區(qū)別呢?
CH32V307VCT6用FreeRTOS例程增加一段代碼后系統(tǒng)無(wú)法運(yùn)行了
ESP8266報(bào)錯(cuò)CONFIG_FREERTOS_HZ未定義的原因?如何解決?
ETH-CH32v20x_v307在Freertos中添加以太網(wǎng)
STM32 FreeRTOS 外部中斷服務(wù)函數(shù)注意事項(xiàng) 精選資料推薦
STM32之FreeRTOS學(xué)習(xí)筆記 精選資料推薦
delay_xms()和vTaskDelay()函數(shù)區(qū)別問(wèn)題如何解決
stm32f103的FreeRTOS工程文件源碼分享
【Atmel WINC1500-XSTK試用體驗(yàn)】+移植freertos
【HAL庫(kù)每天一例】第118例:FreeRTOS移植
【MAX32660試用體驗(yàn)】freertos+dht11+rgy燈
【設(shè)計(jì)技巧】從單片機(jī)到操作系統(tǒng)(7)-FreeRTOS延時(shí)介紹
什么是多任務(wù)系統(tǒng)?FreeRTOS任務(wù)與協(xié)程簡(jiǎn)析
使用FreeRTOS操作系統(tǒng),創(chuàng)建幾個(gè)任務(wù)后進(jìn)入prvTaskExitError第四個(gè)任務(wù)不正常的原因?
關(guān)于FreeRTOS 任務(wù)狀態(tài)機(jī)之阻塞的筆記,給大家分享下
關(guān)于freertos任務(wù)切換問(wèn)題誰(shuí)來(lái)解答一下
函數(shù)vTaskDelay能引發(fā)任務(wù)切換嗎?
在freertos的幾個(gè)任務(wù)中,能不能既有任務(wù)使用vTaskDelay也有任務(wù)使用vtaskdelayuntil?
在GD32F310開(kāi)發(fā)板移植FreeRTOS系統(tǒng)
如何在RISC-V處理器上使用FreeRTOS?
開(kāi)發(fā)實(shí)戰(zhàn)+編程指南,教你快速學(xué)習(xí)FreeRTOS系統(tǒng)
怎樣去設(shè)計(jì)FreeRTOS操作系統(tǒng)?
操作系統(tǒng)FreeRTOS
淺析FreeRTOS任務(wù)系統(tǒng)
添加第二個(gè)USART和第五個(gè)任務(wù)會(huì)殺死vTaskDelay
第30章 FreeRTOS低功耗之睡眠模式
第31章 FreeRTOS低功耗之停機(jī)模式
第32章 FreeRTOS低功耗之待機(jī)模式
請(qǐng)問(wèn)FreeRTOS v8.23系統(tǒng)支持FPU, lwip功能嗎?
請(qǐng)問(wèn)FreeRTOS中vTaskDelay延時(shí)不正確的原因是什么?
轉(zhuǎn):移植FreeRTOS到KEA128
轉(zhuǎn):第5章 FreeRTOS操作系統(tǒng)移植(MDK版)
闡述FreeRTOS系統(tǒng)中機(jī)制的實(shí)現(xiàn)原理
FreeRTOS(V8.0.1)系統(tǒng)之vTaskDelete()
![](https://skin.elecfans.com/images/2021-soft/eye.png)
FreeRTOS(V8.0.1)系統(tǒng)之vTaskSuspendAll()和xTaskResumeAll()
![](https://skin.elecfans.com/images/2021-soft/eye.png)
FreeRTOS(V8.0.1)系統(tǒng)之xTaskGenericCreate()
![](https://skin.elecfans.com/images/2021-soft/eye.png)
FreeRTOS代碼剖析之1:內(nèi)存管理Heap
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file1.elecfans.com//web2/M00/A6/A8/wKgZomUMP2-AXEPPAAAcXbfhrWQ977.png)
FreeRTOS代碼剖析之2:內(nèi)存管理Heap
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file1.elecfans.com//web2/M00/A6/A8/wKgZomUMP2-Af1DuAAAM-f5jrT8382.png)
FreeRTOS代碼剖析之3:內(nèi)存管理Heap
![](https://skin.elecfans.com/images/2021-soft/eye.png)
FreeRTOS嵌入式開(kāi)源實(shí)時(shí)操作系統(tǒng)介紹
![](https://skin.elecfans.com/images/2021-soft/eye.png)
基于FreeRTOS的嵌入式實(shí)時(shí)操作系統(tǒng)的原理和實(shí)現(xiàn)
![](https://skin.elecfans.com/images/2021-soft/eye.png)
什么是操作系統(tǒng)?FreeRTOS中文實(shí)用教程讓你快速入門FreeRTOS
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS任務(wù)控制API函數(shù)介紹
![](https://skin.elecfans.com/images/2021-soft/eye.png)
基于FreeRTOS的嵌入式云臺(tái)控制系統(tǒng)設(shè)計(jì)
![](https://skin.elecfans.com/images/2021-soft/load.png)
嵌入式操作系統(tǒng)FREERTOS的移植.
![](https://skin.elecfans.com/images/2021-soft/load.png)
嵌入式操作系統(tǒng)FreeRTOS的原理實(shí)現(xiàn)
![](https://skin.elecfans.com/images/2021-soft/load.png)
嵌入式操作系統(tǒng)FREERTOS移植
![](https://skin.elecfans.com/images/2021-soft/load.png)
基于FreeRTOS的直流系統(tǒng)主監(jiān)控的設(shè)計(jì)
![](https://skin.elecfans.com/images/2021-soft/load.png)
STM32移植FreeRTOS(圖文實(shí)操)
![](https://skin.elecfans.com/images/2021-soft/load.png)
從0到1學(xué)習(xí)FreeRTOS:FreeRTOS 內(nèi)核應(yīng)用開(kāi)發(fā):(一)移植FreeRTOS到STM32第一部分
![](https://skin.elecfans.com/images/2021-soft/load.png)
初入FreeRTOS
![](https://skin.elecfans.com/images/2021-soft/load.png)
菜鳥(niǎo)入門7,what is FreeRTOS?
![](https://skin.elecfans.com/images/2021-soft/load.png)
【轉(zhuǎn)載】AT32 FreeRTOS應(yīng)用筆記
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS —— 0.前言
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS學(xué)習(xí)(1)——FreeRTOS移植
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS入門學(xué)
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS高級(jí)篇9---FreeRTOS系統(tǒng)延時(shí)分析
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS高級(jí)篇2---FreeRTOS任務(wù)創(chuàng)建分析
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS系列第8篇---FreeRTOS內(nèi)存管理
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS給任務(wù)傳遞兩個(gè)參數(shù)LEDpin和vTaskDelay
![](https://skin.elecfans.com/images/2021-soft/eye.png)
STM32G0開(kāi)發(fā)筆記:使用FreeRTOS系統(tǒng)
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file.elecfans.com/web2/M00/8A/DF/poYBAGPE90WAWzvUAAJdbkXfW9k951.png)
freeRTOS的任務(wù)
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file.elecfans.com/web2/M00/8F/BA/poYBAGPls6KAIydMAAQsn1y3Z9c801.jpg)
FreeRTOS:一個(gè)迷你的實(shí)時(shí)操作系統(tǒng)內(nèi)核
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file1.elecfans.com/web2/M00/8B/B5/wKgZomSdSn6AfapKAAC9H46ZAvo324.jpg)
基于STM32的FreeRTOS開(kāi)發(fā)(1)----FreeRTOS簡(jiǎn)介
![](https://skin.elecfans.com/images/2021-soft/eye.png)
![](https://file1.elecfans.com/web2/M00/8D/EB/wKgaomTBzP-Abdm8AADYzLBC-Bw325.png)
Brocade Fabric操作系統(tǒng)訪問(wèn)網(wǎng)關(guān)管理指南8.0.1
![](https://skin.elecfans.com/images/2021-soft/load.png)
FreeRTOS任務(wù)實(shí)現(xiàn)和控制塊
![](https://skin.elecfans.com/images/2021-soft/eye.png)
評(píng)論