热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FreeRTOS开发实战_链表管理

4.1链表的特性在FreeRTOS的链表管理中,采用的是双向链表,其中链表头指针使用xLIST来表示,而链表尾部指针为xMINI_LIST_ITEM。这个链表有一个非常巧妙的设计在

4.1 链表的特性

在FreeRTOS的链表管理中,采用的是双向链表,其中链表头指针使用xLIST来表示,而链表尾部指针为xMINI_LIST_ITEM。

这个链表有一个非常巧妙的设计在于添加了两个item:

  • pvContainer,用来记录这个Item是属于哪一个链表;
  •  pvOwner,用来扩展Item,可以用来基于链表做客制化的操作;

比如我们客制化的一个链表Item

typedef struct _Rpmsg_Listener

{

      RpmsgCallbackFunction_t pxCallbackFunction;

      RpmsgSendFunction_t pxSendFunction;

      ListItem_t  xRpmsgListenerListItem;

      RpmsgEvent_t *mEvent;

}RpmsgListener_t;

 刚刚初始化表头后的链表形态如下:

FreeRTOS开发实战_链表管理

插入Item之后的链表结构如下图:

FreeRTOS开发实战_链表管理

4.1.1 数据存储

4.1.1.1 表头指针

/*

 * Definition of the type of queue used by the scheduler.

 */

typedef struct xLIST

