全部学习汇总: 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语言的写法有不同的表达方式。我修改了一个自我感觉更容易读懂的版本如下:
可以实现同样的效果,具体的运行效果可以从打印的信息看到。
上面是运行的效果。
代码中,我还修改了堆栈的大小。因为我在调试的时候加了一个printf,这个耗费的内存要大一些。
任务调度的第一个任务是指定的。
另外就是现在任务实体的形式,现在是这样子。多了一个任务切换,现在的代码堆叠这么使用也是情理之中。
至于MCU内核相关的一些部分的整理以及分档的对应解读,后面单独拆分出来单独看。这一次的整理基本就这些。