Freertos 创建任务(动态)

 1.函数指针,即任务函数的名称

2.任务名称是字符创

3.栈的大小

4.参数(放在R0寄存器里)

5.任务的优先级

6.任务句柄(传入的是指针)

Freertos 中portSTACK_GROWTH>0表明栈是向上增长的,arm是向下增长的,所以进入else

pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); 

分配栈的空间

pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );//指向低地址

分配任务控制块的空间

pxNewTCB->pxStack = pxStack;

任务控制块的pxStack指向分配的空间

 分配栈的大小,并将起始地址存入TCB.

这一点和一个结构体中一个指针指向一个空间时,需要先分配是一样的。

给任务控制块分配空间(回传给任务句柄) 。

前面分配的栈空间,

 初始化任务。

1.函数指针

2.函数名称。//字符串

3.栈大小

4.任务优先级

5.任务句柄

6.任务控制块

7.

        pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );

        pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); // 进行字节对齐,2位对齐,就是将最后一位清零,8位对齐就是将末七位清零。

获取栈顶地址,pxTopOfStack的地址为栈的高地址,随着入栈而减小,指向最后入栈的,所以也就是未入栈时的高地址

pxStack为栈的起始地址,低地址,地址是不变的,一般用于栈溢出检测(没看到在哪有检测环节)。

 TCB记录任务的优先级

 

初始化TCB的两个链表

 

 刚创建的任务还没有放入就绪链表,Container(用于指定该列表项属于哪一个列表)指向就绪链表(等)

 

展开形式

#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )      ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )

能够从任务控制块中得信息(我也不懂),设置该任务控制块的列表项属于该任务控制块

 事件链表是根据优先级设置链表项的值的,优先级越高(号大的优先级高),值越大。

(应该是在插入列表项的时候用到)

 任务句柄会获得任务控制块,这样就可以通过任务句柄控制任务

 新创建的任务默认是就绪态

 目前所有的任务(初始值为0)

当前是否有任务运行,CurrentTCB是全局变量。

假设没有

这个新任务就是当前任务

如果当前任务是第一个任务,执行下面的初始化列表。

prvInitialiseTaskLists();//见解析一

 

 任务总量加一(尚不明白和当前任务数量的区别

 加入就绪链表

 是加在就绪链表最后的。

就绪链表根据有限级分成几个 

 

 会指明任务状态(就绪,阻塞等)

 

每一个链表都有链表指针,指示当前的链表的第一个列表项。(此时的Index就是一个列表项)

根据传入的指针,pxList就是就绪链表。

 将任务的状态链表插入当前链表项的后面。(就是链表的最后)。

    pxIndex->pxPrevious->pxNext = pxNewListItem;

    pxIndex->pxPrevious = pxNewListItem;

    /* Remember which list the item is in. */

    pxNewListItem->pvContainer = ( void * ) pxList;

解析:初始化栈。

pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack,栈顶

pxTaskCode,函数指针

pvParameters );参数

1264_FreeRTOS任务的初始化以及堆栈初始化处理分析_堆栈模型的初始化-CSDN博客

StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )

{

    /* Simulate the stack frame as it would be created by a context switch

    interrupt. */

//创建的任务可能不会被立即执行,所以需要模拟任务是被中断了的,所以需要将中断需要入栈的寄存器入栈,来模拟中断

    pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */

    *pxTopOfStack = portINITIAL_XPSR;   /* xPSR */

    pxTopOfStack--;

    *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;    /* PC */

    pxTopOfStack--;

    *pxTopOfStack = ( StackType_t ) prvTaskExitError;   /* LR */

    pxTopOfStack -= 5;  /* R12, R3, R2 and R1. */

    *pxTopOfStack = ( StackType_t ) pvParameters;   /* R0 */

    pxTopOfStack -= 8;  /* R11, R10, R9, R8, R7, R6, R5 and R4. */

    return pxTopOfStack;

}

列表结构体

typedef struct xLIST

{

    listFIRST_LIST_INTEGRITY_CHECK_VALUE                /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */

    configLIST_VOLATILE UBaseType_t uxNumberOfItems;

    ListItem_t * configLIST_VOLATILE pxIndex;           /*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */

    MiniListItem_t xListEnd;                            /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */

    listSECOND_LIST_INTEGRITY_CHECK_VALUE               /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */

} List_t;

见解析一:static void prvInitialiseTaskLists( void )

{

UBaseType_t uxPriority;

    for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )

    {

        vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );//pxReadyTasksLists[ uxPriority ]是一个列表结构体数组,根据优先级不同,有不同的列表。关于vListInitialise()见解析二

    }

    vListInitialise( &xDelayedTaskList1 );//延时列表

    vListInitialise( &xDelayedTaskList2 );//延时列表溢出时保存

    vListInitialise( &xPendingReadyList );

    #if ( INCLUDE_vTaskDelete == 1 )

    {

        vListInitialise( &xTasksWaitingTermination );

    }

    #endif /* INCLUDE_vTaskDelete */

    #if ( INCLUDE_vTaskSuspend == 1 )

    {

        vListInitialise( &xSuspendedTaskList );

    }

    #endif /* INCLUDE_vTaskSuspend */

    /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList

    using list2. */

    pxDelayedTaskList = &xDelayedTaskList1;//这是一个列表指针,均为全局变量

    pxOverflowDelayedTaskList = &xDelayedTaskList2;//这是一个列表指针,均为全局变量

}

解析二:

void vListInitialise( List_t * const pxList )

{

    /* The list structure contains a list item which is used to mark the

    end of the list.  To initialise the list the list end is inserted

    as the only list entry. */

    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );           /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */(list end 代表列表尾部)pxIndex是用来遍历列表的。列表中的 pxIndex 成员变量是用来遍历列表的, pxIndex 所指向的列表项就是要遍历的开始列表项,

    /* The list end value is the highest possible value in the list to

    ensure it remains at the end of the list. */

    pxList->xListEnd.xItemValue = portMAX_DELAY;(列表项插入时,根据值来排序。值大的在后)

    /* The list end next and previous pointers point to itself so we know

    when the list is empty. */

空列表时的指向

    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );   /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */

    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */

    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

    /* Write known values into the list if

    configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */

    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );

    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );

}

上方的初始归结为一个图表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值