configSUPPORT_DYNAMIC_ALLOCATION; #define portSTACK_GROWTH ( -1 )也就是堆栈增长方向为高地址向低地址增长; BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, /* 任务函数 */
const char * const pcName, /* 任务名称 */
const configSTACK_DEPTH_TYPE usStackDepth, /* 任务堆栈大小 */
void * const pvParameters, /* 传入给任务函数的参数 */
UBaseType_t uxPriority, /* 任务优先级 */
TaskHandle_t * const pxCreatedTask ); /* 任务句柄 */
pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); usStackDepth 就是调用API时填入的形参,即任务堆栈大小,StackType_t 在FreeRTOS\portable\RVDS\ARM_CM3\portmacro.h中定义为uint32_t就是4字节;(usStackDepth * 4)字节,这个任务栈内存是当发生任务切换时用来储存当前任务函数中的变量和上下文信息等的,一般会申请稍大于任务函数中变量占用内存之和的量; pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );来申请TCB内存,如果申请不成功就释放申请过的任务堆栈内存,并返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;//省略其他代码
{
StackType_t * pxStack;
/* Allocate space for the stack used by the task being created. */
pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
if( pxStack != NULL ){
/* Allocate space for the TCB. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
if( pxNewTCB != NULL )
{
/* Store the stack location in the TCB. */
pxNewTCB->pxStack = pxStack;
}else{
/* The stack cannot be used as the TCB was not created. Free
* it again. */
vPortFreeStack( pxStack );
}
}else{
pxNewTCB = NULL;
}
}
//省略其他代码
可以看到FreeRTOS中包含大量指针检测,此框架在Linux中同样广泛使用:
// 这个框架在linux中也广泛使用
xxx = malloc(n);
if(xxx != NULL){
// 成功处理
}else{
// 错误处理
}
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );来初始化一个任务,这个函数是针对TCB的初始化,做了以下重要工作:
uxTaskGetStackHighWaterMark函数来获取任务堆栈的内存余量,来确定是否需要增加或减小任务堆栈,任务堆栈设置过大就浪费内存了,过小有溢出的可能,这一机制可以更方便的设置任务堆栈为合理的大小;owner//省略其他代码
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
}
#endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
/* Calculate the top of stack address. This depends on whether the stack
* grows from high memory to low (as per the 80x86) or vice versa.
* portSTACK_GROWTH is used to make the result positive or negative as required
* by the port. */
#if ( portSTACK_GROWTH < 0 )
{
pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */
/* Check the alignment of the calculated top of stack is correct. */
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
#if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
{
/* Also record the stack's high address, which may assist
* debugging. */
pxNewTCB->pxEndOfStack = pxTopOfStack;
}
#endif /* configRECORD_STACK_HIGH_ADDRESS */
}
//省略其他代码
prvAddNewTaskToReadyList( pxNewTCB );这个函数做了以下重要工作:


