FreeRTOS一些知识点

第一章 调度器
vTaskStartScheduler( void ):
1、创建prvIdleTask空闲任务;
2、若空闲任务创建成功,则创建xTimerCreateTimerTask时间任务;
3、若时间任务创建成功,则:
   1)关中断;
   2)调用xPortStartScheduler()开启调度器。
       xPortStartScheduler():
      (1)Make PendSV and SysTick the lowest priority interrupts.
      (2)开启定时器中断,prvSetupTimerInterrupt();
      (3)运行第一个任务vPortStartFirstTask()。
//
第二章 任务创建、删除、挂起、恢复

任务创建过程,xTaskCreate( TaskFunction_t pxTaskCode,
                         const char * const pcName,
                         const uint16_t usStackDepth,
                         void * const pvParameters,
                         UBaseType_t uxPriority,
                         TaskHandle_t * const pxCreatedTask )
1、创建任务参数有任务函数、任务名称、堆栈大小、任务函数参数、任务优先级、任务句柄六个参数;
2、根据堆栈增长方向来决定TCB、堆栈前后顺序:
   1)向上增长,先TCB后堆栈;
   2)向下增长,先堆栈后TCB。
3、调用prvInitialiseNewTask,初始化任务:
   1)参数有任务函数、任务名称、堆栈大小、任务参数、任务优先级、任务句柄、任务控制块和xRegions;
   2)根据堆栈增长方向来决定任务分配堆栈的Top:
     (1)向上增长,pxTopOfStack = pxNewTCB->pxStack;
     (2)向下增长,pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 )。
   3)赋值任务名称;
   4)设置任务优先级;
   5)初始化xStateListItem;
   6)初始化xEventListItem;
   7)xStateListItem指定所有者;
   8)按优先级大小排列xEventListItem,并指定其所有者;
   9)调用pxPortInitialiseStack函数,初始化栈顶信息,以便后面任务运行;
   10)把任务控制块赋值给任务句柄。
4、调用prvAddNewTaskToReadyList,加入ready任务列表:
   1)进入保护区,taskENTER_CRITICAL();
   2)uxCurrentNumberOfTasks++;
   3)如果当前运行控制块为NULL,则把当前创建的任务控制赋值给它;然后初始化prvInitialiseTaskLists();
   4)如果xSchedulerRunning为pdFALSE,确保最高优先级为当前任务;
   5)uxTaskNumber++;
   6)prvAddTaskToReadyList( pxNewTCB )添加到ready任务表;
       prvAddTaskToReadyList:
      (1)确保优先级高的排在前面;
      (2)vListInsertEnd根据优先级插入Readylist列表。
   7)taskEXIT_CRITICAL()退出保护区;
   8)若xSchedulerRunning != pdFALSE,新创建任务优先级比当前运行任务搞,调用taskYIELD_IF_USING_PREEMPTION()触发任务切换。

任务删除,vTaskDelete( TaskHandle_t xTaskToDelete )
1、传入参数只有需要删除的任务句柄,也就是TCB;
2、taskENTER_CRITICAL()进入保护区;
3、xTaskToDelete若为NULL,则删除当前运行任务;
4、uxListRemove( &( pxTCB->xStateListItem ),移除任务TCB中的状态列表项;
5、判断pxTCB->xEventListItem的pvContainer 是否为NULL,若不是NULL,则uxListRemove( &( pxTCB->xEventListItem ) )移除事件列表项;
6、uxTaskNumber++;
7、若要删除当前运行任务本身,vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) )把任务状态列表项插入等待
   终止的列表pxIndex索引指向列表项之前,++uxDeletedTasksWaitingCleanUp;;
   若不是删除当前运行任务本身,--uxCurrentNumberOfTasks,prvDeleteTCB( pxTCB )释放TCB,prvResetNextTaskUnblockTime();
8、taskEXIT_CRITICAL()退出保护区;
9、若调度器未被挂起且删除当前运行任务,则调用portYIELD_WITHIN_API(),触发一次任务切换。