{

        configLIST_VOLATILE UBaseType_t uxNumberOfItems;

        ListItem_t * configLIST_VOLATILE pxIndex;             /*

        MiniListItem_t xListEnd;                                             /*

} List_t;

  • l  uxNumberOfItems:记录链表的ITEM数目;
  • l  pxIndex:链表游标
  • l  xListEnd:队尾标志

4.1.1.2 链表表项

/*

 * Definition of the only type of object that a list can contain.

 */

struct xLIST_ITEM

{

        configLIST_VOLATILE TickType_t xItemValue;                  /*

        struct xLIST_ITEM * configLIST_VOLATILE pxNext;         /*

        struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;   /*

        void * pvOwner;                                                                                    /*

        void * configLIST_VOLATILE pvContainer;                                 /*

};

  • l  xItemValue:表项数值,常用于链表排序;
  • l  pxNext:指针,指向下一个;
  • l  pxPrevious:指针,指向前一个;
  • l  pvOwner:指针,常指向TCB;
  • l  pvContainer:指针,常指向链表表头。

4.2 使用链表

4.2.1 初始化链表

voidvListInitialise( List_t * const pxList )

参数:

  • pxList:链表表头指针

4.2.2 初始化表项

voidvListInitialiseItem( ListItem_t * const pxItem )

参数:

  • pxItem:链表表项

4.2.3 插入表项

voidvListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )

参数:

  •  pxList:需要插入的链表
  • pxNewListItem:链表项目

4.2.4 链表尾部插入

void vListInsertEnd(List_t * const pxList, ListItem_t * const pxNewListItem )

参数:

  • pxList:需要插入的链表
  • pxNewListItem:链表项目

4.2.5 移除表项

UBaseType_tuxListRemove( ListItem_t * const pxItemToRemove )

参数:

  • pxItemToRemove :需要移除的表项

4.2.6 其他宏定义操作

  • l  listSET_LIST_ITEM_VALUE

设置Item Value

  • l  listSET_LIST_ITEM_OWNER

设置List Owner

  • l  listCURRENT_LIST_LENGTH

当前链表的长度

  • l  listGET_LIST_ITEM_OWNER

取得链表的Owner

4.3 使用实例

 

typedef struct _Sensor_Event_

{

    Sensor mSenor;

    float values[4];

}SensorEvent_t;

/*

 * Defines the prototype to which timer callback functions must conform.

 */

typedef void (*SensorCallbackFunction_t)(SensorEvent_t * mListener);

 

typedef struct _Sensor_Listener

{

      int mSensorType;

      SensorCallbackFunction_t pxCallbackFunction;

      ListItem_t  xSensorListenerListItem;

      SensorEvent_t *mEvent;

}SensorListener_t;

 

void ap_RegisterSensorListener(int RegiterID,int mSensorType,SensorCallbackFunction_t mpxCallbackFunction,SensorEvent_t* mEvent)

{

    //Create the new Sensor Listener

    SensorListener_t *pxNewSensorListener;

    pxNewSensorListener =(SensorListener_t *)pvPortMalloc( sizeof( SensorListener_t ) );

    pxNewSensorListener->mSensorType = mSensorType;

    pxNewSensorListener->pxCallbackFunction = mpxCallbackFunction;   

    pxNewSensorListener->mEvent=mEvent;

    vListInitialiseItem( &( pxNewSensorListener->xSensorListenerListItem ) );

   

#ifdef SUPPORT_GSENSOR

    //Add the new Item to the list by the Sensor Type

    if(mSensorType == TYPE_GYROSCOPE)

    {

        listSET_LIST_ITEM_VALUE( &( pxNewSensorListener->xSensorListenerListItem ), RegiterID );

        listSET_LIST_ITEM_OWNER( &( pxNewSensorListener->xSensorListenerListItem ), pxNewSensorListener );

        vListInsert( &xGsensorList, &( pxNewSensorListener->xSensorListenerListItem ) );

    }

#endif

   PRINTF("The xGsensorList length is %d\n",listCURRENT_LIST_LENGTH(&xGsensorList));

}

 

void mw_sensor_init(void)

    //Add Listener List for Sensor Listenor

#ifdef SUPPORT_GSENSOR

    vListInitialise( &xGsensorList );

#endif

}

 

#ifdef SUPPORT_GSENSOR

//Called by the HAL_Sensor

void OnGyroSensorChangedCallBack(float Gxf, float Gyf,float Gzf)

{

    List_t * pxConstList;

    SensorListener_t* vSensorListener;

    pxCOnstList= &xGsensorList;

    pxConstList->pxIndex = pxConstList->pxIndex->pxNext;       

    while(( void * ) ( pxConstList )->pxIndex != ( void * ) &( ( pxConstList )->xListEnd ))

    {

         vSensorListener = (SensorListener_t *)listGET_LIST_ITEM_OWNER( ( pxConstList )->pxIndex );

         vSensorListener->mEvent->values[0] = Gxf;

         vSensorListener->mEvent->values[1] = Gyf;

         vSensorListener->mEvent->values[2] = Gzf;

         vSensorListener->pxCallbackFunction( ( SensorEvent_t *) vSensorListener->mEvent);

         pxConstList->pxIndex = pxConstList->pxIndex->pxNext;      

    }

}

#endif

 

BaseType_t ap_unRegisterSensorListener(int RegiterID,int mSensorType)

{

    SensorListener_t* vSensorListener;

    List_t * pxConstList;

    if(mSensorType == TYPE_GYROSCOPE)

    {

        pxCOnstList= &xGsensorList;

    }else

    {

        return pdFAIL;

    }

    while( (( pxConstList )->pxIndex->xItemValue == RegiterID)

          &&(( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )

          )

    {

          ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                                                       

    }

    if(( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )

    {

        return pdFAIL;

    }

    vSensorListener = (SensorListener_t *)listGET_LIST_ITEM_OWNER( ( pxConstList )->pxIndex );

    ( void ) uxListRemove(&(vSensorListener->xSensorListenerListItem));

    vPortFree(vSensorListener);

    return pdPASS;  

}



推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 包含phppdoerrorcode的词条 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 本文介绍了如何利用 `matplotlib` 库中的 `FuncAnimation` 类将 Python 中的动态图像保存为视频文件。通过详细解释 `FuncAnimation` 类的参数和方法,文章提供了多种实用技巧,帮助用户高效地生成高质量的动态图像视频。此外,还探讨了不同视频编码器的选择及其对输出文件质量的影响,为读者提供了全面的技术指导。 ... [详细]
  • Python中判断一个集合是否为另一集合子集的两种高效方法及其应用场景分析 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • DVWA学习笔记系列:深入理解CSRF攻击机制
    DVWA学习笔记系列:深入理解CSRF攻击机制 ... [详细]
author-avatar
燕子的世界是什么
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有