1901_野火FreeRTOS教程之任务链表以及调度部分阅读

全部学习汇总: g_FreeRTOS: FreeRTOS学习笔记 (gitee.com)

这部分的内容,感觉直接对着代码工程梳理会好一些。教材基本上是看了一遍,先把这部分描述的框架整理一下。

/* 初始化任务相关的列表 */
void prvInitialiseTaskLists( void )
{
    UBaseType_t uxPriority;

    for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
    {
        vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
    }
}

首先是任务就绪链表的初始化,这个继续链表是按照优先级来分的。每一个优先级都会有一个任务调度链表。而使用之前,链表需要进行初始化。这部分主要还是之前所整理的链表部分的基本操作。通过这部分的代码分析看,其实如果是要让自己的系统资源占用更优一些,尽量按照自己真正的需求来配置优先级。

int main(void)
{
    printf("start simulation...\n");

    prvInitialiseTaskLists();

    /* 创建任务 */
    Task1_Handle = xTaskCreateStatic((TaskFunction_t)Task1_Entry, /* 任务入口 */
                                     (char *)"Task1",             /* 任务名称,字符串形式 */
                                     (uint32_t)TASK1_STACK_SIZE,  /* 任务栈大小,单位为字 */
                                     (void *)NULL,                /* 任务形参 */
                                     (StackType_t *)Task1Stack,   /* 任务栈起始地址 */
                                     (TCB_t *)&Task1TCB);         /* 任务控制块 */

    /* 将任务添加到就绪列表 */
    vListInsertEnd(&(pxReadyTasksLists[1]), &(((TCB_t *)(&Task1TCB))->xStateListItem));

    Task2_Handle = xTaskCreateStatic((TaskFunction_t)Task2_Entry, /* 任务入口 */
                                     (char *)"Task2",             /* 任务名称,字符串形式 */
                                     (uint32_t)TASK2_STACK_SIZE,  /* 任务栈大小,单位为字 */
                                     (void *)NULL,                /* 任务形参 */
                                     (StackType_t *)Task2Stack,   /* 任务栈起始地址 */
                                     (TCB_t *)&Task2TCB);         /* 任务控制块 */
    /* 将任务添加到就绪列表 */
    vListInsertEnd(&(pxReadyTasksLists[2]), &(((TCB_t *)(&Task2TCB))->xStateListItem));

    /* 启动调度器,开始多任务调度,启动成功则不返回 */
    vTaskStartScheduler();

    for (;;)
    {
        /* no code */
    }

    return 0;
}

接下来的处理,就是创建任务然后把任务关联到对应的链表中。这里是直接指定了对应的链表信息。而任务创建所实现的功能,之前已经分析过,主要是做了一个TCB的信息准备。之后,启动了调度器开始进行调度。

这里有一个任务控制块的参数处理有一点复杂,主要是因为C语言的写法有不同的表达方式。我修改了一个自我感觉更容易读懂的版本如下:

1901_野火FreeRTOS教程之任务链表以及调度部分阅读_链表

可以实现同样的效果,具体的运行效果可以从打印的信息看到。

1901_野火FreeRTOS教程之任务链表以及调度部分阅读_任务栈_02

上面是运行的效果。

1901_野火FreeRTOS教程之任务链表以及调度部分阅读_javascript_03

代码中,我还修改了堆栈的大小。因为我在调试的时候加了一个printf,这个耗费的内存要大一些。

1901_野火FreeRTOS教程之任务链表以及调度部分阅读_javascript_04

任务调度的第一个任务是指定的。

1901_野火FreeRTOS教程之任务链表以及调度部分阅读_链表_05

另外就是现在任务实体的形式,现在是这样子。多了一个任务切换,现在的代码堆叠这么使用也是情理之中。

至于MCU内核相关的一些部分的整理以及分档的对应解读,后面单独拆分出来单独看。这一次的整理基本就这些。