FreeRTOS 是个轻量级的实时操作系统,功能还不错。最近花了些时间研究了一下,代码写的很严谨,值得学习。鉴于国内介绍资料非常少,因此,准备做一个系列笔记,将其主要功能代码做个注释,主要是方便自己查找。也希望能给对这个操作系统感兴趣的国内同行一点参考。
xTaskGenericCreate 用来建立一个任务,实际上 xTaskCreate 也是对 xTaskGenericCreate 的包装。
下面的代码有些删减,将一些非主线的内容去掉了,这样更方便学习。
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
{
signed portBASE_TYPE xReturn;
tskTCB * pxNewTCB;
configASSERT( pxTaskCode );
configASSERT( ( uxPriority < configMAX_PRIORITIES ) );
/* 为TCB 和 堆栈分配空间 */
pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
if( pxNewTCB != NULL ) /* 如果 TCB 空间分配成功 */
{
portSTACK_TYPE *pxTopOfStack;
/* 计算堆栈栈顶的位置 */
#if( portSTACK_GROWTH < 0 )/* portSTACK_GROWTH == -1 对应倒生堆栈,比如 x86 */
{
pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 ); /* pxStack 指向堆栈的起始地址 */
pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) );/* 堆栈有地址对齐的要求 */
}
#else
{
pxTopOfStack = pxNewTCB->pxStack;/* 新建的堆栈是空的,所以堆栈的栈顶就在起始地址处(正生堆栈)*/
/* Check the alignment of the stack buffer is correct. */
/* 如果要做堆栈检查,就要知道堆栈的另一端界限在哪里 */
pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
}
#endif
/* 设置 TCB 的各个部分 */
prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
/* 初始化堆栈,使得任务好像被中断函数中断了一样,中断返回地址就是任务的首地址,与 uC/OS-II 的方式相同 */
if( ( void * ) pxCreatedTask != NULL )
{
/* 返回任务的句柄 */
*pxCreatedTask = ( xTaskHandle ) pxNewTCB;
}
taskENTER_CRITICAL();
{
uxCurrentNumberOfTasks++;
if( pxCurrentTCB == NULL )
{
/* 如果没有其他任务,这个任务必然就成为当前任务,好像只有第一个任务会遇到这个情况阿?! */
pxCurrentTCB = pxNewTCB;
if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
{
/* 如果这是第一个任务,就做初始化工作,uC/OS-II 有单独的初始化函数,FreeRTOS 没有,初始化工作放在这里 */
prvInitialiseTaskLists();
}
}
else
{
if( xSchedulerRunning == pdFALSE )
{
if( pxCurrentTCB->uxPriority <= uxPriority )
{
pxCurrentTCB = pxNewTCB; /*新任务优先级高*/
}
}
}
if( pxNewTCB->uxPriority > uxTopUsedPriority )
{
uxTopUsedPriority = pxNewTCB->uxPriority;
}
uxTaskNumber++;
prvAddTaskToReadyQueue( pxNewTCB );/* 将任务加入到 Ready 队列 */
xReturn = pdPASS;
traceTASK_CREATE( pxNewTCB );
}
taskEXIT_CRITICAL();
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
traceTASK_CREATE_FAILED();
}
if( xReturn == pdPASS )
{
if( xSchedulerRunning != pdFALSE )
{
if( pxCurrentTCB->uxPriority < uxPriority )
{
portYIELD_WITHIN_API(); /* 新任务比当前正在运行的任务优先级高,因此要做任务调度 */
}
}
}
return xReturn;
}