任务挂起,vTaskSuspend( TaskHandle_t xTaskToSuspend )
1、传入参数只有需要删除的任务句柄,也就是TCB;
2、taskENTER_CRITICAL();
3、调用prvGetTCBFromHandle()获取句柄,若传入参数为NULL,则获取正在运行的任务句柄;
4、调用uxListRemove()从任务列表中移除;
5、如果该任务在等待事件,调用uxListRemove(),从事件列表中移除;
6、调用vListInsertEnd()把被删除的状态列表插入xSuspendedTaskList;
7、taskEXIT_CRITICAL();
8、如果调度器未被挂起,在临界区,调用prvResetNextTaskUnblockTime(),复位解除阻塞时间;
9、当删除的是当前运行任务,且调度器未被挂起,调用portYIELD_WITHIN_API()强制任务切换;当删除的是当前运行任务,且调度器挂起,若未有任务
进入就绪状态则pxCurrentTCB = NULL,若还有任务就绪,调用vTaskSwitchContext()。

任务恢复,vTaskResume( TaskHandle_t xTaskToResume )
1、传入的TCB不为NULL且不是当前运行任务;
2、taskENTER_CRITICAL();
3、调用prvTaskIsTaskSuspended( pxTCB )判断是否为挂起任务,如果是挂起路网,调用uxListRemove()从挂起列表移除,调用prvAddTaskToReadyList()
添加到任务就绪表中;
4、如果恢复任务优先级比当前运行任务高,则调用taskYIELD_IF_USING_PREEMPTION()进行一次任务切换。


第三章 任务控制块、任务堆栈
1、任务控制块(TCB_t),每个任务需要储存的一些属性集合,基本成员如下:
   1)pxTopOfStack,栈顶指针;
   2)xStateListItem,任务状态列表项,有就绪、阻塞、挂起;
   3)xEventListItem,事件列表项;
   4)uxPriority,优先级;
   5)pxStack,堆栈指针;
   6)pcTaskName,任务名称。
2、任务堆栈:保存任务运行状态的堆栈。
//
第四章 列表和列表项
1、列表,一种数据结构,用来跟踪FreeRTOS中的任务,主要成员如下:
   1)uxNumberOfItems,存储的列表项数量;
   2)pxIndex,当前列表的索引号;
   3)xListEnd,mini列表项,用在列表末尾。
2、列表项,存储具体信息功能,主要成员如下:
   1)xItemValue,用来按降序排列;
   2)pxNext,指向下一个列表项;
   3)pxPrevious,指向前一个列表项;
   4)pvOwner,这个列表的所有者,指向TCB结构体;
   5)pvContainer,归属哪个列表,根据这个可知道列表是在就绪列表还是阻塞列表或者其她列表中,没有时未null。
3、mini列表项,列表项的缩减版,主要成员如下:
   1)xItemValue,用来按降序排列;
   2)pxNext,指向下一个列表项;
   3)pxPrevious,指向前一个列表项。
4、列表初始化,vListInitialise过程如下:
   1)列表指针pxIndex指向xListEnd;
   2)xListEnd.xItemValue设置成最高,确保只有xListEnd;
   3)xListEnd.pxNext和xListEnd.pxPrevious都指向自己。
   4)设置列表两头值。
5、列表项操作情况,如下:
  (一)初始化,vListInitialiseItem过程如下:
        1)列表项的pvContainer(所在运行列表指向)设为NULL;
        2)设置列表两头值
  (二)插入列表项,vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )过程如下:
        1)列表和列表项完整性检查;
        2)根据pxNewListItem->xItemValue值降序寻找插入位置;
        3)插入列表项;
        4)pxNewListItem->pvContainer,指向插入的列表。
        5)列表数量加1。
  (三)末尾插入列表项,vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )过程如下:
        1)插入pxList->pxIndex之前,也就是最后一个。
        2)pxNewListItem->pvContainer,指向插入的列表。
        3)列表数量加1。
  (四)删除列表项,uxListRemove( ListItem_t * const pxItemToRemove )过程如下:
        1)找到列表项所在列表pxItemToRemove->pvContainer;
        2)删除列表项;
        3)确保pxList->pxIndex指向有效列表项;
        4)被删除的列表项pxItemToRemove->pvContainer 赋值NULL;
        5)列表数量uxNumberOfItems减一。
  (五)遍历列表,listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )过程如下:
        1)列表pxIndex指向下个列表项;
        2)如果为最后结尾列表项,则pxIndex指向起始列表项;
        3)获取新指向的列表项的pvOwner,即TCB。
/
第五章 内存管理
1、内存碎片问题
   多次申请释放操作后,内存被分割成若干小碎片,随着程序运行,可能内存不够导致程序奔溃。
2、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值