<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>源码 on Zesean 的博客</title><link>https://zeseanblog.top/tags/%E6%BA%90%E7%A0%81/</link><description>Recent content in 源码 on Zesean 的博客</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Tue, 01 Sep 2026 22:58:08 +0800</lastBuildDate><atom:link href="https://zeseanblog.top/tags/%E6%BA%90%E7%A0%81/index.xml" rel="self" type="application/rss+xml"/><item><title>FreeRTOS 源码解析笔记</title><link>https://zeseanblog.top/p/freertos-source/</link><pubDate>Sat, 09 Aug 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/freertos-source/</guid><description>&lt;h1 id="1动态创建详细过程"&gt;&lt;a href="#1%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e8%af%a6%e7%bb%86%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;1.动态创建详细过程&#13;&#10;&lt;/h1&gt;&lt;h2 id="动态创建"&gt;&lt;a href="#%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;动态创建&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;1.首先tasks.c中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;结构体并给别名，所以初始化可以用TCB_t&lt;/p&gt;&#10;&lt;p&gt;typedef struct tskTaskControlBlock&lt;/p&gt;&#10;&lt;p&gt;{&lt;/p&gt;&#10;&lt;p&gt;&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;}tskTCB;&#10;typedef tskTCB TCB_t;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;2.因此在xTaskCreate()实现中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;TCB_t * pxNewTCB;创建了任务控制块&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3.任务控制块的结构体中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;状态列表 事件列表 优先级 栈指针 任务名&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802183613953" class="gallery-image" data-flex-basis="1029px" data-flex-grow="428" height="90" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802183613953.png" width="386"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;4.回到xTaskCreate&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;判断生长方向，STM32栈区向下生长&lt;/p&gt;&#10;&lt;p&gt;#if ( portSTACK_GROWTH &amp;gt; 0 )&lt;/p&gt;&#10;&lt;p&gt;进入的&lt;/p&gt;&#10;&lt;p&gt;#else中&lt;/p&gt;&#10;&lt;p&gt;其中先定义任务堆栈大小：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;StackType_t * pxStack;//这个申请的代表首地址&#10;&#10;pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );//如128*4字节，128字×每字字节数=字节数&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断是否申请成功任务堆栈，成功则进入&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( pxStack != NULL )&#10; {&#10; pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); //任务控制块信息也需要空间，因此申请&#10; if( pxNewTCB != NULL ) //如果申请了一块&#10; {&#10; memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );&#10; pxNewTCB-&amp;gt;pxStack = pxStack;//然后将首地址给到任务控制块的这个成员变量&#10; }&#10; else&#10; {&#10; vPortFreeStack( pxStack );//否则就释放掉任务堆栈&#10; }&#10; }&#10; else&#10; {&#10; pxNewTCB = NULL;&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;再下面判断是否申请成功任务控制块&lt;/p&gt;&#10;&lt;p&gt;prvInitialiseNewTask：这个用来初始化任务控制块中的成员&lt;/p&gt;&#10;&lt;p&gt;prvAddNewTaskToReadyList：将任务添加到就绪列表&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( pxNewTCB != NULL )&#10; {&#10; prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );&#10; prvAddNewTaskToReadyList( pxNewTCB );&#10; xReturn = pdPASS;//就是成功的返回值&#10; }&#10; else&#10; {&#10; xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;5.到prvInitialiseNewTask&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;( void ) memset( pxNewTCB-&amp;gt;pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );&lt;/p&gt;&#10;&lt;p&gt;这句pxStack是任务堆栈的首地址，将( size_t ) ulStackDepth * sizeof( StackType_t )大小的地址赋值为( int ) tskSTACK_FILL_BYTE&lt;/p&gt;&#10;&lt;p&gt;而这个值是&lt;/p&gt;&#10;&lt;p&gt;#define tskSTACK_FILL_BYTE ( 0xa5U )&lt;/p&gt;&#10;&lt;p&gt;意思就是整个任务堆栈赋值成a5，那就可以通过判断多少a5被改变，得到剩下的空间&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;6.判断 #if ( portSTACK_GROWTH &amp;lt; 0 )&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;是否向下生长？&lt;/p&gt;&#10;&lt;p&gt;STM32:是的&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//首地址的最低位，取得栈顶&#10;pxTopOfStack = &amp;amp;( pxNewTCB-&amp;gt;pxStack[ ulStackDepth - ( uint32_t ) 1 ] );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断名字是否为空&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//pcName是一个入口参数&#10;if( pcName != NULL )&#10; {&#10; for( x = ( UBaseType_t ) 0; x &amp;lt; ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )&#10; {&#10; pxNewTCB-&amp;gt;pcTaskName[ x ] = pcName[ x ]; //给到任务控制块的这个成员里&#10; if( pcName[ x ] == ( char ) 0x00 )&#10; {&#10; break;&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10; pxNewTCB-&amp;gt;pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = &amp;#39;\0&amp;#39;;&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断优先级&lt;/p&gt;&#10;&lt;p&gt;优先级大于最大优先级，就改为最大优先级&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( uxPriority &amp;gt;= ( UBaseType_t ) configMAX_PRIORITIES )&#10; {&#10; uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;&#10; }&#10;&#10;pxNewTCB-&amp;gt;uxPriority = uxPriority;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后初始化状态列表项和事件列表项&lt;/p&gt;&#10;&lt;p&gt;vListInitialiseItem( &amp;amp;( pxNewTCB-&amp;gt;xStateListItem ) );&#10;vListInitialiseItem( &amp;amp;( pxNewTCB-&amp;gt;xEventListItem ) );&lt;/p&gt;&#10;&lt;p&gt;将状态列表项所有权给到任务控制块，就可以得到任务当前状态&lt;/p&gt;&#10;&lt;p&gt;listSET_LIST_ITEM_OWNER( &amp;amp;( pxNewTCB-&amp;gt;xStateListItem ), pxNewTCB );&lt;/p&gt;&#10;&lt;p&gt;下面是事件列表项&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;listSET_LIST_ITEM_VALUE( &amp;amp;( pxNewTCB-&amp;gt;xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); &#10; listSET_LIST_ITEM_OWNER( &amp;amp;( pxNewTCB-&amp;gt;xEventListItem ), pxNewTCB );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面来到&lt;/p&gt;&#10;&lt;p&gt;pxNewTCB-&amp;gt;pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;7.进入pxPortInitialiseStack&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;里面栈顶陆续减，就可以往下陆续给赋值。&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,&#10; TaskFunction_t pxCode,&#10; void * pvParameters )&#10;{&#10; &#10; pxTopOfStack--; &#10; *pxTopOfStack = portINITIAL_XPSR; /* xPSR */&#10; pxTopOfStack--;&#10; *pxTopOfStack = ( ( StackType_t ) pxCode ) &amp;amp; portSTART_ADDRESS_MASK; /* PC */&#10; pxTopOfStack--;&#10; *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */&#10;&#10; pxTopOfStack -= 5; /* R12, R3, R2 and R1. */&#10; *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */&#10; pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */&#10;&#10; return pxTopOfStack;&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;PC是任务函数指针&lt;/strong&gt;，切换到A任务时，就通过这个指针切换到任务函数A&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802194920338" class="gallery-image" data-flex-basis="545px" data-flex-grow="227" height="708" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802194920338.png" srcset="https://zeseanblog.top/p/freertos-source/images/image-20250802194920338_hu_381901ee71d0b455.png 800w, https://zeseanblog.top/p/freertos-source/images/image-20250802194920338_hu_50975814e2aa1c3e.png 1600w, https://zeseanblog.top/p/freertos-source/images/image-20250802194920338.png 1610w" width="1610"&gt;&lt;/p&gt;&#10;&lt;p&gt;这个实际就是最初传入的函数指针&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802195354593" class="gallery-image" data-flex-basis="1260px" data-flex-grow="525" height="119" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802195354593.png" width="625"&gt;&lt;/p&gt;&#10;&lt;p&gt;而R0传入的是任务函数参数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802195543474" class="gallery-image" data-flex-basis="1208px" data-flex-grow="503" height="118" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802195543474.png" width="594"&gt;&lt;/p&gt;&#10;&lt;p&gt;程序结束后返回更新后的pxTopOfStack&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;8.回到prvInitialiseNewTask&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;将任务句柄给到任务控制块&lt;/p&gt;&#10;&lt;p&gt;if( pxCreatedTask != NULL )&#10;{&#10;*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;&#10;}&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;9.再到prvAddNewTaskToReadyList()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;这是将任务添加到就绪列表&lt;/p&gt;&#10;&lt;p&gt;先进入临界区 taskENTER_CRITICAL();&lt;/p&gt;&#10;&lt;p&gt;增加任务数量uxCurrentNumberOfTasks++;&lt;/p&gt;&#10;&lt;p&gt;如果当前没有任务，这是第一个任务pxCurrentTCB = pxNewTCB;&lt;/p&gt;&#10;&lt;p&gt;如果这确实是第一个if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )&lt;/p&gt;&#10;&lt;p&gt;就初始化任务列表prvInitialiseTaskLists()&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802201105871" class="gallery-image" data-flex-basis="491px" data-flex-grow="204" height="303" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802201105871.png" width="620"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;10.进入prvInitialiseTaskLists()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;初始化32个就绪列表0~31&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;for( uxPriority = ( UBaseType_t ) 0U; uxPriority &amp;lt; ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )&#10; {&#10; vListInitialise( &amp;amp;( pxReadyTasksLists[ uxPriority ] ) );&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果使能删除列表，就初始化一个等待删除列表&lt;/p&gt;&#10;&lt;p&gt;如果使能挂起列表，就初始化一个挂起列表&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#if ( INCLUDE_vTaskDelete == 1 )&#10; {&#10; vListInitialise( &amp;amp;xTasksWaitingTermination );&#10; }&#10; #endif /* INCLUDE_vTaskDelete */&#10;&#10; #if ( INCLUDE_vTaskSuspend == 1 )&#10; {&#10; vListInitialise( &amp;amp;xSuspendedTaskList );&#10; }&#10; #endif /* INCLUDE_vTaskSuspend */&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;11.继续prvAddNewTaskToReadyList()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;否则的话，如果当前任务控制块优先级小于新创建的任务控制块&lt;/p&gt;&#10;&lt;p&gt;那新创建的就赋给当前&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( xSchedulerRunning == pdFALSE )&#10; {&#10; if( pxCurrentTCB-&amp;gt;uxPriority &amp;lt;= pxNewTCB-&amp;gt;uxPriority )&#10; {&#10; pxCurrentTCB = pxNewTCB;&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面是任务标号，就可以通过这个查询这是第几个创建的任务&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802201852893" class="gallery-image" data-flex-basis="967px" data-flex-grow="403" height="121" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802201852893.png" width="488"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;12.进入prvAddTaskToReadyList( pxNewTCB );&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;进入 taskRECORD_READY_PRIORITY( ( pxTCB )-&amp;gt;uxPriority );&lt;/p&gt;&#10;&lt;p&gt;进如portRECORD_READY_PRIORITY&lt;/p&gt;&#10;&lt;p&gt;得到&lt;/p&gt;&#10;&lt;p&gt;#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL &amp;laquo; ( uxPriority ) )&lt;/p&gt;&#10;&lt;p&gt;表示就绪列表，哪个位置一，哪个位就有任务，从上往下读就知道哪个任务优先级最高&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802202706272" class="gallery-image" data-flex-basis="382px" data-flex-grow="159" height="301" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802202706272.png" width="480"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;13.继续prvAddNewTaskToReadyList()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;退出临界区taskEXIT_CRITICAL();&lt;/p&gt;&#10;&lt;p&gt;如果任务调度器开启，当前任务优先级，小于新的优先级，执行任务切换，到优先级最高的&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802202950218" class="gallery-image" data-flex-basis="750px" data-flex-grow="312" height="210" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802202950218.png" width="657"&gt;&lt;/p&gt;&#10;&lt;h1 id="2任务挂起与恢复详细过程"&gt;&lt;a href="#2%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7%e4%b8%8e%e6%81%a2%e5%a4%8d%e8%af%a6%e7%bb%86%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;2.任务挂起与恢复详细过程&#13;&#10;&lt;/h1&gt;&lt;h2 id="任务挂起"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7" class="header-anchor"&gt;&lt;/a&gt;任务挂起&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;1.进入prvGetTCBFromHandle&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;如果句柄为NULL，返回当前任务控制块句柄，否则返回传入任务控制块句柄&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;2.回到vTaskSuspend&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;if内是不管当前状态是什么，并移除列表项，移除成功则进入&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( uxListRemove( &amp;amp;( pxTCB-&amp;gt;xStateListItem ) ) == ( UBaseType_t ) 0 )&#10; {&#10; taskRESET_READY_PRIORITY( pxTCB-&amp;gt;uxPriority );&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;3.进入taskRESET_READY_PRIORITY&lt;/strong&gt;&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if(listCURRENT_LIST_LENGTH(&amp;amp;(pxReadyTasksLists[( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) &#10; { &#10; portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); &#10; } &#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;4.回到vTaskSuspend&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;移除事件列表项&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( listLIST_ITEM_CONTAINER( &amp;amp;( pxTCB-&amp;gt;xEventListItem ) ) != NULL )&#10; {&#10; ( void ) uxListRemove( &amp;amp;( pxTCB-&amp;gt;xEventListItem ) );&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;插入挂起列表项末尾&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;vListInsertEnd( &amp;amp;xSuspendedTaskList, &amp;amp;( pxTCB-&amp;gt;xStateListItem ) );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果带挂起的任务控制块在等待消息通知，清除消息通知&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;for( x = 0; x &amp;lt; configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )&#10; {&#10; if( pxTCB-&amp;gt;ucNotifyState[ x ] == taskWAITING_NOTIFICATION )&#10; {&#10; pxTCB-&amp;gt;ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;&#10; }&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断调度器是否正在运行&lt;/p&gt;&#10;&lt;p&gt;如果正在运行，更新下一个阻塞超时时间&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( xSchedulerRunning != pdFALSE )&#10; {&#10; taskENTER_CRITICAL();&#10; {&#10; prvResetNextTaskUnblockTime();&#10; }&#10; taskEXIT_CRITICAL();&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断挂起是否为任务自己，如果挂起的是自己，强制进行任务切换。&lt;/p&gt;&#10;&lt;p&gt;如果不是，判断当前挂起的任务总数等于创建的任务总数，表明全部在挂起，则将任务控制块赋值为NULL，&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( pxTCB == pxCurrentTCB )&#10; {&#10; if( xSchedulerRunning != pdFALSE )&#10; {&#10; configASSERT( uxSchedulerSuspended == 0 );&#10; portYIELD_WITHIN_API();&#10; }&#10; else&#10; {&#10; if( listCURRENT_LIST_LENGTH( &amp;amp;xSuspendedTaskList ) == uxCurrentNumberOfTasks ) &#10; {&#10; pxCurrentTCB = NULL;&#10; }&#10; else&#10; {&#10; vTaskSwitchContext();&#9;&#9;//查找下一个最高优先级任务&#10; }&#10; }&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="任务恢复"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;任务恢复&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务句柄赋值给任务控制块&lt;/p&gt;&#10;&lt;p&gt;TCB_t * const pxTCB = xTaskToResume;&lt;/p&gt;&#10;&lt;p&gt;恢复的任务控制块不能等于当前任务和NULL&lt;/p&gt;&#10;&lt;p&gt;if( ( pxTCB != pxCurrentTCB ) &amp;amp;&amp;amp; ( pxTCB != NULL ) )&lt;/p&gt;&#10;&lt;p&gt;如果成立进入，判断任务控制块是否在挂起列表中&lt;/p&gt;&#10;&lt;p&gt;if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )&lt;/p&gt;&#10;&lt;p&gt;如果成立进入，在挂起列表中移除&lt;/p&gt;&#10;&lt;p&gt;( void ) uxListRemove( &amp;amp;( pxTCB-&amp;gt;xStateListItem ) );&lt;/p&gt;&#10;&lt;p&gt;并添加到就绪列表&lt;/p&gt;&#10;&lt;p&gt;prvAddTaskToReadyList( pxTCB );&lt;/p&gt;&#10;&lt;p&gt;在判断优先级是否大于当前优先级，如果是，则任务切换&lt;/p&gt;&#10;&lt;p&gt;taskYIELD_IF_USING_PREEMPTION();&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( ( pxTCB != pxCurrentTCB ) &amp;amp;&amp;amp; ( pxTCB != NULL ) )&#10; {&#10; taskENTER_CRITICAL();&#10; {&#10; if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )&#10; {&#10; traceTASK_RESUME( pxTCB );&#10; ( void ) uxListRemove( &amp;amp;( pxTCB-&amp;gt;xStateListItem ) );&#10; prvAddTaskToReadyList( pxTCB );&#10; if( pxTCB-&amp;gt;uxPriority &amp;gt;= pxCurrentTCB-&amp;gt;uxPriority )&#10; {&#10; taskYIELD_IF_USING_PREEMPTION();&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10; taskEXIT_CRITICAL();&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="3临界段代码保护"&gt;&lt;a href="#3%e4%b8%b4%e7%95%8c%e6%ae%b5%e4%bb%a3%e7%a0%81%e4%bf%9d%e6%8a%a4" class="header-anchor"&gt;&lt;/a&gt;3.临界段代码保护&#13;&#10;&lt;/h1&gt;&lt;p&gt;通过++，&amp;ndash;实现了嵌套，本质还是基于portDISABLE_INTERRUPTS();和portENABLE_INTERRUPTS();&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;/*进入临界段*/&#10;#define taskENTER_CRITICAL() portENTER_CRITICAL()&#10;#define portENTER_CRITICAL() vPortEnterCritical()&#10;&#10;void vPortEnterCritical( void )&#10;{&#10; portDISABLE_INTERRUPTS();&#10; uxCriticalNesting++;&#10; if( uxCriticalNesting == 1 )&#10; {&#10; configASSERT( ( portNVIC_INT_CTRL_REG &amp;amp; portVECTACTIVE_MASK ) == 0 );&#10; }&#10;}&#10;&#10;/*退出临界段*/&#10;void vPortExitCritical( void )&#10;{&#10; configASSERT( uxCriticalNesting );&#10; uxCriticalNesting--;&#10; if( uxCriticalNesting == 0 )&#10; {&#10; portENABLE_INTERRUPTS();&#10; }&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="4任务调度"&gt;&lt;a href="#4%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6" class="header-anchor"&gt;&lt;/a&gt;4.任务调度&#13;&#10;&lt;/h1&gt;</description></item></channel></rss>