FreeRTOS 初始上下文切换
FreeRTOS initial context switch
我正在尝试理解 freeRTOS 上一个简单的 2 任务模型的工作流程。为清楚起见添加伪代码,
Task_A
void Task_A( void *pvParameters )
{
const char *pcTaskName = "Task_A is running\r\n";
for( ;; )
{
vPrintString( pcTaskName );
/* Delay for a period. */
vTaskDelay( 250 / portTICK_RATE_MS );
}
}
Task_B
void Task_B( void *pvParameters )
{
const char *pcTaskName = "Task_B is running\r\n";
volatile unsigned long ul;
for( ;; )
{
vPrintString( pcTaskName );
/* Delay for a period. */
vTaskDelay( 250 / portTICK_RATE_MS );
}
}
主要
int main( void )
{
xTaskCreate( Task_A, "Task 1", 1000, NULL, 1, NULL );
xTaskCreate( Task_B, "Task 2", 1000, NULL, 1, NULL );
/* Start the scheduler so the tasks start executing. */
vTaskStartScheduler();
for( ;; );
}
假设两个任务,比如 Task_A 和 Task_B 都在主函数中创建,将调用调度程序(成功创建所有任务)。如果在创建任务之前未调用调度程序,将如何执行对调度程序的调用?或者简单地说,当执行从 main 开始时,是什么导致控制从 Task_A 和 Task_B 出来,以便稍后调用调度程序?如果我的理解有缺陷,请纠正我。
任务在创建时并未开始执行。创建任务只是将调度程序需要了解的有关任务的数据结构和信息放置到位。任务不会开始执行,直到调度程序 运行 成为其中之一。
在您的示例中,main
正在执行。它调用构建和初始化任务数据结构的任务创建例程。它不是 运行 任务,而是 return 到 main
。然后 main
再次调用任务创建例程,它 return 再次变为 main
。最后 main
调用调度程序,调度程序选择准备好 运行 的最高优先级任务并开始执行该任务。调度程序不会 return 到 main
。
第一个 main 启动 executing.It 调用 xTaskCreate,它只会创建任务 1(处于就绪状态),return 到 main,它再次调用 xTaskCreate,它只会创建任务 2 (在就绪状态)和 returns.After 执行 vTaskStartScheduler(),调度程序将根据优先级(选择的调度算法)调度这两个任务。最高优先级的任务将首先从就绪状态进入 运行 状态并开始执行在调用 xTaskCreate 时作为参数传递的任务函数(TaskA 或 TaskB)。
任务在创建时不会开始执行,但您可以在创建后立即处理其 TaskHandle_t 指针,无论调度程序是否为 运行。为此,“*TaskHandle_t * const 变量”必须作为 xTaskCreate 函数的第 6 个参数传递。
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
pxCreatedTask Used to pass back a handle by which the created task can be referenced.
我正在尝试理解 freeRTOS 上一个简单的 2 任务模型的工作流程。为清楚起见添加伪代码,
Task_A
void Task_A( void *pvParameters )
{
const char *pcTaskName = "Task_A is running\r\n";
for( ;; )
{
vPrintString( pcTaskName );
/* Delay for a period. */
vTaskDelay( 250 / portTICK_RATE_MS );
}
}
Task_B
void Task_B( void *pvParameters )
{
const char *pcTaskName = "Task_B is running\r\n";
volatile unsigned long ul;
for( ;; )
{
vPrintString( pcTaskName );
/* Delay for a period. */
vTaskDelay( 250 / portTICK_RATE_MS );
}
}
主要
int main( void )
{
xTaskCreate( Task_A, "Task 1", 1000, NULL, 1, NULL );
xTaskCreate( Task_B, "Task 2", 1000, NULL, 1, NULL );
/* Start the scheduler so the tasks start executing. */
vTaskStartScheduler();
for( ;; );
}
假设两个任务,比如 Task_A 和 Task_B 都在主函数中创建,将调用调度程序(成功创建所有任务)。如果在创建任务之前未调用调度程序,将如何执行对调度程序的调用?或者简单地说,当执行从 main 开始时,是什么导致控制从 Task_A 和 Task_B 出来,以便稍后调用调度程序?如果我的理解有缺陷,请纠正我。
任务在创建时并未开始执行。创建任务只是将调度程序需要了解的有关任务的数据结构和信息放置到位。任务不会开始执行,直到调度程序 运行 成为其中之一。
在您的示例中,main
正在执行。它调用构建和初始化任务数据结构的任务创建例程。它不是 运行 任务,而是 return 到 main
。然后 main
再次调用任务创建例程,它 return 再次变为 main
。最后 main
调用调度程序,调度程序选择准备好 运行 的最高优先级任务并开始执行该任务。调度程序不会 return 到 main
。
第一个 main 启动 executing.It 调用 xTaskCreate,它只会创建任务 1(处于就绪状态),return 到 main,它再次调用 xTaskCreate,它只会创建任务 2 (在就绪状态)和 returns.After 执行 vTaskStartScheduler(),调度程序将根据优先级(选择的调度算法)调度这两个任务。最高优先级的任务将首先从就绪状态进入 运行 状态并开始执行在调用 xTaskCreate 时作为参数传递的任务函数(TaskA 或 TaskB)。
任务在创建时不会开始执行,但您可以在创建后立即处理其 TaskHandle_t 指针,无论调度程序是否为 运行。为此,“*TaskHandle_t * const 变量”必须作为 xTaskCreate 函数的第 6 个参数传递。
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
pxCreatedTask Used to pass back a handle by which the created task can be referenced.