流程:
osThreadId_t wirelessTransTaskHandle;
const osThreadAttr_t wirelessTransTaskAttri =
{
.name = "wirelessTransTask",
.priority = (osPriority_t) osPriorityNormal6,
.stack_size = 1024*64
};
wirelessTransTaskHandle = osThreadNew(wirelessTransTask, NULL, &wirelessTransTaskAttri);
// cmsis_rtos_v2/cmsis_os2.c
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) {
char empty;
const char *name;
uint32_t stack;
TaskHandle_t hTask;
UBaseType_t prio;
int32_t mem;
hTask = NULL;
if (!IS_IRQ() && (func != NULL)) {
stack = configMINIMAL_STACK_SIZE; // 配置的最小栈
prio = (UBaseType_t)osPriorityNormal; // 先分配一个优先级
empty = '\0';
name = ∅ // 初始化指针
mem = -1;
if (attr != NULL) {
if (attr->name != NULL) {
name = attr->name; // 新建任务名
}
if (attr->priority != osPriorityNone) {
prio = (UBaseType_t)attr->priority; // 新建任务优先级
}
// 优先级检查,不能小于最小优先级,不能高于最大优先级, 及 joinable mode 检查
if ((prio < osPriorityIdle) || (prio > osPriorityISR) || ((attr->attr_bits & osThreadJoinable) == osThreadJoinable)) {
return (NULL);
}
if (attr->stack_size > 0U) {
/* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports. */
/* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */
stack = attr->stack_size / sizeof(StackType_t); // 堆栈大小应为4字节对齐
}
if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTask_t)) &&
(attr->stack_mem != NULL) && (attr->stack_size > 0U)) {
mem = 1; // 没有对这些变量初始化,即使用静态内存分配
}
else {
if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) && (attr->stack_mem == NULL)) {
mem = 0; // 采用动态内存分配
}
}
}
else {
mem = 0;
}
// 任务创建
if (mem == 1) { // 静态内存分配
hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t *)attr->stack_mem,
(StaticTask_t *)attr->cb_mem);
}
else {
if (mem == 0) { // 动态内存分配
if (xTaskCreate ((TaskFunction_t)func, name, (uint16_t)stack, argument, prio, &hTask) != pdPASS) {
hTask = NULL;
}
}
}
}
return ((osThreadId_t)hTask);
}
// task.c
此函数中宏定义 portSTACK_GROWTH 是为了区分堆栈的生成方式,它可以分为递增堆栈(Ascending Stack)和递减堆栈(Decending Stack)。当堆栈由低地址向高地址生成时,称为递增堆栈;当堆栈由高地址向低地址生成时,称为递减堆栈。
这样就有4种类型的堆栈工作方式:
1.满递增堆栈: 堆栈指针指向最后压入的数据,且由低地址向高地址生成.
2.满递减堆栈: 堆栈指针指向最后压入的数据,且由高地址向低地址生成.
3.空递增堆栈: 堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成.
4.空递减堆栈: 堆栈指针指向下一个将要放放数据的空位轩,且由高地址向低地址生成.
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
TCB_t *pxNewTCB;
BaseType_t xReturn;
/* If the stack grows down then allocate the stack then the TCB so the stack
does not grow into the TCB. Likewise if the stack grows up then allocate
the TCB then the stack. */
#if( portSTACK_GROWTH > 0 )
{
/* Allocate space for the TCB. Where the memory comes from depends on
the implementation of the port malloc function and whether or not static
allocation is being used. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL )
{
/* Allocate space for the stack used by the task being created.
The base of the stack memory stored in the TCB so the task can
be deleted later if required. */
pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxNewTCB->pxStack == NULL )
{
/* Could not allocate the stack. Delete the allocated TCB. */
vPortFree( pxNewTCB );
pxNewTCB = NULL;
}
}
}
#else /* portSTACK_GROWTH */
{
StackType_t *pxStack;
/* Allocate space for the stack used by the task being created. */
pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxStack != NULL )
{
/* Allocate space for the TCB. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
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. */
vPortFree( pxStack );
}
}
else
{
pxNewTCB = NULL;
}
}
#endif /* portSTACK_GROWTH */
if( pxNewTCB != NULL )
{
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
{
/* Tasks can be created statically or dynamically, so note this
task was created dynamically in case it is later deleted. */
pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); // 初始化新任务
prvAddNewTaskToReadyList( pxNewTCB ); // 将新任务加入优先安排就绪任务列表
xReturn = pdPASS;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}