最近学习白问网韦东山老师在B站开源的freeRTOS课程,网址:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili和7天物联网训练营【第2期】7天物联网智能家居实战训练营
在学习过程中按照韦老师的方法分析了下freeRTOS源码,如果有不对的地方请指证。
vTaskDelay源码分析,基于cubemx生成的freeRTOS工程。
void vTaskDelay( const TickType_t xTicksToDelay )
{
//xAlreadyYielded:已经调度的状态
//初始赋值为0
BaseType_t xAlreadyYielded = pdFALSE;
/* 延时周期是否大于0,不大于0,就不应该调度 */
if( xTicksToDelay > ( TickType_t ) 0U )
{
configASSERT( uxSchedulerSuspended == 0 );
//1、挂起调度器
vTaskSuspendAll();
{
traceTASK_DELAY();
/* 1、添加任务到延时列表中
2、需要传入两个参数
2.1、xTicksToDelay:延时周期
2.2、pdFALSE:状态值为0
*/
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
}
//恢复调度器,这个调度器是有返回值的,这返回值,表示在恢复调度器
的时候,是否已经进行了任务切换
xAlreadyYielded = xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* xAlreadyYielded 等于FALSE,代表在恢复调度器的时候,没有进行任务切换 */
if( xAlreadyYielded == pdFALSE )
{
//调用了任务切换:内部就是触发PendSV异常
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
//添加任务到延时列表中
//传入两个参数
//xTicksToWait:延时周期
//xCanBlockIndefinitely :延时的确定状态
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
{
//延时周期----下次唤醒的时间
TickType_t xTimeToWake;
//xTickCount为系统节拍值 全局的,进行一次获取
const TickType_t xConstTickCount = xTickCount;
/* 把当前任务从就绪列表中移除 */
if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
//是否使用了任务挂起的功能
#if ( INCLUDE_vTaskSuspend == 1 )
{
//portMAX_DELAY = 0XFFFFFFFF 表示延时是一直持续的,也就是让任务一直阻塞
if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
{
/* 把任务添加到,挂起列表中去*/
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
/* 先去计算,下次唤醒的tick值 */
xTimeToWake = xConstTickCount + xTicksToWait;
/* 每个任务控制块里,状态列表都有一个延时值:value
这个value就是任务延时周期,在systick里面,进行比较,是否到达
*/
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
//判断下次延时周期,是否小于系统节拍值,那就证明定时已经溢出
if( xTimeToWake < xConstTickCount )
{
/* 溢出,就把任务,添加到延时溢出列表里 */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
/* 没有溢出,把任务添加到延时列表中,让内核进行处理 */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
/*还要去更新系统时间片,因为系统时间片永远保存最小的延时周期 */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* 计算下次唤醒的系统节拍值 */
xTimeToWake = xConstTickCount + xTicksToWait;
/* 赋值到任务控制块里 */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
if( xTimeToWake < xConstTickCount )
{
/* 溢出,添加到延时溢出列表中 */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
/* 没有溢出,添加到延时列表中 */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
/*更新时间片 */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
( void ) xCanBlockIndefinitely;
}
#endif /* INCLUDE_vTaskSuspend */
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)