(第20-22讲)STM32F4单片机,FreeRTOS列表和列表项API函数讲解【视频笔记、代码讲解、正点原子】【原创】


🔴🟡🟢其他文章链接,独家吐血整理

【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】
(第1-8讲)STM32F4单片机,FreeRTOS基础知识总结【视频笔记、代码讲解】【正点原子】【原创】
(第9-10讲)STM32F4单片机,FreeRTOS任务创建和删除(动态方法)【视频笔记、代码讲解】【正点原子】【原创】
(第12讲)STM32F4单片机,FreeRTOS任务创建和删除(静态方法)【视频笔记、代码讲解】【正点原子】【原创】
(第13-14讲)STM32F4单片机,FreeRTOS任务挂起和恢复【视频笔记、代码讲解】【正点原子】【原创】
(第16-17讲)STM32F4单片机,FreeRTOS中断管理简介【视频笔记、代码讲解】【正点原子】【原创】
(第18-19讲)32单片机,FreeRTOS临界段代码保护、任务调度器的挂起和恢复【视频笔记、代码讲解】【原创】
(第20-22讲)STM32F4单片机,FreeRTOS列表和列表项API函数讲解【视频笔记、代码讲解、正点原子】【原创】
(第34-36讲)FreeRTOS消息队列知识汇总【B站UP、硬件家园、普中科技、正点原子】【视频笔记】【原创】
(第40-44讲)STM32F4单片机,FreeRTOS信号量【二值、计数、翻转、互斥】【代码讲解】【正点原子】【原创】

1、❤systick中断、pendsv中断、svc异常、时间片调度

看下文链接

【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】

看上文链接

2、视频笔记

1、2024温故知新(纯文字)

根据前面的知识可知,列表是存放任务的,列表有三种就绪、阻塞、挂起,没有运行态列表,列表的优先级为0-31,一个列表中可以存放多个任务,而任务是有优先级的,比如2优先级的任务存放在列表中,列表中的列表项就是任务,多个列表项之间通过链表连接(双向循环链表)
rtos中任务的创建和删除是无时无刻存在的,因此链表这种数据结构很好地实现任务的管理并且实时
待补充,这块太难了。。。

在这里插入图片描述
1、列表、列表项、末尾列表项=mini列表项=迷你列表项都是结构体。
2、列表包含列表项,也包含mini列表项
在这里插入图片描述
1、先上后下,即上一个指针,下一个指针
2、升序排列,末尾列表项的数值最大,所以在最底,永远是它首先指向别人(别的列表项)
3、previous指针指向最后一个插入的,next指针指向第一个插入的,双向循环链表,两个环,手拉手
4、没有列表插入的时候,列表的数值=0,index指针指向末尾列表项,末尾列表项的两个指针指向自己
在这里插入图片描述
1、列表数值变为了2
在这里插入图片描述
这个图片很能解释了,最初10->40->0xFFFFFFFF,现在30要插入进来,首先呢进入for循环,30小于0xFFFFFFFF成立,P指针指向了下一个next也就是列表项1,于是30不小于10就跳出for循环,于是找到了位置,这就是个插入算法吧

3、实验现象

在这里插入图片描述

4、代码讲解

list.h

struct xLIST;
struct xLIST_ITEM//列表项结构体
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE TickType_t xItemValue;          /*< The value being listed.  In most cases this is used to sort the list in ascending order. */
    //列表项数值,根据这个值升序进行排序
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /*< Pointer to the next ListItem_t in the list. */
    //指向下一个列表项
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
    //指向上一个列表项
    void * pvOwner;                                     /*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
    //任意类型指针,用于指向某个列表结构体
    struct xLIST * configLIST_VOLATILE pxContainer;     /*< Pointer to the list in which this list item is placed (if any). */
    //指向列表的结构体指针变量
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t;                   /* For some reason lint wants this as two separate definitions. */

struct xMINI_LIST_ITEM//mini列表项结构体
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE TickType_t xItemValue;
    //列表项数值
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;
    //指向下一个列表项
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
    //指向上一个列表项
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

/*
 * Definition of the type of queue used by the scheduler.
 */
typedef struct xLIST//列表结构体
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE      /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    volatile UBaseType_t uxNumberOfItems;
    //ulong变量=列表中的列表项数量(不包括mini列表项),用于列表项插入删除
    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 (). */
    //指向某个列表项=pxIndex=结构体指针变量
    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. */
    //mini列表项=末尾列表项=结构体变量
    listSECOND_LIST_INTEGRITY_CHECK_VALUE     /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;

list.c

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 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
    //指向末尾列表,xListEnd是mini列表项结构体变量,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;
    //末尾列表数值=最大=( TickType_t ) 0xffffffffUL
    /* 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 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
    //pxList->xListEnd.pxNext是指向结构体中的成员结构体中的结构体指针变量pxNext
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
    //也是结构体中的结构体成员中的结构体指针变量pxPrevious
    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
    //列表项数量默认为0
    /* 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 );
}
/*-----------------------------------------------------------*/

末尾列表项=mini列表项地址给了index
初值=最大
末尾列表项地址,给了自己的两个手
列表项数量=0

void vListInitialiseItem( ListItem_t * const pxItem )
{
    /* Make sure the list item is not recorded as being on a list. */
    pxItem->pxContainer = NULL;
    //列表项中的结构体指针变量为NULL
    /* Write known values into the list item if
     * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
/*-----------------------------------------------------------*/

列表项(不是mini)的容器结构体指针给了null

void vListInsert( List_t * const pxList,
                  ListItem_t * const pxNewListItem )
{
    ListItem_t * pxIterator;
    const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
    //指向的列表项结构体中的列表项数量 赋给 插入值
    //获取待插入的列表项值
    
    /* Only effective when configASSERT() is also defined, these tests may catch
     * the list data structures being overwritten in memory.  They will not catch
     * data errors caused by incorrect configuration or use of FreeRTOS. */
    listTEST_LIST_INTEGRITY( pxList );
    listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );

    /* Insert the new list item into the list, sorted in xItemValue order.
     *
     * If the list already contains a list item with the same item value then the
     * new list item should be placed after it.  This ensures that TCBs which are
     * stored in ready lists (all of which have the same xItemValue value) get a
     * share of the CPU.  However, if the xItemValue is the same as the back marker
     * the iteration loop below will not end.  Therefore the value is checked
     * first, and the algorithm slightly modified if necessary. */
    if( xValueOfInsertion == portMAX_DELAY )//如果插入的列表项的值等于最大值(极极小概率)
    {
        pxIterator = pxList->xListEnd.pxPrevious;//将末尾列表项的pxprevious的内容=列表项自身的地址给了刚定义的结构体指针
    }
    //列表项和mini列表项虽然不同(结构体变量名不同,成员也不同),但是它们中的两只手都是结构体指针,是【相同】struct类型
    //即相当于插入的列表项指向了末尾列表项,实现了末尾列表项永远处于最底端
    else
    {
        /* *** NOTE ***********************************************************
        *  If you find your application is crashing here then likely causes are
        *  listed below.  In addition see https://www.FreeRTOS.org/FAQHelp.html for
        *  more tips, and ensure configASSERT() is defined!
        *  https://www.FreeRTOS.org/a00110.html#configASSERT
        *
        *   1) Stack overflow -
        *      see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html
        *   2) Incorrect interrupt priority assignment, especially on Cortex-M
        *      parts where numerically high priority values denote low actual
        *      interrupt priorities, which can seem counter intuitive.  See
        *      https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition
        *      of configMAX_SYSCALL_INTERRUPT_PRIORITY on
        *      https://www.FreeRTOS.org/a00110.html
        *   3) Calling an API function from within a critical section or when
        *      the scheduler is suspended, or calling an API function that does
        *      not end in "FromISR" from an interrupt.
        *   4) Using a queue or semaphore before it has been initialised or
        *      before the scheduler has been started (are interrupts firing
        *      before vTaskStartScheduler() has been called?).
        *   5) If the FreeRTOS port supports interrupt nesting then ensure that
        *      the priority of the tick interrupt is at or below
        *      configMAX_SYSCALL_INTERRUPT_PRIORITY.
        **********************************************************************/

        for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
        {
            /* There is nothing to do here, just iterating to the wanted
             * insertion position. */
        }
        //列表的末尾列表项地址给刚定义的结构体指针pxi ; 数值<最大值 ; 即刚刚赋给pxi指针的末尾列表项的next再次给了pxi
        //即此时刚刚定义的结构体指针pxi指向的结构体中的next指向了末尾列表项
        
        //没懂没懂,待补充
    }

    pxNewListItem->pxNext = pxIterator->pxNext;
    pxNewListItem->pxNext->pxPrevious = pxNewListItem;
    pxNewListItem->pxPrevious = pxIterator;
    pxIterator->pxNext = pxNewListItem;

    /* Remember which list the item is in.  This allows fast removal of the
     * item later. */
    pxNewListItem->pxContainer = pxList;

    ( pxList->uxNumberOfItems )++;
}

讲解在代码中注释了

if( xValueOfInsertion == portMAX_DELAY )//如果插入的列表项的值等于最大值(极极小概率)
{
pxIterator = pxList->xListEnd.pxPrevious;//将末尾列表项自己的地址给了刚定义的结构体指针
}
//列表项和mini列表项虽然不同(结构体变量名不同,成员也不同),但是它们中的两只手都是结构体指针,是【相同】struct类型

详情请见上面的视频笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值